about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml14
-rw-r--r--README.md5
-rw-r--r--src/Cargo.lock160
-rw-r--r--src/bootstrap/bin/rustc.rs15
-rw-r--r--src/bootstrap/bootstrap.py53
-rw-r--r--src/bootstrap/cc.rs14
-rw-r--r--src/bootstrap/channel.rs10
-rw-r--r--src/bootstrap/check.rs77
-rw-r--r--src/bootstrap/compile.rs41
-rw-r--r--src/bootstrap/config.rs29
-rw-r--r--src/bootstrap/dist.rs67
-rw-r--r--src/bootstrap/doc.rs18
-rw-r--r--src/bootstrap/flags.rs54
-rw-r--r--src/bootstrap/install.rs2
-rw-r--r--src/bootstrap/lib.rs130
-rw-r--r--src/bootstrap/metadata.rs2
-rw-r--r--src/bootstrap/native.rs8
-rw-r--r--src/bootstrap/sanity.rs168
-rw-r--r--src/bootstrap/step.rs134
-rw-r--r--src/bootstrap/util.rs15
-rw-r--r--src/doc/unstable-book/src/language-features/compile-error.md2
-rw-r--r--src/doc/unstable-book/src/language-features/lang-items.md6
-rw-r--r--src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md27
-rw-r--r--src/doc/unstable-book/src/library-features/iterator-for-each.md17
-rw-r--r--src/doc/unstable-book/src/library-features/more-io-inner-methods.md11
-rw-r--r--src/doc/unstable-book/src/library-features/sort-unstable.md40
-rw-r--r--src/liballoc/allocator.rs2
-rw-r--r--src/liballoc/benches/lib.rs2
-rw-r--r--src/liballoc/benches/slice.rs54
-rw-r--r--src/liballoc/fmt.rs8
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/slice.rs31
-rw-r--r--src/liballoc/string.rs8
-rw-r--r--src/liballoc/tests/slice.rs50
-rw-r--r--src/liballoc/tests/vec.rs5
-rw-r--r--src/liballoc/tests/vec_deque.rs3
-rw-r--r--src/liballoc/vec.rs13
-rw-r--r--src/liballoc_jemalloc/build.rs2
-rw-r--r--src/libcore/benches/iter.rs47
-rw-r--r--src/libcore/cmp.rs19
-rw-r--r--src/libcore/fmt/builders.rs139
-rw-r--r--src/libcore/fmt/mod.rs11
-rw-r--r--src/libcore/iter/iterator.rs47
-rw-r--r--src/libcore/iter/mod.rs6
-rw-r--r--src/libcore/iter/range.rs213
-rw-r--r--src/libcore/lib.rs10
-rw-r--r--src/libcore/macros.rs10
-rw-r--r--src/libcore/mem.rs54
-rw-r--r--src/libcore/num/f32.rs19
-rw-r--r--src/libcore/num/f64.rs17
-rw-r--r--src/libcore/panicking.rs41
-rw-r--r--src/libcore/ptr.rs84
-rw-r--r--src/libcore/slice/mod.rs6
-rw-r--r--src/libcore/slice/rotate.rs9
-rw-r--r--src/libcore/slice/sort.rs4
-rw-r--r--src/libcore/tests/iter.rs42
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/librand/lib.rs2
-rw-r--r--src/librustc/diagnostics.rs38
-rw-r--r--src/librustc/hir/lowering.rs12
-rw-r--r--src/librustc/hir/map/mod.rs66
-rw-r--r--src/librustc/hir/print.rs6
-rw-r--r--src/librustc/ich/impls_ty.rs3
-rw-r--r--src/librustc/infer/error_reporting/mod.rs44
-rw-r--r--src/librustc/infer/error_reporting/named_anon_conflict.rs199
-rw-r--r--src/librustc/infer/error_reporting/need_type_info.rs12
-rw-r--r--src/librustc/infer/mod.rs32
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/lint/context.rs65
-rw-r--r--src/librustc/middle/effect.rs28
-rw-r--r--src/librustc/middle/expr_use_visitor.rs9
-rw-r--r--src/librustc/middle/intrinsicck.rs27
-rw-r--r--src/librustc/middle/mem_categorization.rs92
-rw-r--r--src/librustc/middle/resolve_lifetime.rs3
-rw-r--r--src/librustc/session/mod.rs85
-rw-r--r--src/librustc/traits/error_reporting.rs25
-rw-r--r--src/librustc/traits/mod.rs64
-rw-r--r--src/librustc/traits/object_safety.rs2
-rw-r--r--src/librustc/traits/project.rs14
-rw-r--r--src/librustc/traits/select.rs75
-rw-r--r--src/librustc/traits/structural_impls.rs47
-rw-r--r--src/librustc/ty/context.rs5
-rw-r--r--src/librustc/ty/fast_reject.rs3
-rw-r--r--src/librustc/ty/flags.rs3
-rw-r--r--src/librustc/ty/item_path.rs2
-rw-r--r--src/librustc/ty/layout.rs10
-rw-r--r--src/librustc/ty/maps.rs7
-rw-r--r--src/librustc/ty/mod.rs14
-rw-r--r--src/librustc/ty/relate.rs12
-rw-r--r--src/librustc/ty/structural_impls.rs10
-rw-r--r--src/librustc/ty/sty.rs25
-rw-r--r--src/librustc/ty/util.rs31
-rw-r--r--src/librustc/ty/walk.rs3
-rw-r--r--src/librustc/util/ppaux.rs10
-rw-r--r--src/librustc_asan/build.rs1
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs27
-rw-r--r--src/librustc_borrowck/lib.rs3
-rw-r--r--src/librustc_const_eval/pattern.rs6
-rw-r--r--src/librustc_driver/driver.rs37
-rw-r--r--src/librustc_driver/lib.rs122
-rw-r--r--src/librustc_errors/emitter.rs7
-rw-r--r--src/librustc_errors/lib.rs5
-rw-r--r--src/librustc_incremental/lib.rs1
-rw-r--r--src/librustc_lint/builtin.rs28
-rw-r--r--src/librustc_lint/types.rs2
-rw-r--r--src/librustc_llvm/build.rs6
-rw-r--r--src/librustc_llvm/ffi.rs8
-rw-r--r--src/librustc_lsan/build.rs1
-rw-r--r--src/librustc_metadata/cstore_impl.rs2
-rw-r--r--src/librustc_metadata/decoder.rs20
-rw-r--r--src/librustc_metadata/encoder.rs54
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_metadata/schema.rs38
-rw-r--r--src/librustc_mir/build/expr/into.rs13
-rw-r--r--src/librustc_mir/dataflow/drop_flag_effects.rs (renamed from src/librustc_borrowck/borrowck/mir/mod.rs)148
-rw-r--r--src/librustc_mir/dataflow/graphviz.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs)13
-rw-r--r--src/librustc_mir/dataflow/impls/mod.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/impls.rs)29
-rw-r--r--src/librustc_mir/dataflow/mod.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/mod.rs)36
-rw-r--r--src/librustc_mir/dataflow/move_paths/abs_domain.rs (renamed from src/librustc_borrowck/borrowck/mir/abs_domain.rs)0
-rw-r--r--src/librustc_mir/dataflow/move_paths/mod.rs (renamed from src/librustc_borrowck/borrowck/mir/gather_moves.rs)12
-rw-r--r--src/librustc_mir/hair/cx/expr.rs3
-rw-r--r--src/librustc_mir/lib.rs3
-rw-r--r--src/librustc_mir/shim.rs17
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs (renamed from src/librustc_borrowck/borrowck/mir/elaborate_drops.rs)43
-rw-r--r--src/librustc_mir/transform/erase_regions.rs5
-rw-r--r--src/librustc_mir/transform/inline.rs7
-rw-r--r--src/librustc_mir/transform/mod.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs6
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs (renamed from src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs)82
-rw-r--r--src/librustc_mir/transform/type_check.rs2
-rw-r--r--src/librustc_msan/build.rs1
-rw-r--r--src/librustc_passes/ast_validation.rs26
-rw-r--r--src/librustc_passes/static_recursion.rs7
-rw-r--r--src/librustc_privacy/lib.rs16
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs5
-rw-r--r--src/librustc_resolve/lib.rs5
-rw-r--r--src/librustc_resolve/macros.rs2
-rw-r--r--src/librustc_trans/Cargo.toml1
-rw-r--r--src/librustc_trans/back/symbol_names.rs7
-rw-r--r--src/librustc_trans/back/write.rs39
-rw-r--r--src/librustc_trans/collector.rs20
-rw-r--r--src/librustc_trans/common.rs6
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs9
-rw-r--r--src/librustc_trans/debuginfo/type_names.rs4
-rw-r--r--src/librustc_trans/glue.rs12
-rw-r--r--src/librustc_trans/intrinsic.rs7
-rw-r--r--src/librustc_trans/lib.rs2
-rw-r--r--src/librustc_trans/mir/block.rs46
-rw-r--r--src/librustc_trans/mir/constant.rs6
-rw-r--r--src/librustc_trans/mir/rvalue.rs2
-rw-r--r--src/librustc_trans/monomorphize.rs10
-rw-r--r--src/librustc_trans/trans_item.rs46
-rw-r--r--src/librustc_tsan/build.rs1
-rw-r--r--src/librustc_typeck/check/_match.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs6
-rw-r--r--src/librustc_typeck/check/cast.rs118
-rw-r--r--src/librustc_typeck/check/coercion.rs121
-rw-r--r--src/librustc_typeck/check/compare_method.rs28
-rw-r--r--src/librustc_typeck/check/demand.rs24
-rw-r--r--src/librustc_typeck/check/dropck.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs43
-rw-r--r--src/librustc_typeck/check/method/confirm.rs2
-rw-r--r--src/librustc_typeck/check/method/mod.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs257
-rw-r--r--src/librustc_typeck/check/wfcheck.rs16
-rw-r--r--src/librustc_typeck/check/writeback.rs2
-rw-r--r--src/librustc_typeck/coherence/builtin.rs2
-rw-r--r--src/librustc_typeck/collect.rs112
-rw-r--r--src/librustc_typeck/diagnostics.rs179
-rw-r--r--src/librustc_typeck/lib.rs36
-rw-r--r--src/librustc_typeck/variance/constraints.rs394
-rw-r--r--src/librustc_typeck/variance/mod.rs88
-rw-r--r--src/librustc_typeck/variance/solve.rs73
-rw-r--r--src/librustc_typeck/variance/terms.rs160
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs28
-rw-r--r--src/librustdoc/html/format.rs6
-rw-r--r--src/librustdoc/html/highlight.rs2
-rw-r--r--src/librustdoc/html/markdown.rs45
-rw-r--r--src/librustdoc/test.rs41
-rw-r--r--src/libstd/env.rs82
-rw-r--r--src/libstd/f32.rs48
-rw-r--r--src/libstd/f64.rs39
-rw-r--r--src/libstd/ffi/c_str.rs8
-rw-r--r--src/libstd/ffi/os_str.rs14
-rw-r--r--src/libstd/fs.rs39
-rw-r--r--src/libstd/io/mod.rs20
-rw-r--r--src/libstd/macros.rs10
-rw-r--r--src/libstd/panicking.rs84
-rw-r--r--src/libstd/path.rs21
-rw-r--r--src/libstd/process.rs4
-rw-r--r--src/libstd/rt.rs2
-rw-r--r--src/libstd/sys/redox/fast_thread_local.rs6
-rw-r--r--src/libstd/sys/redox/fs.rs19
-rw-r--r--src/libstd/sys/redox/net/tcp.rs1
-rw-r--r--src/libstd/sys/redox/pipe.rs4
-rw-r--r--src/libstd/sys/redox/syscall/flag.rs2
-rw-r--r--src/libstd/thread/mod.rs10
-rw-r--r--src/libstd_unicode/tables.rs323
-rw-r--r--src/libsyntax/ast.rs5
-rw-r--r--src/libsyntax/ext/build.rs11
-rw-r--r--src/libsyntax/ext/tt/quoted.rs4
-rw-r--r--src/libsyntax/feature_gate.rs14
-rw-r--r--src/libsyntax/parse/lexer/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs50
-rw-r--r--src/libsyntax/parse/token.rs30
-rw-r--r--src/libsyntax/print/pprust.rs4
-rw-r--r--src/libsyntax/test.rs14
-rw-r--r--src/libsyntax_ext/deriving/clone.rs2
-rw-r--r--src/libsyntax_ext/deriving/debug.rs2
-rw-r--r--src/libsyntax_ext/deriving/encodable.rs2
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs9
-rw-r--r--src/libsyntax_ext/deriving/hash.rs2
-rw-r--r--src/libsyntax_pos/symbol.rs126
-rw-r--r--src/libtest/lib.rs58
m---------src/llvm0
-rw-r--r--src/rustllvm/.editorconfig6
-rw-r--r--src/rustllvm/PassWrapper.cpp128
-rw-r--r--src/rustllvm/llvm-rebuild-trigger2
-rw-r--r--src/test/compile-fail/E0604.rs13
-rw-r--r--src/test/compile-fail/E0605.rs19
-rw-r--r--src/test/compile-fail/E0606.rs13
-rw-r--r--src/test/compile-fail/E0607.rs14
-rw-r--r--src/test/compile-fail/E0619.rs19
-rw-r--r--src/test/compile-fail/E0620.rs13
-rw-r--r--src/test/compile-fail/E0621-does-not-trigger-for-closures.rs28
-rw-r--r--src/test/compile-fail/E0622.rs (renamed from src/test/compile-fail/invalid-intrinsic.rs)4
-rw-r--r--src/test/compile-fail/associated-types-path-2.rs2
-rw-r--r--src/test/compile-fail/cast-from-nil.rs2
-rw-r--r--src/test/compile-fail/cast-to-bare-fn.rs4
-rw-r--r--src/test/compile-fail/cast-to-nil.rs2
-rw-r--r--src/test/compile-fail/closure-no-fn-3.rs2
-rw-r--r--src/test/compile-fail/coerce-to-bang-cast.rs2
-rw-r--r--src/test/compile-fail/dollar-crate-is-keyword-2.rs23
-rw-r--r--src/test/compile-fail/dollar-crate-is-keyword.rs24
-rw-r--r--src/test/compile-fail/dst-bad-assign-3.rs50
-rw-r--r--src/test/compile-fail/dst-bad-coerce1.rs14
-rw-r--r--src/test/compile-fail/dst-bad-coerce2.rs10
-rw-r--r--src/test/compile-fail/dst-bad-coerce3.rs12
-rw-r--r--src/test/compile-fail/dst-bad-coerce4.rs10
-rw-r--r--src/test/compile-fail/dst-bad-deep-2.rs23
-rw-r--r--src/test/compile-fail/fat-ptr-cast.rs2
-rw-r--r--src/test/compile-fail/feature-gate-allow_fail.rs17
-rw-r--r--src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs14
-rw-r--r--src/test/compile-fail/issue-10991.rs2
-rw-r--r--src/test/compile-fail/issue-22289.rs2
-rw-r--r--src/test/compile-fail/issue-22312.rs2
-rw-r--r--src/test/compile-fail/issue-23046.rs4
-rw-r--r--src/test/compile-fail/issue-2995.rs2
-rw-r--r--src/test/compile-fail/issue-38954.rs6
-rw-r--r--src/test/compile-fail/issue-42312.rs21
-rw-r--r--src/test/compile-fail/issue-42880.rs18
-rw-r--r--src/test/compile-fail/nonscalar-cast.rs4
-rw-r--r--src/test/compile-fail/on-unimplemented/multiple-impls.rs6
-rw-r--r--src/test/compile-fail/on-unimplemented/on-impl.rs2
-rw-r--r--src/test/compile-fail/patkind-litrange-no-expr.rs36
-rw-r--r--src/test/compile-fail/tag-variant-cast-non-nullary.rs4
-rw-r--r--src/test/compile-fail/uninhabited-enum-cast.rs2
-rw-r--r--src/test/compile-fail/unsized3.rs1
-rw-r--r--src/test/compile-fail/use-self-type.rs21
-rw-r--r--src/test/compile-fail/variance-trait-bounds.rs20
-rw-r--r--src/test/compile-fail/variance-types-bounds.rs27
-rw-r--r--src/test/parse-fail/macro-keyword.rs2
-rw-r--r--src/test/run-make/llvm-phase/test.rs2
-rw-r--r--src/test/run-pass-valgrind/dst-dtor-3.rs34
-rw-r--r--src/test/run-pass-valgrind/dst-dtor-4.rs31
-rw-r--r--src/test/run-pass/allocator-alloc-one.rs27
-rw-r--r--src/test/run-pass/associated-types-sugar-path.rs2
-rw-r--r--src/test/run-pass/deriving-hash.rs13
-rw-r--r--src/test/run-pass/dst-irrefutable-bind.rs12
-rw-r--r--src/test/run-pass/dst-raw.rs34
-rw-r--r--src/test/run-pass/dst-trait-tuple.rs111
-rw-r--r--src/test/run-pass/dst-tuple-sole.rs85
-rw-r--r--src/test/run-pass/dst-tuple.rs129
-rw-r--r--src/test/run-pass/dynamic-drop.rs15
-rw-r--r--src/test/run-pass/env.rs98
-rw-r--r--src/test/run-pass/issue-31260.rs5
-rw-r--r--src/test/run-pass/issue-37725.rs14
-rw-r--r--src/test/run-pass/macro-pat-neg-lit.rs35
-rw-r--r--src/test/run-pass/process-envs.rs2
-rw-r--r--src/test/run-pass/range_inclusive.rs2
-rw-r--r--src/test/run-pass/sync-send-iterators-in-libcore.rs2
-rw-r--r--src/test/run-pass/test-allow-fail-attr.rs24
-rw-r--r--src/test/run-pass/vector-sort-panic-safe.rs168
-rw-r--r--src/test/rustdoc/issue-42875.rs23
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-do.rs (renamed from src/test/compile-fail/block-must-not-have-result-do.rs)0
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-do.stderr11
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-res.rs (renamed from src/test/compile-fail/block-must-not-have-result-res.rs)0
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-res.stderr11
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-while.rs (renamed from src/test/compile-fail/block-must-not-have-result-while.rs)0
-rw-r--r--src/test/ui/block-result/block-must-not-have-result-while.stderr11
-rw-r--r--src/test/ui/block-result/consider-removing-last-semi.rs (renamed from src/test/compile-fail/consider-removing-last-semi.rs)0
-rw-r--r--src/test/ui/block-result/consider-removing-last-semi.stderr30
-rw-r--r--src/test/ui/block-result/issue-11714.rs (renamed from src/test/compile-fail/issue-11714.rs)0
-rw-r--r--src/test/ui/block-result/issue-11714.stderr17
-rw-r--r--src/test/ui/block-result/issue-13428.rs (renamed from src/test/compile-fail/issue-13428.rs)0
-rw-r--r--src/test/ui/block-result/issue-13428.stderr33
-rw-r--r--src/test/ui/block-result/issue-13624.rs (renamed from src/test/compile-fail/issue-13624.rs)0
-rw-r--r--src/test/ui/block-result/issue-13624.stderr20
-rw-r--r--src/test/ui/block-result/issue-20862.rs (renamed from src/test/compile-fail/issue-20862.rs)0
-rw-r--r--src/test/ui/block-result/issue-20862.stderr19
-rw-r--r--src/test/ui/block-result/issue-22645.rs (renamed from src/test/compile-fail/issue-22645.rs)0
-rw-r--r--src/test/ui/block-result/issue-22645.stderr21
-rw-r--r--src/test/ui/block-result/issue-3563.rs (renamed from src/test/compile-fail/issue-3563.rs)0
-rw-r--r--src/test/ui/block-result/issue-3563.stderr19
-rw-r--r--src/test/ui/block-result/issue-5500.rs (renamed from src/test/compile-fail/issue-5500.rs)0
-rw-r--r--src/test/ui/block-result/issue-5500.stderr11
-rw-r--r--src/test/ui/block-result/unexpected-return-on-unit.rs24
-rw-r--r--src/test/ui/block-result/unexpected-return-on-unit.stderr15
-rw-r--r--src/test/ui/borrowck/borrowck-in-static.stderr2
-rw-r--r--src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr2
-rw-r--r--src/test/ui/check_match/issue-35609.stderr2
-rw-r--r--src/test/ui/closure_context/issue-26046-fn-mut.stderr2
-rw-r--r--src/test/ui/closure_context/issue-26046-fn-once.stderr2
-rw-r--r--src/test/ui/closure_context/issue-42065.stderr2
-rw-r--r--src/test/ui/codemap_tests/bad-format-args.stderr2
-rw-r--r--src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr2
-rw-r--r--src/test/ui/codemap_tests/empty_span.stderr2
-rw-r--r--src/test/ui/codemap_tests/huge_multispan_highlight.stderr2
-rw-r--r--src/test/ui/codemap_tests/issue-11715.stderr2
-rw-r--r--src/test/ui/codemap_tests/issue-28308.stderr2
-rw-r--r--src/test/ui/codemap_tests/one_line.stderr2
-rw-r--r--src/test/ui/codemap_tests/overlapping_inherent_impls.stderr2
-rw-r--r--src/test/ui/codemap_tests/overlapping_spans.stderr2
-rw-r--r--src/test/ui/codemap_tests/tab.stderr2
-rw-r--r--src/test/ui/codemap_tests/unicode.stderr2
-rw-r--r--src/test/ui/coercion-missing-tail-expected-type.stderr14
-rw-r--r--src/test/ui/compare-method/proj-outlives-region.stderr2
-rw-r--r--src/test/ui/compare-method/region-extra-2.stderr2
-rw-r--r--src/test/ui/compare-method/region-extra.stderr2
-rw-r--r--src/test/ui/compare-method/region-unrelated.stderr2
-rw-r--r--src/test/ui/compare-method/reordered-type-param.stderr2
-rw-r--r--src/test/ui/compare-method/trait-bound-on-type-parameter.stderr2
-rw-r--r--src/test/ui/compare-method/traits-misc-mismatch-1.stderr2
-rw-r--r--src/test/ui/compare-method/traits-misc-mismatch-2.stderr2
-rw-r--r--src/test/ui/cross-crate-macro-backtrace/main.stderr2
-rw-r--r--src/test/ui/did_you_mean/E0178.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-31424.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-34126.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-34337.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-35937.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-36798.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-36798_unknown_field.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-37139.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-1.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-2.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-3.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-38147-4.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-39544.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-40006.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-40396.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-40823.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-41679.stderr2
-rw-r--r--src/test/ui/did_you_mean/recursion_limit.stderr2
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_deref.stderr2
-rw-r--r--src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr2
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr2
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr2
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-reorder.stderr2
-rw-r--r--src/test/ui/dropck/dropck-eyepatch.stderr2
-rw-r--r--src/test/ui/fmt/format-string-error.stderr2
-rw-r--r--src/test/ui/impl-trait/equality.stderr2
-rw-r--r--src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr2
-rw-r--r--src/test/ui/impl-trait/method-suggestion-no-duplication.stderr2
-rw-r--r--src/test/ui/impl-trait/no-method-suggested-traits.stderr2
-rw-r--r--src/test/ui/impl-trait/trait_type.stderr2
-rw-r--r--src/test/ui/interior-mutability/interior-mutability.stderr2
-rw-r--r--src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr2
-rw-r--r--src/test/ui/issue-22644.stderr2
-rw-r--r--src/test/ui/issue-26548.stderr2
-rw-r--r--src/test/ui/issue-33525.rs15
-rw-r--r--src/test/ui/issue-33525.stderr20
-rw-r--r--src/test/ui/issue-37311-type-length-limit/issue-37311.stderr2
-rw-r--r--src/test/ui/issue-38875/issue_38875.stderr2
-rw-r--r--src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr2
-rw-r--r--src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr2
-rw-r--r--src/test/ui/issue-41652/issue_41652.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs15
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs15
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs18
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs (renamed from src/test/compile-fail/variance-region-bounds.rs)19
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr11
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs27
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr27
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr23
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs24
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr27
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs23
-rw-r--r--src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr27
-rw-r--r--src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs19
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr10
-rw-r--r--src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr25
-rw-r--r--src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr2
-rw-r--r--src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr2
-rw-r--r--src/test/ui/lifetimes/borrowck-let-suggestion.stderr2
-rw-r--r--src/test/ui/lint/command-line-lint-group-deny.stderr2
-rw-r--r--src/test/ui/lint/command-line-lint-group-forbid.stderr2
-rw-r--r--src/test/ui/lint/lint-group-style.stderr12
-rw-r--r--src/test/ui/lint/outer-forbid.rs22
-rw-r--r--src/test/ui/lint/outer-forbid.stderr29
-rw-r--r--src/test/ui/loop-break-value-no-repeat.stderr2
-rw-r--r--src/test/ui/macros/bad_hello.stderr2
-rw-r--r--src/test/ui/macros/format-foreign.stderr2
-rw-r--r--src/test/ui/macros/macro-backtrace-invalid-internals.stderr2
-rw-r--r--src/test/ui/macros/macro-backtrace-nested.stderr2
-rw-r--r--src/test/ui/macros/macro-backtrace-println.stderr2
-rw-r--r--src/test/ui/mismatched_types/E0053.stderr2
-rw-r--r--src/test/ui/mismatched_types/E0281.stderr2
-rw-r--r--src/test/ui/mismatched_types/E0409.stderr2
-rw-r--r--src/test/ui/mismatched_types/abridged.rs10
-rw-r--r--src/test/ui/mismatched_types/abridged.stderr26
-rw-r--r--src/test/ui/mismatched_types/binops.stderr2
-rw-r--r--src/test/ui/mismatched_types/cast-rfc0401.stderr70
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr2
-rw-r--r--src/test/ui/mismatched_types/closure-mismatch.stderr2
-rw-r--r--src/test/ui/mismatched_types/const-fn-in-trait.stderr2
-rw-r--r--src/test/ui/mismatched_types/fn-variance-1.stderr2
-rw-r--r--src/test/ui/mismatched_types/for-loop-has-unit-body.rs (renamed from src/test/compile-fail/for-loop-has-unit-body.rs)0
-rw-r--r--src/test/ui/mismatched_types/for-loop-has-unit-body.stderr11
-rw-r--r--src/test/ui/mismatched_types/issue-19109.stderr4
-rw-r--r--src/test/ui/mismatched_types/issue-26480.stderr6
-rw-r--r--src/test/ui/mismatched_types/issue-35030.stderr2
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr2
-rw-r--r--src/test/ui/mismatched_types/issue-38371.stderr2
-rw-r--r--src/test/ui/mismatched_types/main.stderr2
-rw-r--r--src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr2
-rw-r--r--src/test/ui/mismatched_types/overloaded-calls-bad.stderr2
-rw-r--r--src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr2
-rw-r--r--src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr2
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr2
-rw-r--r--src/test/ui/missing-items/issue-40221.stderr2
-rw-r--r--src/test/ui/missing-items/m2.stderr2
-rw-r--r--src/test/ui/missing-items/missing-type-parameter.stderr2
-rw-r--r--src/test/ui/path-lookahead.stderr2
-rw-r--r--src/test/ui/pub/pub-restricted-error-fn.stderr2
-rw-r--r--src/test/ui/pub/pub-restricted-error.stderr2
-rw-r--r--src/test/ui/pub/pub-restricted-non-path.stderr2
-rw-r--r--src/test/ui/pub/pub-restricted.stderr2
-rw-r--r--src/test/ui/reachable/expr_add.stderr2
-rw-r--r--src/test/ui/reachable/expr_again.stderr2
-rw-r--r--src/test/ui/reachable/expr_array.stderr2
-rw-r--r--src/test/ui/reachable/expr_assign.stderr2
-rw-r--r--src/test/ui/reachable/expr_block.stderr2
-rw-r--r--src/test/ui/reachable/expr_box.stderr2
-rw-r--r--src/test/ui/reachable/expr_call.stderr2
-rw-r--r--src/test/ui/reachable/expr_cast.stderr2
-rw-r--r--src/test/ui/reachable/expr_if.stderr2
-rw-r--r--src/test/ui/reachable/expr_loop.stderr2
-rw-r--r--src/test/ui/reachable/expr_match.stderr2
-rw-r--r--src/test/ui/reachable/expr_method.stderr2
-rw-r--r--src/test/ui/reachable/expr_repeat.stderr2
-rw-r--r--src/test/ui/reachable/expr_return.stderr2
-rw-r--r--src/test/ui/reachable/expr_struct.stderr2
-rw-r--r--src/test/ui/reachable/expr_tup.stderr2
-rw-r--r--src/test/ui/reachable/expr_type.stderr2
-rw-r--r--src/test/ui/reachable/expr_unary.stderr2
-rw-r--r--src/test/ui/reachable/expr_while.stderr2
-rw-r--r--src/test/ui/regions-fn-subtyping-return-static.stderr2
-rw-r--r--src/test/ui/resolve/enums-are-namespaced-xc.stderr2
-rw-r--r--src/test/ui/resolve/issue-14254.stderr2
-rw-r--r--src/test/ui/resolve/issue-16058.stderr2
-rw-r--r--src/test/ui/resolve/issue-17518.stderr2
-rw-r--r--src/test/ui/resolve/issue-18252.stderr2
-rw-r--r--src/test/ui/resolve/issue-19452.stderr2
-rw-r--r--src/test/ui/resolve/issue-23305.stderr2
-rw-r--r--src/test/ui/resolve/issue-2356.stderr2
-rw-r--r--src/test/ui/resolve/issue-24968.stderr2
-rw-r--r--src/test/ui/resolve/issue-33876.stderr2
-rw-r--r--src/test/ui/resolve/issue-3907-2.stderr2
-rw-r--r--src/test/ui/resolve/issue-39226.stderr2
-rw-r--r--src/test/ui/resolve/issue-5035-2.stderr2
-rw-r--r--src/test/ui/resolve/issue-6702.stderr2
-rw-r--r--src/test/ui/resolve/levenshtein.stderr2
-rw-r--r--src/test/ui/resolve/privacy-struct-ctor.stderr2
-rw-r--r--src/test/ui/resolve/resolve-assoc-suggestions.stderr2
-rw-r--r--src/test/ui/resolve/resolve-hint-macro.stderr2
-rw-r--r--src/test/ui/resolve/resolve-speculative-adjustment.stderr2
-rw-r--r--src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr2
-rw-r--r--src/test/ui/resolve/token-error-correct-2.stderr2
-rw-r--r--src/test/ui/resolve/token-error-correct-3.stderr6
-rw-r--r--src/test/ui/resolve/token-error-correct.stderr2
-rw-r--r--src/test/ui/resolve/tuple-struct-alias.stderr2
-rw-r--r--src/test/ui/resolve/unresolved_static_type_field.stderr2
-rw-r--r--src/test/ui/shadowed-type-parameter.rs (renamed from src/test/compile-fail/shadowed-type-parameter.rs)0
-rw-r--r--src/test/ui/shadowed-type-parameter.stderr28
-rw-r--r--src/test/ui/span/E0046.stderr2
-rw-r--r--src/test/ui/span/E0057.stderr2
-rw-r--r--src/test/ui/span/E0072.stderr2
-rw-r--r--src/test/ui/span/E0204.stderr2
-rw-r--r--src/test/ui/span/E0493.stderr2
-rw-r--r--src/test/ui/span/E0535.stderr2
-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-borrow-overloaded-auto-deref-mut.stderr2
-rw-r--r--src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr2
-rw-r--r--src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr2
-rw-r--r--src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr2
-rw-r--r--src/test/ui/span/borrowck-fn-in-const-b.stderr2
-rw-r--r--src/test/ui/span/borrowck-let-suggestion-suffixes.stderr2
-rw-r--r--src/test/ui/span/borrowck-object-mutability.stderr2
-rw-r--r--src/test/ui/span/borrowck-ref-into-rvalue.stderr2
-rw-r--r--src/test/ui/span/coerce-suggestions.stderr2
-rw-r--r--src/test/ui/span/destructor-restrictions.stderr2
-rw-r--r--src/test/ui/span/dropck-object-cycle.stderr2
-rw-r--r--src/test/ui/span/dropck_arr_cycle_checked.stderr2
-rw-r--r--src/test/ui/span/dropck_direct_cycle_with_drop.stderr2
-rw-r--r--src/test/ui/span/dropck_misc_variants.stderr2
-rw-r--r--src/test/ui/span/dropck_vec_cycle_checked.stderr2
-rw-r--r--src/test/ui/span/impl-wrong-item-for-trait.stderr2
-rw-r--r--src/test/ui/span/issue-11925.stderr2
-rw-r--r--src/test/ui/span/issue-15480.stderr2
-rw-r--r--src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr2
-rw-r--r--src/test/ui/span/issue-23729.stderr2
-rw-r--r--src/test/ui/span/issue-23827.stderr2
-rw-r--r--src/test/ui/span/issue-24356.stderr2
-rw-r--r--src/test/ui/span/issue-24690.stderr8
-rw-r--r--src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr2
-rw-r--r--src/test/ui/span/issue-24805-dropck-trait-has-items.stderr2
-rw-r--r--src/test/ui/span/issue-24895-copy-clone-dropck.stderr2
-rw-r--r--src/test/ui/span/issue-25199.stderr2
-rw-r--r--src/test/ui/span/issue-26656.stderr2
-rw-r--r--src/test/ui/span/issue-27522.stderr2
-rw-r--r--src/test/ui/span/issue-29106.stderr2
-rw-r--r--src/test/ui/span/issue-29595.stderr2
-rw-r--r--src/test/ui/span/issue-33884.stderr2
-rw-r--r--src/test/ui/span/issue-34264.stderr2
-rw-r--r--src/test/ui/span/issue-36530.stderr2
-rw-r--r--src/test/ui/span/issue-36537.stderr2
-rw-r--r--src/test/ui/span/issue-37767.stderr2
-rw-r--r--src/test/ui/span/issue-39018.stderr2
-rw-r--r--src/test/ui/span/issue-39698.stderr2
-rw-r--r--src/test/ui/span/issue-40157.stderr2
-rw-r--r--src/test/ui/span/issue-7575.stderr2
-rw-r--r--src/test/ui/span/issue28498-reject-ex1.stderr2
-rw-r--r--src/test/ui/span/issue28498-reject-lifetime-param.stderr2
-rw-r--r--src/test/ui/span/issue28498-reject-passed-to-fn.stderr2
-rw-r--r--src/test/ui/span/issue28498-reject-trait-bound.stderr2
-rw-r--r--src/test/ui/span/lint-unused-unsafe.stderr2
-rw-r--r--src/test/ui/span/loan-extend.stderr2
-rw-r--r--src/test/ui/span/move-closure.stderr2
-rw-r--r--src/test/ui/span/multiline-span-E0072.stderr2
-rw-r--r--src/test/ui/span/multiline-span-simple.stderr2
-rw-r--r--src/test/ui/span/mut-arg-hint.stderr2
-rw-r--r--src/test/ui/span/mut-ptr-cant-outlive-ref.stderr2
-rw-r--r--src/test/ui/span/pub-struct-field.stderr2
-rw-r--r--src/test/ui/span/range-2.stderr2
-rw-r--r--src/test/ui/span/recursive-type-field.stderr2
-rw-r--r--src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr2
-rw-r--r--src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr2
-rw-r--r--src/test/ui/span/regions-close-over-type-parameter-2.stderr2
-rw-r--r--src/test/ui/span/regions-escape-loop-via-variable.stderr2
-rw-r--r--src/test/ui/span/regions-escape-loop-via-vec.stderr2
-rw-r--r--src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr2
-rw-r--r--src/test/ui/span/send-is-not-static-ensures-scoping.stderr2
-rw-r--r--src/test/ui/span/send-is-not-static-std-sync-2.stderr2
-rw-r--r--src/test/ui/span/send-is-not-static-std-sync.stderr2
-rw-r--r--src/test/ui/span/slice-borrow.stderr2
-rw-r--r--src/test/ui/span/suggestion-non-ascii.stderr2
-rw-r--r--src/test/ui/span/type-binding.stderr2
-rw-r--r--src/test/ui/span/typo-suggestion.stderr2
-rw-r--r--src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr2
-rw-r--r--src/test/ui/span/vec_refs_data_with_early_death.stderr2
-rw-r--r--src/test/ui/span/wf-method-late-bound-regions.stderr2
-rw-r--r--src/test/ui/static-lifetime.stderr2
-rw-r--r--src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr2
-rw-r--r--src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr2
-rw-r--r--src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr2
-rw-r--r--src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr2
-rw-r--r--src/test/ui/suggestions/confuse-field-and-method/private-field.stderr2
-rw-r--r--src/test/ui/suggestions/tuple-float-index.stderr2
-rw-r--r--src/test/ui/token/bounds-obj-parens.stderr2
-rw-r--r--src/test/ui/token/issue-10636-2.stderr2
-rw-r--r--src/test/ui/token/issue-41155.stderr2
-rw-r--r--src/test/ui/token/macro-incomplete-parse.stderr2
-rw-r--r--src/test/ui/token/trailing-plus-in-bounds.stderr2
-rw-r--r--src/test/ui/transmute/main.stderr2
-rw-r--r--src/test/ui/transmute/transmute-from-fn-item-types-error.stderr2
-rw-r--r--src/test/ui/transmute/transmute-type-parameters.stderr2
-rw-r--r--src/test/ui/type-check/assignment-in-if.stderr2
-rw-r--r--src/test/ui/type-check/cannot_infer_local_or_array.stderr2
-rw-r--r--src/test/ui/type-check/cannot_infer_local_or_vec.stderr2
-rw-r--r--src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr2
-rw-r--r--src/test/ui/type-check/issue-22897.stderr2
-rw-r--r--src/test/ui/type-check/issue-40294.stderr2
-rw-r--r--src/test/ui/type-check/unknown_type_for_closure.stderr2
m---------src/tools/cargo0
-rw-r--r--src/tools/compiletest/src/errors.rs6
-rw-r--r--src/tools/compiletest/src/header.rs27
-rw-r--r--src/tools/compiletest/src/json.rs2
-rw-r--r--src/tools/compiletest/src/main.rs26
-rw-r--r--src/tools/compiletest/src/procsrv.rs3
-rw-r--r--src/tools/compiletest/src/runtest.rs112
m---------src/tools/rls0
605 files changed, 6476 insertions, 3688 deletions
diff --git a/.gitignore b/.gitignore
index ff839c34df1..b54bab177d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@
 .hg/
 .hgignore
 .idea
+*.iml
 __pycache__/
 *.py[cod]
 *$py.class
diff --git a/.travis.yml b/.travis.yml
index b95196da356..21877ecb43e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -171,16 +171,22 @@ before_script:
       if [[ "$SKIP_BUILD" == true ]]; then
           export RUN_SCRIPT="echo 'skipping, not a full build'";
       else
-          RUN_SCRIPT="stamp src/ci/init_repo.sh . $HOME/rustsrc";
+          RUN_SCRIPT="src/ci/init_repo.sh . $HOME/rustsrc";
           if [ "$TRAVIS_OS_NAME" = "osx" ]; then
-              export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/run.sh";
+              export RUN_SCRIPT="$RUN_SCRIPT && src/ci/run.sh";
           else
-              export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/docker/run.sh $IMAGE";
+              export RUN_SCRIPT="$RUN_SCRIPT && src/ci/docker/run.sh $IMAGE";
           fi
       fi
 
+# Log time information from this machine and an external machine for insight into possible
+# clock drift. Timezones don't matter since relative deltas give all the necessary info.
 script:
-  - sh -x -c "$RUN_SCRIPT"
+  - >
+      date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g'
+  - stamp sh -x -c "$RUN_SCRIPT"
+  - >
+      date && curl -s --head https://google.com | grep ^Date: | sed 's/Date: //g'
 
 after_success:
   - >
diff --git a/README.md b/README.md
index 0b209fd3e94..a1f01861075 100644
--- a/README.md
+++ b/README.md
@@ -40,8 +40,9 @@ Read ["Installation"] from [The Book].
 
     > ***Note:*** Install locations can be adjusted by copying the config file
     > from `./src/bootstrap/config.toml.example` to `./config.toml`, and
-    > adjusting the `prefix` option under `[install]`. Various other options are
-    > also supported, and are documented in the config file.
+    > adjusting the `prefix` option under `[install]`. Various other options, such
+    > as enabling debug information, are also supported, and are documented in
+    > the config file.
 
     When complete, `sudo ./x.py install` will place several programs into
     `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
diff --git a/src/Cargo.lock b/src/Cargo.lock
index e8f0ed6ed2c..dc94ee27e93 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -129,7 +129,7 @@ dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -157,7 +157,7 @@ dependencies = [
 [[package]]
 name = "cargo"
 version = "0.21.0"
-source = "git+https://github.com/rust-lang/cargo#50b1c24d146fa072db71f12005deed319ac5ba9a"
+source = "git+https://github.com/rust-lang/cargo#eb6cf012a6cc23c9c89c4009564de9fccc38b9cb"
 replace = "cargo 0.21.0"
 
 [[package]]
@@ -170,8 +170,8 @@ dependencies = [
  "cargotest 0.1.0",
  "crates-io 0.10.0",
  "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -188,7 +188,7 @@ dependencies = [
  "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.5.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.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -201,8 +201,8 @@ dependencies = [
  "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.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.2 (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)",
 ]
 
@@ -224,7 +224,7 @@ dependencies = [
  "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.0 (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)",
 ]
 
@@ -301,12 +301,12 @@ dependencies = [
 name = "crates-io"
 version = "0.10.0"
 dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.8 (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.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -316,19 +316,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "curl"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (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.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "curl-sys"
-version = "0.3.12"
+version = "0.3.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -365,7 +366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "docopt"
-version = "0.8.0"
+version = "0.8.1"
 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)",
@@ -474,7 +475,7 @@ dependencies = [
  "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.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -482,10 +483,10 @@ name = "git2-curl"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -575,14 +576,14 @@ dependencies = [
 
 [[package]]
 name = "languageserver-types"
-version = "0.10.0"
+version = "0.11.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.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.8 (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.0 (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)",
 ]
 
@@ -609,7 +610,7 @@ version = "0.6.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -798,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "num_cpus"
-version = "1.5.1"
+version = "1.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -936,11 +937,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "racer"
-version = "2.0.8"
+version = "2.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.24.2 (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)",
@@ -984,7 +986,7 @@ dependencies = [
  "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1013,39 +1015,30 @@ dependencies = [
  "cargo 0.21.0 (git+https://github.com/rust-lang/cargo)",
  "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "languageserver-types 0.11.0 (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.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-data 0.7.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.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.8 (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.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.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)",
 ]
 
 [[package]]
 name = "rls-analysis"
-version = "0.3.2"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "rls-data"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
+ "rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1071,10 +1064,10 @@ dependencies = [
 
 [[package]]
 name = "rls-vfs"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "racer 2.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1396,6 +1389,7 @@ dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_math 0.0.0",
@@ -1463,7 +1457,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.1.3"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1477,8 +1471,8 @@ dependencies = [
  "serde_derive 1.0.8 (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.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.1 (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.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1580,6 +1574,18 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "socket2"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.1 (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.24 (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)",
+]
+
+[[package]]
 name = "stable_deref_trait"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1697,7 +1703,7 @@ dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1720,7 +1726,7 @@ dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1748,7 +1754,7 @@ version = "0.0.0"
 
 [[package]]
 name = "term"
-version = "0.4.5"
+version = "0.4.6"
 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)",
@@ -1791,15 +1797,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "thread-id"
-version = "3.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "thread_local"
 version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1809,11 +1806,11 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1846,7 +1843,7 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1892,7 +1889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unreachable"
-version = "0.1.1"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1907,7 +1904,7 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "1.5.0"
+version = "1.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1921,7 +1918,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2026,12 +2023,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f"
 "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
 "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
-"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b"
-"checksum curl-sys 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f00c8ba847fb0730c293069b4d1203dc01bf3c2e1f90b4e55f426ed8f4a1eeac"
+"checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7"
+"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de"
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41be6ca3b99e0c0483fb2389685448f650459c3ecbe4e18d7705d8010ec4ab8e"
 "checksum diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0a515461b6c8c08419850ced27bc29e86166dcdcde8fbe76f8b1f0589bb49472"
-"checksum docopt 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63e408eee8a772c5c61f62353992e3ebf51ef5c832dd04d986b3dc7d48c5b440"
+"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
@@ -2053,7 +2050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum languageserver-types 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97c2985bfcbbcb0189cfa25e1c10c1ac7111df2b6214b652c690127aefdf4e5b"
+"checksum languageserver-types 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c178b944c3187527293fb9f8a0b0db3c5fb62eb127cacd65296f651a2440f5b1"
 "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
 "checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc"
 "checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d"
@@ -2075,7 +2072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e"
 "checksum num-rational 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "33c881e104a26e1accc09449374c095ff2312c8e0c27fab7bbefe16eac7c776d"
 "checksum num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1708c0628602a98b52fad936cf3edb9a107af06e52e49fdf0707e884456a6af6"
-"checksum num_cpus 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e416ba127a4bb3ff398cb19546a8d0414f73352efe2857f4060d36f5fe5983a"
+"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.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41"
 "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
@@ -2090,20 +2087,19 @@ 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.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edf2dfc188373ef96168bec3646a0415c5c21111c6144c0c36104fc720587ecd"
+"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd"
 "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"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum rls-analysis 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d77d58e8933752142b5b92e3f8ba6d6f1630be6da5627c492268a43f79ffbda"
-"checksum rls-data 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "374a8fad31cc0681a7bfd8a04079dd4afd0e981d34e18a171b1a467445bdf51e"
+"checksum rls-analysis 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "78a05b130793ebc781c2d933299d7214a10d014fdebe5184eb652c81ba8d3184"
 "checksum rls-data 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e502ac679bc35e023e982506c32d0278ef89e29af1e4ad21cb70c44b525b87a9"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
-"checksum rls-vfs 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ace07060dd154731b39254864245cbdd33c8f5f64fe1f630a089c72e2468f854"
+"checksum rls-vfs 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f19246a0fda45f2fb6eb34addef2a692c044cbf1c90ec7695583450fb5f23e7"
 "checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "277deb9c0ee9c4788ee94faef5988fa334179cd7363bf281a2cae027edbbc8bf"
+"checksum rustfmt-nightly 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "31ac6fe40a9844ee2de3d51d0be2bbcdb361bad6f3667a02db8c4e2330afbbb5"
 "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 semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
@@ -2116,6 +2112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum serde_json 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ad8bcf487be7d2e15d3d543f04312de991d631cfe1b43ea0ade69e6a8a5b16a1"
 "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 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"
@@ -2127,17 +2124,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
 "checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
-"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
+"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 thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
-"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
 "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
-"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
+"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
 "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
 "checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f"
-"checksum toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4cc5dbfb20a481e64b99eb7ae280859ec76730c7191570ba5edaa962394edb0a"
+"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7"
 "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
 "checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
@@ -2145,8 +2141,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "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"
-"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
-"checksum url 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a69a2e36a5e5ed3f3063c8c64a3b028c4d50d689fa6c862abd7cfe65f882595c"
+"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27"
 "checksum url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e7d099f1ee52f823d4bdd60c93c3602043c728f5db3b97bdb548467f7bddea"
 "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 8c6eaee24f2..7232208b522 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -75,16 +75,11 @@ fn main() {
         Err(_) => 0,
     };
 
-    // Build scripts always use the snapshot compiler which is guaranteed to be
-    // able to produce an executable, whereas intermediate compilers may not
-    // have the standard library built yet and may not be able to produce an
-    // executable. Otherwise we just use the standard compiler we're
-    // bootstrapping with.
-    //
-    // Also note that cargo will detect the version of the compiler to trigger
-    // a rebuild when the compiler changes. If this happens, we want to make
-    // sure to use the actual compiler instead of the snapshot compiler becase
-    // that's the one that's actually changing.
+    // Use a different compiler for build scripts, since there may not yet be a
+    // libstd for the real compiler to use. However, if Cargo is attempting to
+    // determine the version of the compiler, the real compiler needs to be
+    // used. Currently, these two states are differentiated based on whether
+    // --target and -vV is/isn't passed.
     let (rustc, libdir) = if target.is_none() && version.is_none() {
         ("RUSTC_SNAPSHOT", "RUSTC_SNAPSHOT_LIBDIR")
     } else {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 8dc2875ec42..eaf2a40f2fa 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -25,10 +25,11 @@ from time import time
 
 
 def get(url, path, verbose=False):
-    sha_url = url + ".sha256"
+    suffix = '.sha256'
+    sha_url = url + suffix
     with tempfile.NamedTemporaryFile(delete=False) as temp_file:
         temp_path = temp_file.name
-    with tempfile.NamedTemporaryFile(suffix=".sha256", delete=False) as sha_file:
+    with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as sha_file:
         sha_path = sha_file.name
 
     try:
@@ -55,6 +56,7 @@ def get(url, path, verbose=False):
 
 
 def delete_if_present(path, verbose):
+    """Remove the given file if present"""
     if os.path.isfile(path):
         if verbose:
             print("removing " + path)
@@ -92,12 +94,13 @@ def _download(path, url, probably_big, verbose, exception):
 
 
 def verify(path, sha_path, verbose):
+    """Check if the sha256 sum of the given path is valid"""
     if verbose:
         print("verifying " + path)
-    with open(path, "rb") as f:
-        found = hashlib.sha256(f.read()).hexdigest()
-    with open(sha_path, "r") as f:
-        expected = f.readline().split()[0]
+    with open(path, "rb") as source:
+        found = hashlib.sha256(source.read()).hexdigest()
+    with open(sha_path, "r") as sha256sum:
+        expected = sha256sum.readline().split()[0]
     verified = found == expected
     if not verified:
         print("invalid checksum:\n"
@@ -107,6 +110,7 @@ def verify(path, sha_path, verbose):
 
 
 def unpack(tarball, dst, verbose=False, match=None):
+    """Unpack the given tarball file"""
     print("extracting " + tarball)
     fname = os.path.basename(tarball).replace(".tar.gz", "")
     with contextlib.closing(tarfile.open(tarball)) as tar:
@@ -128,6 +132,7 @@ def unpack(tarball, dst, verbose=False, match=None):
             shutil.move(tp, fp)
     shutil.rmtree(os.path.join(dst, fname))
 
+
 def run(args, verbose=False, exception=False, **kwargs):
     if verbose:
         print("running: " + ' '.join(args))
@@ -245,7 +250,8 @@ class RustBuild(object):
             return
 
         # At this point we're pretty sure the user is running NixOS
-        print("info: you seem to be running NixOS. Attempting to patch " + fname)
+        nix_os_msg = "info: you seem to be running NixOS. Attempting to patch"
+        print(nix_os_msg, fname)
 
         try:
             interpreter = subprocess.check_output(
@@ -293,18 +299,22 @@ class RustBuild(object):
         return self._cargo_channel
 
     def rustc_stamp(self):
+        """Return the path for .rustc-stamp"""
         return os.path.join(self.bin_root(), '.rustc-stamp')
 
     def cargo_stamp(self):
+        """Return the path for .cargo-stamp"""
         return os.path.join(self.bin_root(), '.cargo-stamp')
 
     def rustc_out_of_date(self):
+        """Check if rustc is out of date"""
         if not os.path.exists(self.rustc_stamp()) or self.clean:
             return True
         with open(self.rustc_stamp(), 'r') as f:
             return self.stage0_date() != f.read()
 
     def cargo_out_of_date(self):
+        """Check if cargo is out of date"""
         if not os.path.exists(self.cargo_stamp()) or self.clean:
             return True
         with open(self.cargo_stamp(), 'r') as f:
@@ -357,8 +367,7 @@ class RustBuild(object):
     def exe_suffix(self):
         if sys.platform == 'win32':
             return '.exe'
-        else:
-            return ''
+        return ''
 
     def print_what_it_means_to_bootstrap(self):
         if hasattr(self, 'printed'):
@@ -366,7 +375,7 @@ class RustBuild(object):
         self.printed = True
         if os.path.exists(self.bootstrap_binary()):
             return
-        if not '--help' in sys.argv or len(sys.argv) == 1:
+        if '--help' not in sys.argv or len(sys.argv) == 1:
             return
 
         print('info: the build system for Rust is written in Rust, so this')
@@ -461,8 +470,8 @@ class RustBuild(object):
             # 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)
+                cputype = subprocess.check_output(
+                    ['isainfo', '-k']).strip().decode(default_encoding)
             except (subprocess.CalledProcessError, OSError):
                 err = "isainfo not found"
                 if self.verbose:
@@ -562,21 +571,26 @@ class RustBuild(object):
         default_encoding = sys.getdefaultencoding()
         run(["git", "submodule", "-q", "sync"], cwd=self.rust_root)
         submodules = [s.split(' ', 1)[1] for s in subprocess.check_output(
-            ["git", "config", "--file", os.path.join(self.rust_root, ".gitmodules"),
+            ["git", "config", "--file",
+             os.path.join(self.rust_root, ".gitmodules"),
              "--get-regexp", "path"]
         ).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
+                                self.get_mk('CFG_LLVM_ROOT'))) or
                               (module.endswith("jemalloc") and
-                               (self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT'))))
-                     ]
+                               (self.get_toml('jemalloc') or
+                                self.get_mk('CFG_JEMALLOC_ROOT'))))]
         run(["git", "submodule", "update",
-                  "--init"] + submodules, cwd=self.rust_root, verbose=self.verbose)
+             "--init"] + submodules,
+            cwd=self.rust_root, verbose=self.verbose)
         run(["git", "submodule", "-q", "foreach", "git",
-                  "reset", "-q", "--hard"], cwd=self.rust_root, verbose=self.verbose)
+             "reset", "-q", "--hard"],
+            cwd=self.rust_root, verbose=self.verbose)
         run(["git", "submodule", "-q", "foreach", "git",
-                  "clean", "-qdfx"], cwd=self.rust_root, verbose=self.verbose)
+             "clean", "-qdfx"],
+            cwd=self.rust_root, verbose=self.verbose)
 
 
 def bootstrap():
@@ -692,5 +706,6 @@ def main():
                   format_build_time(time() - start_time))
         sys.exit(exit_code)
 
+
 if __name__ == '__main__':
     main()
diff --git a/src/bootstrap/cc.rs b/src/bootstrap/cc.rs
index 54c8194678e..7c7161916ee 100644
--- a/src/bootstrap/cc.rs
+++ b/src/bootstrap/cc.rs
@@ -42,10 +42,13 @@ use config::Target;
 pub fn find(build: &mut Build) {
     // For all targets we're going to need a C compiler for building some shims
     // and such as well as for being a linker for Rust code.
-    for target in build.config.target.iter() {
+    //
+    // This includes targets that aren't necessarily passed on the commandline
+    // (FIXME: Perhaps it shouldn't?)
+    for target in &build.config.target {
         let mut cfg = gcc::Config::new();
         cfg.cargo_metadata(false).opt_level(0).debug(false)
-           .target(target).host(&build.config.build);
+           .target(target).host(&build.build);
 
         let config = build.config.target_config.get(target);
         if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
@@ -64,10 +67,13 @@ pub fn find(build: &mut Build) {
     }
 
     // For all host triples we need to find a C++ compiler as well
-    for host in build.config.host.iter() {
+    //
+    // This includes hosts that aren't necessarily passed on the commandline
+    // (FIXME: Perhaps it shouldn't?)
+    for host in &build.config.host {
         let mut cfg = gcc::Config::new();
         cfg.cargo_metadata(false).opt_level(0).debug(false).cpp(true)
-           .target(host).host(&build.config.build);
+           .target(host).host(&build.build);
         let config = build.config.target_config.get(host);
         if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
             cfg.compiler(cxx);
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 4664b1f765e..1153acfa57d 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -23,12 +23,12 @@ use build_helper::output;
 use Build;
 
 // The version number
-pub const CFG_RELEASE_NUM: &'static str = "1.20.0";
+pub const CFG_RELEASE_NUM: &str = "1.20.0";
 
 // An optional number to put after the label, e.g. '.2' -> '-beta.2'
 // Be sure to make this starts with a dot to conform to semver pre-release
 // versions (section 9)
-pub const CFG_PRERELEASE_VERSION: &'static str = ".1";
+pub const CFG_PRERELEASE_VERSION: &str = ".1";
 
 pub struct GitInfo {
     inner: Option<Info>,
@@ -99,6 +99,10 @@ impl GitInfo {
             version.push_str(&inner.commit_date);
             version.push_str(")");
         }
-        return version
+        version
+    }
+
+    pub fn is_git(&self) -> bool {
+        self.inner.is_some()
     }
 }
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 277728b90b7..b3b5ae8d67d 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -13,23 +13,22 @@
 //! This file implements the various regression test suites that we execute on
 //! our CI.
 
-extern crate build_helper;
-
 use std::collections::HashSet;
 use std::env;
+use std::iter;
 use std::fmt;
 use std::fs::{self, File};
 use std::path::{PathBuf, Path};
 use std::process::Command;
 use std::io::Read;
 
-use build_helper::output;
+use build_helper::{self, output};
 
 use {Build, Compiler, Mode};
 use dist;
 use util::{self, dylib_path, dylib_path_var, exe};
 
-const ADB_TEST_DIR: &'static str = "/data/tmp/work";
+const ADB_TEST_DIR: &str = "/data/tmp/work";
 
 /// The two modes of the test runner; tests or benchmarks.
 #[derive(Copy, Clone)]
@@ -60,7 +59,7 @@ impl fmt::Display for TestKind {
 }
 
 fn try_run(build: &Build, cmd: &mut Command) {
-    if build.flags.cmd.no_fail_fast() {
+    if !build.fail_fast {
         if !build.try_run(cmd) {
             let failures = build.delayed_failures.get();
             build.delayed_failures.set(failures + 1);
@@ -71,7 +70,7 @@ fn try_run(build: &Build, cmd: &mut Command) {
 }
 
 fn try_run_quiet(build: &Build, cmd: &mut Command) {
-    if build.flags.cmd.no_fail_fast() {
+    if !build.fail_fast {
         if !build.try_run_quiet(cmd) {
             let failures = build.delayed_failures.get();
             build.delayed_failures.set(failures + 1);
@@ -99,7 +98,7 @@ pub fn linkcheck(build: &Build, host: &str) {
 /// This tool in `src/tools` will check out a few Rust projects and run `cargo
 /// test` to ensure that we don't regress the test suites there.
 pub fn cargotest(build: &Build, stage: u32, host: &str) {
-    let ref compiler = Compiler::new(stage, host);
+    let compiler = Compiler::new(stage, host);
 
     // Note that this is a short, cryptic, and not scoped directory name. This
     // is currently to minimize the length of path on Windows where we otherwise
@@ -109,11 +108,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
 
     let _time = util::timeit();
     let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest"));
-    build.prepare_tool_cmd(compiler, &mut cmd);
-    try_run(build, cmd.arg(&build.cargo)
+    build.prepare_tool_cmd(&compiler, &mut cmd);
+    try_run(build, cmd.arg(&build.initial_cargo)
                       .arg(&out_dir)
-                      .env("RUSTC", build.compiler_path(compiler))
-                      .env("RUSTDOC", build.rustdoc(compiler)));
+                      .env("RUSTC", build.compiler_path(&compiler))
+                      .env("RUSTDOC", build.rustdoc(&compiler)));
 }
 
 /// Runs `cargo test` for `cargo` packaged with Rust.
@@ -124,13 +123,12 @@ pub fn cargo(build: &Build, stage: u32, host: &str) {
     // and not RUSTC because the Cargo test suite has tests that will
     // fail if rustc is not spelled `rustc`.
     let path = build.sysroot(compiler).join("bin");
-    let old_path = ::std::env::var("PATH").expect("");
-    let sep = if cfg!(windows) { ";" } else {":" };
-    let ref newpath = format!("{}{}{}", path.display(), sep, old_path);
+    let old_path = env::var_os("PATH").unwrap_or_default();
+    let newpath = env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("");
 
     let mut cargo = build.cargo(compiler, Mode::Tool, host, "test");
     cargo.arg("--manifest-path").arg(build.src.join("src/tools/cargo/Cargo.toml"));
-    if build.flags.cmd.no_fail_fast() {
+    if !build.fail_fast {
         cargo.arg("--no-fail-fast");
     }
 
@@ -198,9 +196,9 @@ pub fn compiletest(build: &Build,
     cmd.arg("--mode").arg(mode);
     cmd.arg("--target").arg(target);
     cmd.arg("--host").arg(compiler.host);
-    cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.config.build));
+    cmd.arg("--llvm-filecheck").arg(build.llvm_filecheck(&build.build));
 
-    if let Some(nodejs) = build.config.nodejs.as_ref() {
+    if let Some(ref nodejs) = build.config.nodejs {
         cmd.arg("--nodejs").arg(nodejs);
     }
 
@@ -224,7 +222,7 @@ pub fn compiletest(build: &Build,
 
     cmd.arg("--docck-python").arg(build.python());
 
-    if build.config.build.ends_with("apple-darwin") {
+    if build.build.ends_with("apple-darwin") {
         // Force /usr/bin/python on macOS for LLDB tests because we're loading the
         // LLDB plugin's compiled module which only works with the system python
         // (namely not Homebrew-installed python)
@@ -251,7 +249,7 @@ pub fn compiletest(build: &Build,
 
     cmd.args(&build.flags.cmd.test_args());
 
-    if build.config.verbose() || build.flags.verbose() {
+    if build.is_verbose() {
         cmd.arg("--verbose");
     }
 
@@ -279,7 +277,7 @@ pub fn compiletest(build: &Build,
 
     if build.remote_tested(target) {
         cmd.arg("--remote-test-client")
-           .arg(build.tool(&Compiler::new(0, &build.config.build),
+           .arg(build.tool(&Compiler::new(0, &build.build),
                            "remote-test-client"));
     }
 
@@ -368,7 +366,7 @@ pub fn error_index(build: &Build, compiler: &Compiler) {
                              "error_index_generator")
                    .arg("markdown")
                    .arg(&output)
-                   .env("CFG_BUILD", &build.config.build));
+                   .env("CFG_BUILD", &build.build));
 
     markdown_test(build, compiler, &output);
 }
@@ -450,7 +448,7 @@ pub fn krate(build: &Build,
     cargo.arg("--manifest-path")
          .arg(build.src.join(path).join("Cargo.toml"))
          .arg("--features").arg(features);
-    if test_kind.subcommand() == "test" && build.flags.cmd.no_fail_fast() {
+    if test_kind.subcommand() == "test" && !build.fail_fast {
         cargo.arg("--no-fail-fast");
     }
 
@@ -520,16 +518,14 @@ fn krate_emscripten(build: &Build,
                     compiler: &Compiler,
                     target: &str,
                     mode: Mode) {
-    let mut tests = Vec::new();
     let out_dir = build.cargo_out(compiler, mode, target);
-    find_tests(&out_dir.join("deps"), target, &mut tests);
+    let tests = find_tests(&out_dir.join("deps"), target);
 
+    let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
     for test in tests {
-        let test_file_name = test.to_string_lossy().into_owned();
-        println!("running {}", test_file_name);
-        let nodejs = build.config.nodejs.as_ref().expect("nodejs not configured");
+        println!("running {}", test.display());
         let mut cmd = Command::new(nodejs);
-        cmd.arg(&test_file_name);
+        cmd.arg(&test);
         if build.config.quiet_tests {
             cmd.arg("--quiet");
         }
@@ -541,11 +537,10 @@ fn krate_remote(build: &Build,
                 compiler: &Compiler,
                 target: &str,
                 mode: Mode) {
-    let mut tests = Vec::new();
     let out_dir = build.cargo_out(compiler, mode, target);
-    find_tests(&out_dir.join("deps"), target, &mut tests);
+    let tests = find_tests(&out_dir.join("deps"), target);
 
-    let tool = build.tool(&Compiler::new(0, &build.config.build),
+    let tool = build.tool(&Compiler::new(0, &build.build),
                           "remote-test-client");
     for test in tests {
         let mut cmd = Command::new(&tool);
@@ -559,9 +554,8 @@ fn krate_remote(build: &Build,
     }
 }
 
-fn find_tests(dir: &Path,
-              target: &str,
-              dst: &mut Vec<PathBuf>) {
+fn find_tests(dir: &Path, target: &str) -> Vec<PathBuf> {
+    let mut dst = Vec::new();
     for e in t!(dir.read_dir()).map(|e| t!(e)) {
         let file_type = t!(e.file_type());
         if !file_type.is_file() {
@@ -576,6 +570,7 @@ fn find_tests(dir: &Path,
             dst.push(e.path());
         }
     }
+    dst
 }
 
 pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
@@ -590,7 +585,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
                       .join(exe("remote-test-server", target));
 
     // Spawn the emulator and wait for it to come online
-    let tool = build.tool(&Compiler::new(0, &build.config.build),
+    let tool = build.tool(&Compiler::new(0, &build.build),
                           "remote-test-client");
     let mut cmd = Command::new(&tool);
     cmd.arg("spawn-emulator")
@@ -616,7 +611,7 @@ pub fn remote_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
 
 /// Run "distcheck", a 'make check' from a tarball
 pub fn distcheck(build: &Build) {
-    if build.config.build != "x86_64-unknown-linux-gnu" {
+    if build.build != "x86_64-unknown-linux-gnu" {
         return
     }
     if !build.config.host.iter().any(|s| s == "x86_64-unknown-linux-gnu") {
@@ -641,7 +636,7 @@ pub fn distcheck(build: &Build) {
                      .args(&build.config.configure_args)
                      .arg("--enable-vendor")
                      .current_dir(&dir));
-    build.run(Command::new(build_helper::make(&build.config.build))
+    build.run(Command::new(build_helper::make(&build.build))
                      .arg("check")
                      .current_dir(&dir));
 
@@ -659,7 +654,7 @@ pub fn distcheck(build: &Build) {
     build.run(&mut cmd);
 
     let toml = dir.join("rust-src/lib/rustlib/src/rust/src/libstd/Cargo.toml");
-    build.run(Command::new(&build.cargo)
+    build.run(Command::new(&build.initial_cargo)
                      .arg("generate-lockfile")
                      .arg("--manifest-path")
                      .arg(&toml)
@@ -668,13 +663,13 @@ pub fn distcheck(build: &Build) {
 
 /// Test the build system itself
 pub fn bootstrap(build: &Build) {
-    let mut cmd = Command::new(&build.cargo);
+    let mut cmd = Command::new(&build.initial_cargo);
     cmd.arg("test")
        .current_dir(build.src.join("src/bootstrap"))
        .env("CARGO_TARGET_DIR", build.out.join("bootstrap"))
        .env("RUSTC_BOOTSTRAP", "1")
-       .env("RUSTC", &build.rustc);
-    if build.flags.cmd.no_fail_fast() {
+       .env("RUSTC", &build.initial_rustc);
+    if !build.fail_fast {
         cmd.arg("--no-fail-fast");
     }
     cmd.arg("--").args(&build.flags.cmd.test_args());
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index c8ab3a8fc1d..5a3106c7d5e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -50,7 +50,7 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) {
     let mut cargo = build.cargo(compiler, Mode::Libstd, target, "build");
     let mut features = build.std_features();
 
-    if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") {
+    if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
 
@@ -158,7 +158,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st
         return
     }
 
-    let compiler = Compiler::new(0, &build.config.build);
+    let compiler = Compiler::new(0, &build.build);
     let compiler_path = build.compiler_path(&compiler);
     let src_dir = &build.src.join("src/rtstartup");
     let dst_dir = &build.native_dir(target).join("rtstartup");
@@ -199,7 +199,7 @@ pub fn test(build: &Build, target: &str, compiler: &Compiler) {
     let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
     build.clear_if_dirty(&out_dir, &libstd_stamp(build, compiler, target));
     let mut cargo = build.cargo(compiler, Mode::Libtest, target, "build");
-    if let Ok(target) = env::var("MACOSX_STD_DEPLOYMENT_TARGET") {
+    if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") {
         cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
     }
     cargo.arg("--manifest-path")
@@ -247,7 +247,7 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
     cargo.env("CFG_RELEASE", build.rust_release())
          .env("CFG_RELEASE_CHANNEL", &build.config.channel)
          .env("CFG_VERSION", build.rust_version())
-         .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or(PathBuf::new()));
+         .env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
 
     if compiler.stage == 0 {
         cargo.env("CFG_LIBDIR_RELATIVE", "lib");
@@ -276,10 +276,6 @@ pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
     if build.is_rust_llvm(target) {
         cargo.env("LLVM_RUSTLLVM", "1");
     }
-    if let Some(ref cfg_file) = build.flags.config {
-        let cfg_path = t!(PathBuf::from(cfg_file).canonicalize());
-        cargo.env("CFG_LLVM_TOML", cfg_path.into_os_string());
-    }
     cargo.env("LLVM_CONFIG", build.llvm_config(target));
     let target_config = build.config.target_config.get(target);
     if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
@@ -355,7 +351,7 @@ pub fn create_sysroot(build: &Build, compiler: &Compiler) {
 /// Prepare a new compiler from the artifacts in `stage`
 ///
 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
-/// must have been previously produced by the `stage - 1` build.config.build
+/// must have been previously produced by the `stage - 1` build.build
 /// compiler.
 pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
     // nothing to do in stage0
@@ -369,7 +365,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
     let target_compiler = Compiler::new(stage, host);
 
     // The compiler that compiled the compiler we're assembling
-    let build_compiler = Compiler::new(stage - 1, &build.config.build);
+    let build_compiler = Compiler::new(stage - 1, &build.build);
 
     // Link in all dylibs to the libdir
     let sysroot = build.sysroot(&target_compiler);
@@ -389,7 +385,7 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
     let rustc = out_dir.join(exe("rustc", host));
     let bindir = sysroot.join("bin");
     t!(fs::create_dir_all(&bindir));
-    let compiler = build.compiler_path(&Compiler::new(stage, host));
+    let compiler = build.compiler_path(&target_compiler);
     let _ = fs::remove_file(&compiler);
     copy(&rustc, &compiler);
 
@@ -411,6 +407,8 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
     t!(fs::create_dir_all(&sysroot_dst));
     let mut contents = Vec::new();
     t!(t!(File::open(stamp)).read_to_end(&mut contents));
+    // This is the method we use for extracting paths from the stamp file passed to us. See
+    // run_cargo for more information (in this file).
     for part in contents.split(|b| *b == 0) {
         if part.is_empty() {
             continue
@@ -425,7 +423,7 @@ fn add_to_sysroot(sysroot_dst: &Path, stamp: &Path) {
 /// This will build the specified tool with the specified `host` compiler in
 /// `stage` into the normal cargo output directory.
 pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) {
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(stage, &build.build);
 
     let stamp = match mode {
         Mode::Libstd => libstd_stamp(build, &compiler, target),
@@ -445,7 +443,7 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
     let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool));
     println!("Building stage{} tool {} ({})", stage, tool, target);
 
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(stage, &build.build);
 
     let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build");
     let dir = build.src.join("src/tools").join(tool);
@@ -561,23 +559,24 @@ fn run_cargo(build: &Build, cargo: &mut Command, stamp: &Path) {
             // If this was an output file in the "host dir" we don't actually
             // worry about it, it's not relevant for us.
             if filename.starts_with(&host_root_dir) {
-                continue
+                continue;
+            }
 
             // If this was output in the `deps` dir then this is a precise file
             // name (hash included) so we start tracking it.
-            } else if filename.starts_with(&target_deps_dir) {
+            if filename.starts_with(&target_deps_dir) {
                 deps.push(filename.to_path_buf());
+                continue;
+            }
 
             // Otherwise this was a "top level artifact" which right now doesn't
             // have a hash in the name, but there's a version of this file in
             // the `deps` folder which *does* have a hash in the name. That's
             // the one we'll want to we'll probe for it later.
-            } else {
-                toplevel.push((filename.file_stem().unwrap()
-                                       .to_str().unwrap().to_string(),
-                               filename.extension().unwrap().to_owned()
-                                       .to_str().unwrap().to_string()));
-            }
+            toplevel.push((filename.file_stem().unwrap()
+                                    .to_str().unwrap().to_string(),
+                            filename.extension().unwrap().to_owned()
+                                    .to_str().unwrap().to_string()));
         }
     }
 
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 3ada846e382..34628852ab3 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -81,8 +81,6 @@ pub struct Config {
     pub build: String,
     pub host: Vec<String>,
     pub target: Vec<String>,
-    pub rustc: Option<PathBuf>,
-    pub cargo: Option<PathBuf>,
     pub local_rebuild: bool,
 
     // dist misc
@@ -114,11 +112,18 @@ pub struct Config {
     pub python: Option<PathBuf>,
     pub configure_args: Vec<String>,
     pub openssl_static: bool,
+
+
+    // 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.
 #[derive(Default)]
 pub struct Target {
+    /// Some(path to llvm-config) if using an external LLVM.
     pub llvm_config: Option<PathBuf>,
     pub jemalloc: Option<PathBuf>,
     pub cc: Option<PathBuf>,
@@ -307,8 +312,6 @@ impl Config {
                 config.target.push(target.clone());
             }
         }
-        config.rustc = build.rustc.map(PathBuf::from);
-        config.cargo = build.cargo.map(PathBuf::from);
         config.nodejs = build.nodejs.map(PathBuf::from);
         config.gdb = build.gdb.map(PathBuf::from);
         config.python = build.python.map(PathBuf::from);
@@ -410,13 +413,25 @@ impl Config {
             set(&mut config.rust_dist_src, t.src_tarball);
         }
 
+        let cwd = t!(env::current_dir());
+        let out = cwd.join("build");
+
+        let stage0_root = out.join(&config.build).join("stage0/bin");
+        config.initial_rustc = match build.rustc {
+            Some(s) => PathBuf::from(s),
+            None => stage0_root.join(exe("rustc", &config.build)),
+        };
+        config.initial_cargo = match build.cargo {
+            Some(s) => PathBuf::from(s),
+            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();
         }
 
-        return config
+        config
     }
 
     /// "Temporary" routine to parse `config.mk` into this configuration.
@@ -609,8 +624,8 @@ impl Config {
                 }
                 "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => {
                     let path = parse_configure_path(value);
-                    self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"]));
-                    self.cargo = Some(push_exe_path(path, &["bin", "cargo"]));
+                    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);
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 753bd1df0d8..efc33bcee9b 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -50,7 +50,7 @@ pub fn tmpdir(build: &Build) -> PathBuf {
 }
 
 fn rust_installer(build: &Build) -> Command {
-    build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer")
+    build.tool_cmd(&Compiler::new(0, &build.build), "rust-installer")
 }
 
 /// Builds the `rust-docs` installer component.
@@ -89,7 +89,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) {
 
     // As part of this step, *also* copy the docs directory to a directory which
     // buildbot typically uploads.
-    if host == build.config.build {
+    if host == build.build {
         let dst = distdir(build).join("doc").join(build.rust_package_vers());
         t!(fs::create_dir_all(&dst));
         cp_r(&src, &dst);
@@ -97,7 +97,7 @@ pub fn docs(build: &Build, stage: u32, host: &str) {
 }
 
 fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
-    let mut found = Vec::new();
+    let mut found = Vec::with_capacity(files.len());
 
     for file in files {
         let file_path =
@@ -119,17 +119,9 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
     //Ask gcc where it keeps its stuff
     let mut cmd = Command::new(build.cc(target_triple));
     cmd.arg("-print-search-dirs");
-    build.run_quiet(&mut cmd);
-    let gcc_out =
-        String::from_utf8(
-                cmd
-                .output()
-                .expect("failed to execute gcc")
-                .stdout).expect("gcc.exe output was not utf8");
-
-    let mut bin_path: Vec<_> =
-        env::split_paths(&env::var_os("PATH").unwrap_or_default())
-        .collect();
+    let gcc_out = output(&mut cmd);
+
+    let mut bin_path: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap_or_default()).collect();
     let mut lib_path = Vec::new();
 
     for line in gcc_out.lines() {
@@ -140,7 +132,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
             line[(idx + 1)..]
                 .trim_left_matches(trim_chars)
                 .split(';')
-                .map(|s| PathBuf::from(s));
+                .map(PathBuf::from);
 
         if key == "programs" {
             bin_path.extend(value);
@@ -149,7 +141,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
         }
     }
 
-    let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"];
+    let target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"];
     let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"];
     if target_triple.starts_with("i686-") {
         rustc_dlls.push("libgcc_s_dw2-1.dll");
@@ -157,7 +149,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
         rustc_dlls.push("libgcc_s_seh-1.dll");
     }
 
-    let target_libs = vec![ //MinGW libs
+    let target_libs = [ //MinGW libs
         "libgcc.a",
         "libgcc_eh.a",
         "libgcc_s.a",
@@ -203,7 +195,7 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
     let target_libs = find_files(&target_libs, &lib_path);
 
     fn copy_to_folder(src: &Path, dest_folder: &Path) {
-        let file_name = src.file_name().unwrap().to_os_string();
+        let file_name = src.file_name().unwrap();
         let dest = dest_folder.join(file_name);
         copy(src, &dest);
     }
@@ -234,8 +226,6 @@ fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build:
 ///
 /// This contains all the bits and pieces to run the MinGW Windows targets
 /// without any extra installed software (e.g. we bundle gcc, libraries, etc).
-/// Currently just shells out to a python script, but that should be rewritten
-/// in Rust.
 pub fn mingw(build: &Build, host: &str) {
     println!("Dist mingw ({})", host);
     let name = pkgname(build, "rust-mingw");
@@ -366,9 +356,9 @@ pub fn rustc(build: &Build, stage: u32, host: &str) {
 pub fn debugger_scripts(build: &Build,
                         sysroot: &Path,
                         host: &str) {
+    let dst = sysroot.join("lib/rustlib/etc");
+    t!(fs::create_dir_all(&dst));
     let cp_debugger_script = |file: &str| {
-        let dst = sysroot.join("lib/rustlib/etc");
-        t!(fs::create_dir_all(&dst));
         install(&build.src.join("src/etc/").join(file), &dst, 0o644);
     };
     if host.contains("windows-msvc") {
@@ -404,7 +394,7 @@ pub fn std(build: &Build, compiler: &Compiler, target: &str) {
 
     // The only true set of target libraries came from the build triple, so
     // let's reduce redundant work by only producing archives from that host.
-    if compiler.host != build.config.build {
+    if compiler.host != build.build {
         println!("\tskipping, not a build host");
         return
     }
@@ -450,7 +440,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
     assert!(build.config.extended);
     println!("Dist analysis");
 
-    if compiler.host != build.config.build {
+    if compiler.host != build.build {
         println!("\tskipping, not a build host");
         return;
     }
@@ -498,12 +488,11 @@ fn copy_src_dirs(build: &Build, src_dirs: &[&str], exclude_dirs: &[&str], dst_di
         if spath.ends_with("~") || spath.ends_with(".pyc") {
             return false
         }
-        if spath.contains("llvm/test") || spath.contains("llvm\\test") {
-            if spath.ends_with(".ll") ||
-               spath.ends_with(".td") ||
-               spath.ends_with(".s") {
-                return false
-            }
+        if (spath.contains("llvm/test") || spath.contains("llvm\\test")) &&
+            (spath.ends_with(".ll") ||
+             spath.ends_with(".td") ||
+             spath.ends_with(".s")) {
+            return false
         }
 
         let full_path = Path::new(dir).join(path);
@@ -595,7 +584,7 @@ pub fn rust_src(build: &Build) {
     t!(fs::remove_dir_all(&image));
 }
 
-const CARGO_VENDOR_VERSION: &'static str = "0.1.4";
+const CARGO_VENDOR_VERSION: &str = "0.1.4";
 
 /// Creates the plain source tarball
 pub fn plain_source_tarball(build: &Build) {
@@ -634,26 +623,26 @@ pub fn plain_source_tarball(build: &Build) {
     write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes());
 
     // If we're building from git sources, we need to vendor a complete distribution.
-    if build.src_is_git {
+    if build.rust_info.is_git() {
         // Get cargo-vendor installed, if it isn't already.
         let mut has_cargo_vendor = false;
-        let mut cmd = Command::new(&build.cargo);
+        let mut cmd = Command::new(&build.initial_cargo);
         for line in output(cmd.arg("install").arg("--list")).lines() {
             has_cargo_vendor |= line.starts_with("cargo-vendor ");
         }
         if !has_cargo_vendor {
-            let mut cmd = Command::new(&build.cargo);
+            let mut cmd = Command::new(&build.initial_cargo);
             cmd.arg("install")
                .arg("--force")
                .arg("--debug")
                .arg("--vers").arg(CARGO_VENDOR_VERSION)
                .arg("cargo-vendor")
-               .env("RUSTC", &build.rustc);
+               .env("RUSTC", &build.initial_rustc);
             build.run(&mut cmd);
         }
 
         // Vendor all Cargo dependencies
-        let mut cmd = Command::new(&build.cargo);
+        let mut cmd = Command::new(&build.initial_cargo);
         cmd.arg("vendor")
            .current_dir(&plain_dst_src.join("src"));
         build.run(&mut cmd);
@@ -716,7 +705,7 @@ fn write_file(path: &Path, data: &[u8]) {
 
 pub fn cargo(build: &Build, stage: u32, target: &str) {
     println!("Dist cargo stage{} ({})", stage, target);
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(stage, &build.build);
 
     let src = build.src.join("src/tools/cargo");
     let etc = src.join("src/etc");
@@ -777,7 +766,7 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
 pub fn rls(build: &Build, stage: u32, target: &str) {
     assert!(build.config.extended);
     println!("Dist RLS stage{} ({})", stage, target);
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(stage, &build.build);
 
     let src = build.src.join("src/tools/rls");
     let release_num = build.release_num("rls");
@@ -1209,7 +1198,7 @@ fn add_env(build: &Build, cmd: &mut Command, target: &str) {
 }
 
 pub fn hash_and_sign(build: &Build) {
-    let compiler = Compiler::new(0, &build.config.build);
+    let compiler = Compiler::new(0, &build.build);
     let mut cmd = build.tool_cmd(&compiler, "build-manifest");
     let sign = build.config.dist_sign_folder.as_ref().unwrap_or_else(|| {
         panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n")
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 30f631ca2df..7dbc3e55539 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -45,7 +45,7 @@ pub fn rustbook_src(build: &Build, target: &str, name: &str, src: &Path) {
     t!(fs::create_dir_all(&out));
 
     let out = out.join(name);
-    let compiler = Compiler::new(0, &build.config.build);
+    let compiler = Compiler::new(0, &build.build);
     let src = src.join(name);
     let index = out.join("index.html");
     let rustbook = build.tool(&compiler, "rustbook");
@@ -95,7 +95,7 @@ pub fn book(build: &Build, target: &str, name: &str) {
 fn invoke_rustdoc(build: &Build, target: &str, markdown: &str) {
     let out = build.doc_out(target);
 
-    let compiler = Compiler::new(0, &build.config.build);
+    let compiler = Compiler::new(0, &build.build);
 
     let path = build.src.join("src/doc").join(markdown);
 
@@ -150,7 +150,7 @@ pub fn standalone(build: &Build, target: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
 
-    let compiler = Compiler::new(0, &build.config.build);
+    let compiler = Compiler::new(0, &build.build);
 
     let favicon = build.src.join("src/doc/favicon.inc");
     let footer = build.src.join("src/doc/footer.inc");
@@ -217,7 +217,7 @@ pub fn std(build: &Build, stage: u32, target: &str) {
     println!("Documenting stage{} std ({})", stage, target);
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(stage, &build.build);
     let compiler = if build.force_use_stage1(&compiler, target) {
         Compiler::new(1, compiler.host)
     } else {
@@ -276,7 +276,7 @@ pub fn test(build: &Build, stage: u32, target: &str) {
     println!("Documenting stage{} test ({})", stage, target);
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(stage, &build.build);
     let compiler = if build.force_use_stage1(&compiler, target) {
         Compiler::new(1, compiler.host)
     } else {
@@ -306,7 +306,7 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
     println!("Documenting stage{} compiler ({})", stage, target);
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(stage, &build.build);
     let compiler = if build.force_use_stage1(&compiler, target) {
         Compiler::new(1, compiler.host)
     } else {
@@ -351,13 +351,13 @@ pub fn error_index(build: &Build, target: &str) {
     println!("Documenting error index ({})", target);
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
-    let compiler = Compiler::new(0, &build.config.build);
+    let compiler = Compiler::new(0, &build.build);
     let mut index = build.tool_cmd(&compiler, "error_index_generator");
     index.arg("html");
     index.arg(out.join("error-index.html"));
 
     // FIXME: shouldn't have to pass this env var
-    index.env("CFG_BUILD", &build.config.build);
+    index.env("CFG_BUILD", &build.build);
 
     build.run(&mut index);
 }
@@ -367,7 +367,7 @@ pub fn unstable_book_gen(build: &Build, target: &str) {
     let out = build.md_doc_out(target).join("unstable-book");
     t!(fs::create_dir_all(&out));
     t!(fs::remove_dir_all(&out));
-    let compiler = Compiler::new(0, &build.config.build);
+    let compiler = Compiler::new(0, &build.build);
     let mut cmd = build.tool_cmd(&compiler, "unstable-book-gen");
     cmd.arg(build.src.join("src"));
     cmd.arg(out);
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index dc9dac73627..5804df34e8b 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -35,22 +35,12 @@ pub struct Flags {
     pub host: Vec<String>,
     pub target: Vec<String>,
     pub config: Option<PathBuf>,
-    pub src: Option<PathBuf>,
+    pub src: PathBuf,
     pub jobs: Option<u32>,
     pub cmd: Subcommand,
     pub incremental: bool,
 }
 
-impl Flags {
-    pub fn verbose(&self) -> bool {
-        self.verbose > 0
-    }
-
-    pub fn very_verbose(&self) -> bool {
-        self.verbose > 1
-    }
-}
-
 pub enum Subcommand {
     Build {
         paths: Vec<PathBuf>,
@@ -61,7 +51,7 @@ pub enum Subcommand {
     Test {
         paths: Vec<PathBuf>,
         test_args: Vec<String>,
-        no_fail_fast: bool,
+        fail_fast: bool,
     },
     Bench {
         paths: Vec<PathBuf>,
@@ -122,16 +112,15 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
         // the subcommand. Therefore we must manually identify the subcommand first, so that we can
         // complete the definition of the options.  Then we can use the getopt::Matches object from
         // there on out.
-        let mut possible_subcommands = args.iter().collect::<Vec<_>>();
-        possible_subcommands.retain(|&s|
-                                           (s == "build")
-                                        || (s == "test")
-                                        || (s == "bench")
-                                        || (s == "doc")
-                                        || (s == "clean")
-                                        || (s == "dist")
-                                        || (s == "install"));
-        let subcommand = match possible_subcommands.first() {
+        let subcommand = args.iter().find(|&s|
+            (s == "build")
+            || (s == "test")
+            || (s == "bench")
+            || (s == "doc")
+            || (s == "clean")
+            || (s == "dist")
+            || (s == "install"));
+        let subcommand = match subcommand {
             Some(s) => s,
             None => {
                 // No subcommand -- show the general usage and subcommand help
@@ -164,7 +153,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
         let mut pass_sanity_check = true;
         match matches.free.get(0) {
             Some(check_subcommand) => {
-                if &check_subcommand != subcommand {
+                if check_subcommand != subcommand {
                     pass_sanity_check = false;
                 }
             },
@@ -279,7 +268,7 @@ Arguments:
                 Subcommand::Test {
                     paths: paths,
                     test_args: matches.opt_strs("test-args"),
-                    no_fail_fast: matches.opt_present("no-fail-fast"),
+                    fail_fast: !matches.opt_present("no-fail-fast"),
                 }
             }
             "bench" => {
@@ -316,12 +305,15 @@ Arguments:
 
         let mut stage = matches.opt_str("stage").map(|j| j.parse().unwrap());
 
-        if matches.opt_present("incremental") {
-            if stage.is_none() {
-                stage = Some(1);
-            }
+        if matches.opt_present("incremental") && stage.is_none() {
+            stage = Some(1);
         }
 
+        let cwd = t!(env::current_dir());
+        let src = matches.opt_str("src").map(PathBuf::from)
+            .or_else(|| env::var_os("SRC").map(PathBuf::from))
+            .unwrap_or(cwd);
+
         Flags {
             verbose: matches.opt_count("verbose"),
             stage: stage,
@@ -333,7 +325,7 @@ Arguments:
             host: split(matches.opt_strs("host")),
             target: split(matches.opt_strs("target")),
             config: cfg_file,
-            src: matches.opt_str("src").map(PathBuf::from),
+            src: src,
             jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()),
             cmd: cmd,
             incremental: matches.opt_present("incremental"),
@@ -352,9 +344,9 @@ impl Subcommand {
         }
     }
 
-    pub fn no_fail_fast(&self) -> bool {
+    pub fn fail_fast(&self) -> bool {
         match *self {
-            Subcommand::Test { no_fail_fast, .. } => no_fail_fast,
+            Subcommand::Test { fail_fast, .. } => fail_fast,
             _ => false,
         }
     }
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 21e21628dc9..8e2ef527b16 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -146,5 +146,5 @@ fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
             _ => {}
         }
     }
-    return ret
+    ret
 }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index ce7cde8fc94..69b0c4a2756 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -161,25 +161,35 @@ pub struct Build {
     flags: Flags,
 
     // Derived properties from the above two configurations
-    cargo: PathBuf,
-    rustc: PathBuf,
     src: PathBuf,
     out: PathBuf,
     rust_info: channel::GitInfo,
     cargo_info: channel::GitInfo,
     rls_info: channel::GitInfo,
     local_rebuild: bool,
+    fail_fast: bool,
+    verbosity: usize,
+
+    // Targets for which to build.
+    build: String,
+    hosts: Vec<String>,
+    targets: Vec<String>,
+
+    // Stage 0 (downloaded) compiler and cargo or their local rust equivalents.
+    initial_rustc: PathBuf,
+    initial_cargo: PathBuf,
 
     // Probed tools at runtime
     lldb_version: Option<String>,
     lldb_python_dir: Option<String>,
 
     // Runtime state filled in later on
+    // target -> (cc, ar)
     cc: HashMap<String, (gcc::Tool, Option<PathBuf>)>,
+    // host -> (cc, ar)
     cxx: HashMap<String, gcc::Tool>,
     crates: HashMap<String, Crate>,
     is_sudo: bool,
-    src_is_git: bool,
     ci_env: CiEnv,
     delayed_failures: Cell<usize>,
 }
@@ -202,20 +212,16 @@ struct Crate {
 /// build system, with each mod generating output in a different directory.
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub enum Mode {
-    /// This cargo is going to build the standard library, placing output in the
-    /// "stageN-std" directory.
+    /// Build the standard library, placing output in the "stageN-std" directory.
     Libstd,
 
-    /// This cargo is going to build libtest, placing output in the
-    /// "stageN-test" directory.
+    /// Build libtest, placing output in the "stageN-test" directory.
     Libtest,
 
-    /// This cargo is going to build librustc and compiler libraries, placing
-    /// output in the "stageN-rustc" directory.
+    /// Build librustc and compiler libraries, placing output in the "stageN-rustc" directory.
     Librustc,
 
-    /// This cargo is going to build some tool, placing output in the
-    /// "stageN-tools" directory.
+    /// Build some tool, placing output in the "stageN-tools" directory.
     Tool,
 }
 
@@ -226,22 +232,9 @@ impl Build {
     /// By default all build output will be placed in the current directory.
     pub fn new(flags: Flags, config: Config) -> Build {
         let cwd = t!(env::current_dir());
-        let src = flags.src.clone().or_else(|| {
-            env::var_os("SRC").map(|x| x.into())
-        }).unwrap_or(cwd.clone());
+        let src = flags.src.clone();
         let out = cwd.join("build");
 
-        let stage0_root = out.join(&config.build).join("stage0/bin");
-        let rustc = match config.rustc {
-            Some(ref s) => PathBuf::from(s),
-            None => stage0_root.join(exe("rustc", &config.build)),
-        };
-        let cargo = match config.cargo {
-            Some(ref s) => PathBuf::from(s),
-            None => stage0_root.join(exe("cargo", &config.build)),
-        };
-        let local_rebuild = config.local_rebuild;
-
         let is_sudo = match env::var_os("SUDO_USER") {
             Some(sudo_user) => {
                 match env::var_os("USER") {
@@ -254,32 +247,64 @@ impl Build {
         let rust_info = channel::GitInfo::new(&src);
         let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo"));
         let rls_info = channel::GitInfo::new(&src.join("src/tools/rls"));
-        let src_is_git = src.join(".git").exists();
+
+        let hosts = if !flags.host.is_empty() {
+            for host in flags.host.iter() {
+                if !config.host.contains(host) {
+                    panic!("specified host `{}` is not in configuration", host);
+                }
+            }
+            flags.host.clone()
+        } else {
+            config.host.clone()
+        };
+        let targets = if !flags.target.is_empty() {
+            for target in flags.target.iter() {
+                if !config.target.contains(target) {
+                    panic!("specified target `{}` is not in configuration", target);
+                }
+            }
+            flags.target.clone()
+        } else {
+            config.target.clone()
+        };
 
         Build {
+            initial_rustc: config.initial_rustc.clone(),
+            initial_cargo: config.initial_cargo.clone(),
+            local_rebuild: config.local_rebuild,
+            fail_fast: flags.cmd.fail_fast(),
+            verbosity: cmp::max(flags.verbose, config.verbose),
+
+            build: config.host[0].clone(),
+            hosts: hosts,
+            targets: targets,
+
             flags: flags,
             config: config,
-            cargo: cargo,
-            rustc: rustc,
             src: src,
             out: out,
 
             rust_info: rust_info,
             cargo_info: cargo_info,
             rls_info: rls_info,
-            local_rebuild: local_rebuild,
             cc: HashMap::new(),
             cxx: HashMap::new(),
             crates: HashMap::new(),
             lldb_version: None,
             lldb_python_dir: None,
             is_sudo: is_sudo,
-            src_is_git: src_is_git,
             ci_env: CiEnv::current(),
             delayed_failures: Cell::new(0),
         }
     }
 
+    fn build_slice(&self) -> &[String] {
+        unsafe {
+            std::slice::from_raw_parts(&self.build, 1)
+        }
+    }
+
     /// Executes the entire build, as configured by the flags and configuration.
     pub fn build(&mut self) {
         unsafe {
@@ -296,7 +321,7 @@ impl Build {
         sanity::check(self);
         // If local-rust is the same major.minor as the current version, then force a local-rebuild
         let local_version_verbose = output(
-            Command::new(&self.rustc).arg("--version").arg("--verbose"));
+            Command::new(&self.initial_rustc).arg("--version").arg("--verbose"));
         let local_release = local_version_verbose
             .lines().filter(|x| x.starts_with("release:"))
             .next().unwrap().trim_left_matches("release:").trim();
@@ -338,7 +363,7 @@ impl Build {
              mode: Mode,
              target: &str,
              cmd: &str) -> Command {
-        let mut cargo = Command::new(&self.cargo);
+        let mut cargo = Command::new(&self.initial_cargo);
         let out_dir = self.stage_out(compiler, mode);
         cargo.env("CARGO_TARGET_DIR", out_dir)
              .arg(cmd)
@@ -347,7 +372,7 @@ impl Build {
 
         // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005
         // Force cargo to output binaries with disambiguating hashes in the name
-        cargo.env("__CARGO_DEFAULT_LIB_METADATA", "1");
+        cargo.env("__CARGO_DEFAULT_LIB_METADATA", &self.config.channel);
 
         let stage;
         if compiler.stage == 0 && self.local_rebuild {
@@ -422,7 +447,7 @@ impl Build {
         // library up and running, so we can use the normal compiler to compile
         // build scripts in that situation.
         if mode == Mode::Libstd {
-            cargo.env("RUSTC_SNAPSHOT", &self.rustc)
+            cargo.env("RUSTC_SNAPSHOT", &self.initial_rustc)
                  .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir());
         } else {
             cargo.env("RUSTC_SNAPSHOT", self.compiler_path(compiler))
@@ -441,8 +466,7 @@ impl Build {
             cargo.env("RUSTC_ON_FAIL", on_fail);
         }
 
-        let verbose = cmp::max(self.config.verbose, self.flags.verbose);
-        cargo.env("RUSTC_VERBOSE", format!("{}", verbose));
+        cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
 
         // Specify some various options for build scripts used throughout
         // the build.
@@ -480,7 +504,7 @@ impl Build {
         // FIXME: should update code to not require this env var
         cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
 
-        if self.config.verbose() || self.flags.verbose() {
+        if self.is_verbose() {
             cargo.arg("-v");
         }
         // FIXME: cargo bench does not accept `--release`
@@ -496,13 +520,13 @@ impl Build {
 
         self.ci_env.force_coloring_in_ci(&mut cargo);
 
-        return cargo
+        cargo
     }
 
     /// Get a path to the compiler specified.
     fn compiler_path(&self, compiler: &Compiler) -> PathBuf {
         if compiler.is_snapshot(self) {
-            self.rustc.clone()
+            self.initial_rustc.clone()
         } else {
             self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host))
         }
@@ -519,7 +543,7 @@ impl Build {
         let mut rustdoc = self.compiler_path(compiler);
         rustdoc.pop();
         rustdoc.push(exe("rustdoc", compiler.host));
-        return rustdoc
+        rustdoc
     }
 
     /// Get a `Command` which is ready to run `tool` in `stage` built for
@@ -527,7 +551,7 @@ impl Build {
     fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command {
         let mut cmd = Command::new(self.tool(&compiler, tool));
         self.prepare_tool_cmd(compiler, &mut cmd);
-        return cmd
+        cmd
     }
 
     /// Prepares the `cmd` provided to be able to run the `compiler` provided.
@@ -578,7 +602,7 @@ impl Build {
         if self.config.profiler {
             features.push_str(" profiler");
         }
-        return features
+        features
     }
 
     /// Get the space-separated set of activated features for the compiler.
@@ -587,7 +611,7 @@ impl Build {
         if self.config.use_jemalloc {
             features.push_str(" jemalloc");
         }
-        return features
+        features
     }
 
     /// Component directory that Cargo will produce output into (e.g.
@@ -760,7 +784,7 @@ impl Build {
 
     /// Returns the libdir of the snapshot compiler.
     fn rustc_snapshot_libdir(&self) -> PathBuf {
-        self.rustc.parent().unwrap().parent().unwrap()
+        self.initial_rustc.parent().unwrap().parent().unwrap()
             .join(libdir(&self.config.build))
     }
 
@@ -792,9 +816,17 @@ impl Build {
         try_run_suppressed(cmd)
     }
 
+    pub fn is_verbose(&self) -> bool {
+        self.verbosity > 0
+    }
+
+    pub fn is_very_verbose(&self) -> bool {
+        self.verbosity > 1
+    }
+
     /// Prints a message if this build is configured in verbose mode.
     fn verbose(&self, msg: &str) {
-        if self.flags.verbose() || self.config.verbose() {
+        if self.is_verbose() {
             println!("{}", msg);
         }
     }
@@ -802,7 +834,7 @@ impl Build {
     /// Returns the number of parallel jobs that have been configured for this
     /// build.
     fn jobs(&self) -> u32 {
-        self.flags.jobs.unwrap_or(num_cpus::get() as u32)
+        self.flags.jobs.unwrap_or_else(|| num_cpus::get() as u32)
     }
 
     /// Returns the path to the C compiler for the target specified.
@@ -834,7 +866,7 @@ impl Build {
         if target == "i686-pc-windows-gnu" {
             base.push("-fno-omit-frame-pointer".into());
         }
-        return base
+        base
     }
 
     /// Returns the path to the `ar` archive utility for the target specified.
@@ -866,7 +898,7 @@ impl Build {
             !target.contains("emscripten") {
             base.push(format!("-Clinker={}", self.cc(target).display()));
         }
-        return base
+        base
     }
 
     /// Returns the "musl root" for this `target`, if defined
@@ -1047,7 +1079,7 @@ impl<'a> Compiler<'a> {
 
     /// Returns whether this is a snapshot compiler for `build`'s configuration
     fn is_snapshot(&self, build: &Build) -> bool {
-        self.stage == 0 && self.host == build.config.build
+        self.stage == 0 && self.host == build.build
     }
 
     /// Returns if this compiler should be treated as a final stage one in the
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index 7b6b01655df..9326bb7129a 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -56,7 +56,7 @@ fn build_krate(build: &mut Build, krate: &str) {
     // of packages we're going to have to know what `-p` arguments to pass it
     // to know what crates to test. Here we run `cargo metadata` to learn about
     // the dependency graph and what `-p` arguments there are.
-    let mut cargo = Command::new(&build.cargo);
+    let mut cargo = Command::new(&build.initial_cargo);
     cargo.arg("metadata")
          .arg("--format-version").arg("1")
          .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml"));
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index f150df6cdcd..20eec97d8e5 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -94,7 +94,7 @@ pub fn llvm(build: &Build, target: &str) {
     let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
 
     cfg.target(target)
-       .host(&build.config.build)
+       .host(&build.build)
        .out_dir(&out_dir)
        .profile(profile)
        .define("LLVM_ENABLE_ASSERTIONS", assertions)
@@ -129,11 +129,11 @@ pub fn llvm(build: &Build, target: &str) {
     }
 
     // http://llvm.org/docs/HowToCrossCompileLLVM.html
-    if target != build.config.build {
+    if target != build.build {
         // FIXME: if the llvm root for the build triple is overridden then we
         //        should use llvm-tblgen from there, also should verify that it
         //        actually exists most of the time in normal installs of LLVM.
-        let host = build.llvm_out(&build.config.build).join("bin/llvm-tblgen");
+        let host = build.llvm_out(&build.build).join("bin/llvm-tblgen");
         cfg.define("CMAKE_CROSSCOMPILING", "True")
            .define("LLVM_TABLEGEN", &host);
     }
@@ -243,7 +243,7 @@ pub fn test_helpers(build: &Build, target: &str) {
     cfg.cargo_metadata(false)
        .out_dir(&dst)
        .target(target)
-       .host(&build.config.build)
+       .host(&build.build)
        .opt_level(0)
        .debug(false)
        .file(build.src.join("src/rt/rust_test_helpers.c"))
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 46d047bb015..a9c1b023dd4 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -18,9 +18,9 @@
 //! In theory if we get past this phase it's a bug if a build fails, but in
 //! practice that's likely not true!
 
-use std::collections::HashSet;
+use std::collections::HashMap;
 use std::env;
-use std::ffi::{OsStr, OsString};
+use std::ffi::{OsString, OsStr};
 use std::fs;
 use std::process::Command;
 use std::path::PathBuf;
@@ -29,45 +29,59 @@ use build_helper::output;
 
 use Build;
 
+struct Finder {
+    cache: HashMap<OsString, Option<PathBuf>>,
+    path: OsString,
+}
+
+impl Finder {
+    fn new() -> Self {
+        Self {
+            cache: HashMap::new(),
+            path: env::var_os("PATH").unwrap_or_default()
+        }
+    }
+
+    fn maybe_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> Option<PathBuf> {
+        let cmd: OsString = cmd.as_ref().into();
+        let path = self.path.clone();
+        self.cache.entry(cmd.clone()).or_insert_with(|| {
+            for path in env::split_paths(&path) {
+                let target = path.join(&cmd);
+                let mut cmd_alt = cmd.clone();
+                cmd_alt.push(".exe");
+                if target.is_file() || // some/path/git
+                target.with_extension("exe").exists() || // some/path/git.exe
+                target.join(&cmd_alt).exists() { // some/path/git/git.exe
+                    return Some(target);
+                }
+            }
+            None
+        }).clone()
+    }
+
+    fn must_have<S: AsRef<OsStr>>(&mut self, cmd: S) -> PathBuf {
+        self.maybe_have(&cmd).unwrap_or_else(|| {
+            panic!("\n\ncouldn't find required command: {:?}\n\n", cmd.as_ref());
+        })
+    }
+}
+
 pub fn check(build: &mut Build) {
-    let mut checked = HashSet::new();
-    let path = env::var_os("PATH").unwrap_or(OsString::new());
+    let path = env::var_os("PATH").unwrap_or_default();
     // On Windows, quotes are invalid characters for filename paths, and if
     // one is present as part of the PATH then that can lead to the system
     // being unable to identify the files properly. See
     // https://github.com/rust-lang/rust/issues/34959 for more details.
-    if cfg!(windows) {
-        if path.to_string_lossy().contains("\"") {
-            panic!("PATH contains invalid character '\"'");
-        }
+    if cfg!(windows) && path.to_string_lossy().contains("\"") {
+        panic!("PATH contains invalid character '\"'");
     }
-    let have_cmd = |cmd: &OsStr| {
-        for path in env::split_paths(&path) {
-            let target = path.join(cmd);
-            let mut cmd_alt = cmd.to_os_string();
-            cmd_alt.push(".exe");
-            if target.is_file() ||
-               target.with_extension("exe").exists() ||
-               target.join(cmd_alt).exists() {
-                return Some(target);
-            }
-        }
-        return None;
-    };
-
-    let mut need_cmd = |cmd: &OsStr| {
-        if !checked.insert(cmd.to_owned()) {
-            return
-        }
-        if have_cmd(cmd).is_none() {
-            panic!("\n\ncouldn't find required command: {:?}\n\n", cmd);
-        }
-    };
 
+    let mut cmd_finder = Finder::new();
     // If we've got a git directory we're gona need git to update
     // submodules and learn about various other aspects.
-    if build.src_is_git {
-        need_cmd("git".as_ref());
+    if build.rust_info.is_git() {
+        cmd_finder.must_have("git");
     }
 
     // We need cmake, but only if we're actually building LLVM or sanitizers.
@@ -75,57 +89,32 @@ pub fn check(build: &mut Build) {
         .filter_map(|host| build.config.target_config.get(host))
         .any(|config| config.llvm_config.is_none());
     if building_llvm || build.config.sanitizers {
-        need_cmd("cmake".as_ref());
+        cmd_finder.must_have("cmake");
     }
 
     // Ninja is currently only used for LLVM itself.
-    if building_llvm && build.config.ninja {
-        // Some Linux distros rename `ninja` to `ninja-build`.
-        // CMake can work with either binary name.
-        if have_cmd("ninja-build".as_ref()).is_none() {
-            need_cmd("ninja".as_ref());
-        }
+    // 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 build.config.python.is_none() {
-        // set by bootstrap.py
-        if let Some(v) = env::var_os("BOOTSTRAP_PYTHON") {
-            build.config.python = Some(PathBuf::from(v));
-        }
-    }
-    if build.config.python.is_none() {
-        build.config.python = have_cmd("python2.7".as_ref());
-    }
-    if build.config.python.is_none() {
-        build.config.python = have_cmd("python2".as_ref());
-    }
-    if build.config.python.is_none() {
-        need_cmd("python".as_ref());
-        build.config.python = Some("python".into());
-    }
-    need_cmd(build.config.python.as_ref().unwrap().as_ref());
+    build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
+        .or_else(|| env::var_os("BOOTSTRAP_PYTHON").map(PathBuf::from)) // set by bootstrap.py
+        .or_else(|| cmd_finder.maybe_have("python2.7"))
+        .or_else(|| cmd_finder.maybe_have("python2"))
+        .or_else(|| Some(cmd_finder.must_have("python")));
 
+    build.config.nodejs = build.config.nodejs.take().map(|p| cmd_finder.must_have(p))
+        .or_else(|| cmd_finder.maybe_have("node"))
+        .or_else(|| cmd_finder.maybe_have("nodejs"));
 
-    if let Some(ref s) = build.config.nodejs {
-        need_cmd(s.as_ref());
-    } else {
-        // Look for the nodejs command, needed for emscripten testing
-        if let Some(node) = have_cmd("node".as_ref()) {
-            build.config.nodejs = Some(node);
-        } else if let Some(node) = have_cmd("nodejs".as_ref()) {
-            build.config.nodejs = Some(node);
-        }
-    }
-
-    if let Some(ref gdb) = build.config.gdb {
-        need_cmd(gdb.as_ref());
-    } else {
-        build.config.gdb = have_cmd("gdb".as_ref());
-    }
+    build.config.gdb = build.config.gdb.take().map(|p| cmd_finder.must_have(p))
+        .or_else(|| cmd_finder.maybe_have("gdb"));
 
     // We're gonna build some custom C code here and there, host triples
     // also build some C++ shims for LLVM so we need a C++ compiler.
-    for target in build.config.target.iter() {
+    for target in &build.config.target {
         // On emscripten we don't actually need the C compiler to just
         // build the target artifacts, only for testing. For the sake
         // of easier bot configuration, just skip detection.
@@ -133,33 +122,32 @@ pub fn check(build: &mut Build) {
             continue;
         }
 
-        need_cmd(build.cc(target).as_ref());
+        cmd_finder.must_have(build.cc(target));
         if let Some(ar) = build.ar(target) {
-            need_cmd(ar.as_ref());
+            cmd_finder.must_have(ar);
         }
     }
-    for host in build.config.host.iter() {
-        need_cmd(build.cxx(host).unwrap().as_ref());
-    }
 
-    // The msvc hosts don't use jemalloc, turn it off globally to
-    // avoid packaging the dummy liballoc_jemalloc on that platform.
     for host in build.config.host.iter() {
+        cmd_finder.must_have(build.cxx(host).unwrap());
+
+        // The msvc hosts don't use jemalloc, turn it off globally to
+        // avoid packaging the dummy liballoc_jemalloc on that platform.
         if host.contains("msvc") {
             build.config.use_jemalloc = false;
         }
     }
 
     // Externally configured LLVM requires FileCheck to exist
-    let filecheck = build.llvm_filecheck(&build.config.build);
+    let filecheck = build.llvm_filecheck(&build.build);
     if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
         panic!("FileCheck executable {:?} does not exist", filecheck);
     }
 
-    for target in build.config.target.iter() {
+    for target in &build.config.target {
         // Can't compile for iOS unless we're on macOS
         if target.contains("apple-ios") &&
-           !build.config.build.contains("apple-darwin") {
+           !build.build.contains("apple-darwin") {
             panic!("the iOS target is only supported on macOS");
         }
 
@@ -206,18 +194,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
         }
     }
 
-    for host in build.flags.host.iter() {
-        if !build.config.host.contains(host) {
-            panic!("specified host `{}` is not in the ./configure list", host);
-        }
-    }
-    for target in build.flags.target.iter() {
-        if !build.config.target.contains(target) {
-            panic!("specified target `{}` is not in the ./configure list",
-                   target);
-        }
-    }
-
     let run = |cmd: &mut Command| {
         cmd.output().map(|output| {
             String::from_utf8_lossy(&output.stdout)
@@ -231,6 +207,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
     }
 
     if let Some(ref s) = build.config.ccache {
-        need_cmd(s.as_ref());
+        cmd_finder.must_have(s);
     }
 }
diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs
index 5f0724c6577..c221d707683 100644
--- a/src/bootstrap/step.rs
+++ b/src/bootstrap/step.rs
@@ -104,10 +104,10 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.build("llvm", "src/llvm")
          .host(true)
          .dep(move |s| {
-             if s.target == build.config.build {
+             if s.target == build.build {
                  Step::noop()
              } else {
-                 s.target(&build.config.build)
+                 s.target(&build.build)
              }
          })
          .run(move |s| native::llvm(build, s.target));
@@ -124,7 +124,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
                  Step::noop()
              } else {
                  s.name("librustc")
-                  .host(&build.config.build)
+                  .host(&build.build)
                   .stage(s.stage - 1)
              }
          })
@@ -148,7 +148,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
                 }
             }
         }
-        return ret
+        ret
     };
 
     // ========================================================================
@@ -215,29 +215,29 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
         let mut rule = rules.build(&krate, "path/to/nowhere");
         rule.dep(move |s| {
                 if build.force_use_stage1(&s.compiler(), s.target) {
-                    s.host(&build.config.build).stage(1)
-                } else if s.host == build.config.build {
+                    s.host(&build.build).stage(1)
+                } else if s.host == build.build {
                     s.name(dep)
                 } else {
-                    s.host(&build.config.build)
+                    s.host(&build.build)
                 }
             })
             .run(move |s| {
                 if build.force_use_stage1(&s.compiler(), s.target) {
                     link(build,
-                         &s.stage(1).host(&build.config.build).compiler(),
+                         &s.stage(1).host(&build.build).compiler(),
                          &s.compiler(),
                          s.target)
-                } else if s.host == build.config.build {
+                } else if s.host == build.build {
                     link(build, &s.compiler(), &s.compiler(), s.target)
                 } else {
                     link(build,
-                         &s.host(&build.config.build).compiler(),
+                         &s.host(&build.build).compiler(),
                          &s.compiler(),
                          s.target)
                 }
             });
-            return rule
+            rule
     }
 
     // Similar to the `libstd`, `libtest`, and `librustc` rules above, except
@@ -269,7 +269,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     for (krate, path, _default) in krates("std") {
         rules.build(&krate.build_step, path)
              .dep(|s| s.name("startup-objects"))
-             .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
+             .dep(move |s| s.name("rustc").host(&build.build).target(s.host))
              .run(move |s| compile::std(build, s.target, &s.compiler()));
     }
     for (krate, path, _default) in krates("test") {
@@ -280,7 +280,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     for (krate, path, _default) in krates("rustc-main") {
         rules.build(&krate.build_step, path)
              .dep(|s| s.name("libtest-link"))
-             .dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
+             .dep(move |s| s.name("llvm").host(&build.build).stage(0))
              .dep(|s| s.name("may-run-build-script"))
              .run(move |s| compile::rustc(build, s.target, &s.compiler()));
     }
@@ -291,8 +291,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.build("may-run-build-script", "path/to/nowhere")
          .dep(move |s| {
              s.name("libstd-link")
-              .host(&build.config.build)
-              .target(&build.config.build)
+              .host(&build.build)
+              .target(&build.build)
          });
     rules.build("startup-objects", "src/rtstartup")
          .dep(|s| s.name("create-sysroot").target(s.host))
@@ -332,7 +332,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
               "incremental");
     }
 
-    if build.config.build.contains("msvc") {
+    if build.build.contains("msvc") {
         // nothing to do for debuginfo tests
     } else {
         rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb")
@@ -352,7 +352,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
                                          "debuginfo-gdb", "debuginfo"));
         let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
         rule.default(true);
-        if build.config.build.contains("apple") {
+        if build.build.contains("apple") {
             rule.dep(|s| s.name("check-debuginfo-lldb"));
         } else {
             rule.dep(|s| s.name("check-debuginfo-gdb"));
@@ -594,8 +594,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
              // Cargo depends on procedural macros, which requires a full host
              // compiler to be available, so we need to depend on that.
              s.name("librustc-link")
-              .target(&build.config.build)
-              .host(&build.config.build)
+              .target(&build.build)
+              .host(&build.build)
          })
          .run(move |s| compile::tool(build, s.stage, s.target, "cargo"));
     rules.build("tool-rls", "src/tools/rls")
@@ -606,8 +606,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
          .dep(move |s| {
              // rls, like cargo, uses procedural macros
              s.name("librustc-link")
-              .target(&build.config.build)
-              .host(&build.config.build)
+              .target(&build.build)
+              .host(&build.build)
          })
          .run(move |s| compile::tool(build, s.stage, s.target, "rls"));
 
@@ -635,8 +635,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.doc("doc-book", "src/doc/book")
          .dep(move |s| {
              s.name("tool-rustbook")
-              .host(&build.config.build)
-              .target(&build.config.build)
+              .host(&build.build)
+              .target(&build.build)
               .stage(0)
          })
          .default(build.config.docs)
@@ -644,8 +644,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.doc("doc-nomicon", "src/doc/nomicon")
          .dep(move |s| {
              s.name("tool-rustbook")
-              .host(&build.config.build)
-              .target(&build.config.build)
+              .host(&build.build)
+              .target(&build.build)
               .stage(0)
          })
          .default(build.config.docs)
@@ -653,8 +653,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.doc("doc-reference", "src/doc/reference")
          .dep(move |s| {
              s.name("tool-rustbook")
-              .host(&build.config.build)
-              .target(&build.config.build)
+              .host(&build.build)
+              .target(&build.build)
               .stage(0)
          })
          .default(build.config.docs)
@@ -662,8 +662,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.doc("doc-unstable-book", "src/doc/unstable-book")
          .dep(move |s| {
              s.name("tool-rustbook")
-              .host(&build.config.build)
-              .target(&build.config.build)
+              .host(&build.build)
+              .target(&build.build)
               .stage(0)
          })
          .dep(move |s| s.name("doc-unstable-book-gen"))
@@ -675,14 +675,14 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.doc("doc-standalone", "src/doc")
          .dep(move |s| {
              s.name("rustc")
-              .host(&build.config.build)
-              .target(&build.config.build)
+              .host(&build.build)
+              .target(&build.build)
               .stage(0)
          })
          .default(build.config.docs)
          .run(move |s| doc::standalone(build, s.target));
     rules.doc("doc-error-index", "src/tools/error_index_generator")
-         .dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0))
+         .dep(move |s| s.name("tool-error-index").target(&build.build).stage(0))
          .dep(move |s| s.name("librustc-link"))
          .default(build.config.docs)
          .host(true)
@@ -690,8 +690,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     rules.doc("doc-unstable-book-gen", "src/tools/unstable-book-gen")
          .dep(move |s| {
              s.name("tool-unstable-book-gen")
-              .host(&build.config.build)
-              .target(&build.config.build)
+              .host(&build.build)
+              .target(&build.build)
               .stage(0)
          })
          .dep(move |s| s.name("libstd-link"))
@@ -725,7 +725,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     // ========================================================================
     // Distribution targets
     rules.dist("dist-rustc", "src/librustc")
-         .dep(move |s| s.name("rustc").host(&build.config.build))
+         .dep(move |s| s.name("rustc").host(&build.build))
          .host(true)
          .only_host_build(true)
          .default(true)
@@ -811,7 +811,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
          .host(true)
          .only_build(true)
          .only_host_build(true)
-         .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0))
+         .dep(move |s| s.name("tool-build-manifest").target(&build.build).stage(0))
          .run(move |_| dist::hash_and_sign(build));
 
     rules.install("install-docs", "src/doc")
@@ -861,8 +861,8 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules {
     /// Helper to depend on a stage0 build-only rust-installer tool.
     fn tool_rust_installer<'a>(build: &'a Build, step: &Step<'a>) -> Step<'a> {
         step.name("tool-rust-installer")
-            .host(&build.config.build)
-            .target(&build.config.build)
+            .host(&build.build)
+            .target(&build.build)
             .stage(0)
     }
 }
@@ -1058,8 +1058,8 @@ impl<'a> Rules<'a> {
             build: build,
             sbuild: Step {
                 stage: build.flags.stage.unwrap_or(2),
-                target: &build.config.build,
-                host: &build.config.build,
+                target: &build.build,
+                host: &build.build,
                 name: "",
             },
             rules: BTreeMap::new(),
@@ -1218,16 +1218,9 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
 
         rules.into_iter().flat_map(|(rule, _)| {
             let hosts = if rule.only_host_build || rule.only_build {
-                &self.build.config.host[..1]
-            } else if self.build.flags.host.len() > 0 {
-                &self.build.flags.host
+                self.build.build_slice()
             } else {
-                &self.build.config.host
-            };
-            let targets = if self.build.flags.target.len() > 0 {
-                &self.build.flags.target
-            } else {
-                &self.build.config.target
+                &self.build.hosts
             };
             // Determine the actual targets participating in this rule.
             // NOTE: We should keep the full projection from build triple to
@@ -1236,19 +1229,18 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
             // the original non-shadowed hosts array is used below.
             let arr = if rule.host {
                 // If --target was specified but --host wasn't specified,
-                // don't run any host-only tests. Also, respect any `--host`
-                // overrides as done for `hosts`.
+                // don't run any host-only tests.
                 if self.build.flags.host.len() > 0 {
-                    &self.build.flags.host[..]
+                    &self.build.hosts
                 } else if self.build.flags.target.len() > 0 {
                     &[]
                 } else if rule.only_build {
-                    &self.build.config.host[..1]
+                    self.build.build_slice()
                 } else {
-                    &self.build.config.host[..]
+                    &self.build.hosts
                 }
             } else {
-                targets
+                &self.build.targets
             };
 
             hosts.iter().flat_map(move |host| {
@@ -1326,7 +1318,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
         for idx in 0..nodes.len() {
             self.topo_sort(idx, &idx_to_node, &edges, &mut visited, &mut order);
         }
-        return order
+        order
     }
 
     /// Builds the dependency graph rooted at `step`.
@@ -1365,7 +1357,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd?
         }
 
         edges.entry(idx).or_insert(HashSet::new()).extend(deps);
-        return idx
+        idx
     }
 
     /// Given a dependency graph with a finished list of `nodes`, fill out more
@@ -1494,8 +1486,8 @@ mod tests {
         let step = super::Step {
             name: "",
             stage: 2,
-            host: &build.config.build,
-            target: &build.config.build,
+            host: &build.build,
+            target: &build.build,
         };
 
         assert!(plan.contains(&step.name("dist-docs")));
@@ -1517,8 +1509,8 @@ mod tests {
         let step = super::Step {
             name: "",
             stage: 2,
-            host: &build.config.build,
-            target: &build.config.build,
+            host: &build.build,
+            target: &build.build,
         };
 
         assert!(plan.contains(&step.name("dist-docs")));
@@ -1545,8 +1537,8 @@ mod tests {
         let step = super::Step {
             name: "",
             stage: 2,
-            host: &build.config.build,
-            target: &build.config.build,
+            host: &build.build,
+            target: &build.build,
         };
 
         assert!(!plan.iter().any(|s| s.host == "B"));
@@ -1575,8 +1567,8 @@ mod tests {
         let step = super::Step {
             name: "",
             stage: 2,
-            host: &build.config.build,
-            target: &build.config.build,
+            host: &build.build,
+            target: &build.build,
         };
 
         assert!(!plan.iter().any(|s| s.host == "B"));
@@ -1612,8 +1604,8 @@ mod tests {
         let step = super::Step {
             name: "",
             stage: 2,
-            host: &build.config.build,
-            target: &build.config.build,
+            host: &build.build,
+            target: &build.build,
         };
 
         assert!(!plan.iter().any(|s| s.target == "A"));
@@ -1639,8 +1631,8 @@ mod tests {
         let step = super::Step {
             name: "",
             stage: 2,
-            host: &build.config.build,
-            target: &build.config.build,
+            host: &build.build,
+            target: &build.build,
         };
 
         assert!(!plan.iter().any(|s| s.target == "A"));
@@ -1683,8 +1675,8 @@ mod tests {
         let step = super::Step {
             name: "",
             stage: 2,
-            host: &build.config.build,
-            target: &build.config.build,
+            host: &build.build,
+            target: &build.build,
         };
 
         // rustc built for all for of (A, B) x (A, B)
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 61bd85e76c5..092fb04637b 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -14,7 +14,6 @@
 //! not a lot of interesting happenings here unfortunately.
 
 use std::env;
-use std::ffi::OsString;
 use std::fs;
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
@@ -32,16 +31,9 @@ pub fn staticlib(name: &str, target: &str) -> String {
     }
 }
 
-/// Copies a file from `src` to `dst`, attempting to use hard links and then
-/// falling back to an actually filesystem copy if necessary.
+/// Copies a file from `src` to `dst`
 pub fn copy(src: &Path, dst: &Path) {
-    // A call to `hard_link` will fail if `dst` exists, so remove it if it
-    // already exists so we can try to help `hard_link` succeed.
     let _ = fs::remove_file(&dst);
-
-    // Attempt to "easy copy" by creating a hard link (symlinks don't work on
-    // windows), but if that fails just fall back to a slow `copy` operation.
-    // let res = fs::hard_link(src, dst);
     let res = fs::copy(src, dst);
     if let Err(e) = res {
         panic!("failed to copy `{}` to `{}`: {}", src.display(),
@@ -149,8 +141,7 @@ pub fn dylib_path_var() -> &'static str {
 /// Parses the `dylib_path_var()` environment variable, returning a list of
 /// paths that are members of this lookup path.
 pub fn dylib_path() -> Vec<PathBuf> {
-    env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new()))
-        .collect()
+    env::split_paths(&env::var_os(dylib_path_var()).unwrap_or_default()).collect()
 }
 
 /// `push` all components to `buf`. On windows, append `.exe` to the last component.
@@ -422,4 +413,4 @@ impl CiEnv {
             cmd.env("TERM", "xterm").args(&["--color", "always"]);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/doc/unstable-book/src/language-features/compile-error.md b/src/doc/unstable-book/src/language-features/compile-error.md
index 1b25eeda3f6..4b24c0a6a0d 100644
--- a/src/doc/unstable-book/src/language-features/compile-error.md
+++ b/src/doc/unstable-book/src/language-features/compile-error.md
@@ -2,7 +2,7 @@
 
 The tracking issue for this feature is: [#40872]
 
-[#29599]: https://github.com/rust-lang/rust/issues/40872
+[#40872]: https://github.com/rust-lang/rust/issues/40872
 
 ------------------------
 
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index 375b8bd6b82..a2368ee5f4a 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -143,7 +143,8 @@ pub extern fn rust_eh_unwind_resume() {
 #[no_mangle]
 pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
                                _file: &'static str,
-                               _line: u32) -> ! {
+                               _line: u32,
+                               _column: u32) -> ! {
     unsafe { intrinsics::abort() }
 }
 ```
@@ -187,7 +188,8 @@ pub extern fn rust_eh_unwind_resume() {
 #[no_mangle]
 pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
                                _file: &'static str,
-                               _line: u32) -> ! {
+                               _line: u32,
+                               _column: u32) -> ! {
     unsafe { intrinsics::abort() }
 }
 ```
diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
new file mode 100644
index 00000000000..200a9c19462
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
@@ -0,0 +1,27 @@
+# `unsized_tuple_coercion`
+
+The tracking issue for this feature is: [#42877]
+
+[#42877]: https://github.com/rust-lang/rust/issues/42877
+
+------------------------
+
+This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
+
+```rust
+impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
+```
+
+This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
+
+```rust
+#![feature(unsized_tuple_coercion)]
+
+fn main() {
+    let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
+    let y : &([i32; 3], [i32]) = &x;
+    assert_eq!(y.1[0], 4);
+}
+```
+
+[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
diff --git a/src/doc/unstable-book/src/library-features/iterator-for-each.md b/src/doc/unstable-book/src/library-features/iterator-for-each.md
new file mode 100644
index 00000000000..ebeb5f6a1de
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/iterator-for-each.md
@@ -0,0 +1,17 @@
+# `iterator_for_each`
+
+The tracking issue for this feature is: [#42986]
+
+[#42986]: https://github.com/rust-lang/rust/issues/42986
+
+------------------------
+
+To call a closure on each element of an iterator, you can use `for_each`:
+
+```rust
+#![feature(iterator_for_each)]
+
+fn main() {
+    (0..10).for_each(|i| println!("{}", i));
+}
+```
diff --git a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md b/src/doc/unstable-book/src/library-features/more-io-inner-methods.md
deleted file mode 100644
index c84f40e7ee5..00000000000
--- a/src/doc/unstable-book/src/library-features/more-io-inner-methods.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# `more_io_inner_methods`
-
-The tracking issue for this feature is: [#41519]
-
-[#41519]: https://github.com/rust-lang/rust/issues/41519
-
-------------------------
-
-This feature enables several internal accessor methods on structures in
-`std::io` including `Take::{get_ref, get_mut}` and `Chain::{into_inner, get_ref,
-get_mut}`.
diff --git a/src/doc/unstable-book/src/library-features/sort-unstable.md b/src/doc/unstable-book/src/library-features/sort-unstable.md
deleted file mode 100644
index 9effcfc774c..00000000000
--- a/src/doc/unstable-book/src/library-features/sort-unstable.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# `sort_unstable`
-
-The tracking issue for this feature is: [#40585]
-
-[#40585]: https://github.com/rust-lang/rust/issues/40585
-
-------------------------
-
-The default `sort` method on slices is stable. In other words, it guarantees
-that the original order of equal elements is preserved after sorting. The
-method has several undesirable characteristics:
-
-1. It allocates a sizable chunk of memory.
-2. If you don't need stability, it is not as performant as it could be.
-
-An alternative is the new `sort_unstable` feature, which includes these
-methods for sorting slices:
-
-1. `sort_unstable`
-2. `sort_unstable_by`
-3. `sort_unstable_by_key`
-
-Unstable sorting is generally faster and makes no allocations. The majority
-of real-world sorting needs doesn't require stability, so these methods can
-very often come in handy.
-
-Another important difference is that `sort` lives in `libstd` and
-`sort_unstable` lives in `libcore`. The reason is that the former makes
-allocations and the latter doesn't.
-
-A simple example:
-
-```rust
-#![feature(sort_unstable)]
-
-let mut v = [-5, 4, 1, -3, 2];
-
-v.sort_unstable();
-assert!(v == [-5, -3, 1, 2, 4]);
-```
diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs
index 9bddce29957..bf38629ed38 100644
--- a/src/liballoc/allocator.rs
+++ b/src/liballoc/allocator.rs
@@ -873,7 +873,7 @@ pub unsafe trait Alloc {
     {
         let k = Layout::new::<T>();
         if k.size() > 0 {
-            unsafe { self.alloc(k).map(|p|Unique::new(*p as *mut T)) }
+            unsafe { self.alloc(k).map(|p| Unique::new(p as *mut T)) }
         } else {
             Err(AllocErr::invalid_input("zero-sized type invalid for alloc_one"))
         }
diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs
index 958020d0b0e..174628ccd07 100644
--- a/src/liballoc/benches/lib.rs
+++ b/src/liballoc/benches/lib.rs
@@ -14,9 +14,9 @@
 #![feature(rand)]
 #![feature(repr_simd)]
 #![feature(slice_rotate)]
-#![feature(sort_unstable)]
 #![feature(test)]
 
+extern crate rand;
 extern crate test;
 
 mod btree;
diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs
index aa5a438b35e..d99270e7f31 100644
--- a/src/liballoc/benches/slice.rs
+++ b/src/liballoc/benches/slice.rs
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::{mem, ptr};
-use std::__rand::{Rng, thread_rng};
+use std::__rand::{thread_rng};
+use std::mem;
+use std::ptr;
 
+use rand::{Rng, SeedableRng, XorShiftRng};
 use test::{Bencher, black_box};
 
 #[bench]
@@ -191,17 +193,17 @@ fn gen_descending(len: usize) -> Vec<u64> {
 }
 
 fn gen_random(len: usize) -> Vec<u64> {
-    let mut rng = thread_rng();
+    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
     rng.gen_iter::<u64>().take(len).collect()
 }
 
 fn gen_random_bytes(len: usize) -> Vec<u8> {
-    let mut rng = thread_rng();
+    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
     rng.gen_iter::<u8>().take(len).collect()
 }
 
 fn gen_mostly_ascending(len: usize) -> Vec<u64> {
-    let mut rng = thread_rng();
+    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
     let mut v = gen_ascending(len);
     for _ in (0usize..).take_while(|x| x * x <= len) {
         let x = rng.gen::<usize>() % len;
@@ -212,7 +214,7 @@ fn gen_mostly_ascending(len: usize) -> Vec<u64> {
 }
 
 fn gen_mostly_descending(len: usize) -> Vec<u64> {
-    let mut rng = thread_rng();
+    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
     let mut v = gen_descending(len);
     for _ in (0usize..).take_while(|x| x * x <= len) {
         let x = rng.gen::<usize>() % len;
@@ -223,7 +225,7 @@ fn gen_mostly_descending(len: usize) -> Vec<u64> {
 }
 
 fn gen_strings(len: usize) -> Vec<String> {
-    let mut rng = thread_rng();
+    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
     let mut v = vec![];
     for _ in 0..len {
         let n = rng.gen::<usize>() % 20 + 1;
@@ -233,7 +235,7 @@ fn gen_strings(len: usize) -> Vec<String> {
 }
 
 fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
-    let mut rng = thread_rng();
+    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
     rng.gen_iter().map(|x| [x; 16]).take(len).collect()
 }
 
@@ -241,18 +243,32 @@ macro_rules! sort {
     ($f:ident, $name:ident, $gen:expr, $len:expr) => {
         #[bench]
         fn $name(b: &mut Bencher) {
-            b.iter(|| $gen($len).$f());
+            let v = $gen($len);
+            b.iter(|| v.clone().$f());
             b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
         }
     }
 }
 
+macro_rules! sort_strings {
+    ($f:ident, $name:ident, $gen:expr, $len:expr) => {
+        #[bench]
+        fn $name(b: &mut Bencher) {
+            let v = $gen($len);
+            let v = v.iter().map(|s| &**s).collect::<Vec<&str>>();
+            b.iter(|| v.clone().$f());
+            b.bytes = $len * mem::size_of::<&str>() as u64;
+        }
+    }
+}
+
 macro_rules! sort_expensive {
     ($f:ident, $name:ident, $gen:expr, $len:expr) => {
         #[bench]
         fn $name(b: &mut Bencher) {
+            let v = $gen($len);
             b.iter(|| {
-                let mut v = $gen($len);
+                let mut v = v.clone();
                 let mut count = 0;
                 v.$f(|a: &u64, b: &u64| {
                     count += 1;
@@ -263,7 +279,7 @@ macro_rules! sort_expensive {
                 });
                 black_box(count);
             });
-            b.bytes = $len as u64 * mem::size_of::<u64>() as u64;
+            b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
         }
     }
 }
@@ -271,30 +287,30 @@ macro_rules! sort_expensive {
 sort!(sort, sort_small_ascending, gen_ascending, 10);
 sort!(sort, sort_small_descending, gen_descending, 10);
 sort!(sort, sort_small_random, gen_random, 10);
-sort!(sort, sort_small_big_random, gen_big_random, 10);
+sort!(sort, sort_small_big, gen_big_random, 10);
 sort!(sort, sort_medium_random, gen_random, 100);
 sort!(sort, sort_large_ascending, gen_ascending, 10000);
 sort!(sort, sort_large_descending, gen_descending, 10000);
 sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000);
 sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000);
 sort!(sort, sort_large_random, gen_random, 10000);
-sort!(sort, sort_large_big_random, gen_big_random, 10000);
-sort!(sort, sort_large_strings, gen_strings, 10000);
-sort_expensive!(sort_by, sort_large_random_expensive, gen_random, 10000);
+sort!(sort, sort_large_big, gen_big_random, 10000);
+sort_strings!(sort, sort_large_strings, gen_strings, 10000);
+sort_expensive!(sort_by, sort_large_expensive, gen_random, 10000);
 
 sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10);
 sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10);
 sort!(sort_unstable, sort_unstable_small_random, gen_random, 10);
-sort!(sort_unstable, sort_unstable_small_big_random, gen_big_random, 10);
+sort!(sort_unstable, sort_unstable_small_big, gen_big_random, 10);
 sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100);
 sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000);
 sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000);
 sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000);
 sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000);
 sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000);
-sort!(sort_unstable, sort_unstable_large_big_random, gen_big_random, 10000);
-sort!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000);
-sort_expensive!(sort_unstable_by, sort_unstable_large_random_expensive, gen_random, 10000);
+sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000);
+sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000);
+sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000);
 
 macro_rules! reverse {
     ($name:ident, $ty:ty, $f:expr) => {
diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs
index 1bd95fb82aa..4847b21c0b3 100644
--- a/src/liballoc/fmt.rs
+++ b/src/liballoc/fmt.rs
@@ -498,12 +498,10 @@ pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
 
 use string;
 
-/// The format function takes a precompiled format string and a list of
-/// arguments, to return the resulting formatted string.
+/// The `format` function takes an `Arguments` struct and returns the resulting
+/// formatted string.
 ///
-/// # Arguments
-///
-///   * args - a structure of arguments generated via the `format_args!` macro.
+/// The `Arguments` instance can be created with the `format_args!` macro.
 ///
 /// # Examples
 ///
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index ca52943ea97..23da2913136 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -83,7 +83,6 @@
 #![cfg_attr(not(test), feature(core_float))]
 #![cfg_attr(not(test), feature(exact_size_is_empty))]
 #![cfg_attr(not(test), feature(slice_rotate))]
-#![cfg_attr(not(test), feature(sort_unstable))]
 #![cfg_attr(not(test), feature(str_checked_slicing))]
 #![cfg_attr(test, feature(rand, test))]
 #![feature(allocator)]
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 88876999d76..f4c2b9d054b 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -1144,6 +1144,10 @@ impl<T> [T] {
     ///
     /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
     ///
+    /// When applicable, unstable sorting is preferred because it is generally faster than stable
+    /// sorting and it doesn't allocate auxiliary memory.
+    /// See [`sort_unstable`](#method.sort_unstable).
+    ///
     /// # Current implementation
     ///
     /// The current algorithm is an adaptive, iterative merge sort inspired by
@@ -1174,6 +1178,10 @@ impl<T> [T] {
     ///
     /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
     ///
+    /// When applicable, unstable sorting is preferred because it is generally faster than stable
+    /// sorting and it doesn't allocate auxiliary memory.
+    /// See [`sort_unstable_by`](#method.sort_unstable_by).
+    ///
     /// # Current implementation
     ///
     /// The current algorithm is an adaptive, iterative merge sort inspired by
@@ -1207,6 +1215,10 @@ impl<T> [T] {
     ///
     /// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
     ///
+    /// When applicable, unstable sorting is preferred because it is generally faster than stable
+    /// sorting and it doesn't allocate auxiliary memory.
+    /// See [`sort_unstable_by_key`](#method.sort_unstable_by_key).
+    ///
     /// # Current implementation
     ///
     /// The current algorithm is an adaptive, iterative merge sort inspired by
@@ -1251,8 +1263,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(sort_unstable)]
-    ///
     /// let mut v = [-5, 4, 1, -3, 2];
     ///
     /// v.sort_unstable();
@@ -1260,8 +1270,7 @@ impl<T> [T] {
     /// ```
     ///
     /// [pdqsort]: https://github.com/orlp/pdqsort
-    // FIXME #40585: Mention `sort_unstable` in the documentation for `sort`.
-    #[unstable(feature = "sort_unstable", issue = "40585")]
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
     #[inline]
     pub fn sort_unstable(&mut self)
         where T: Ord
@@ -1288,8 +1297,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(sort_unstable)]
-    ///
     /// let mut v = [5, 4, 1, 3, 2];
     /// v.sort_unstable_by(|a, b| a.cmp(b));
     /// assert!(v == [1, 2, 3, 4, 5]);
@@ -1300,8 +1307,7 @@ impl<T> [T] {
     /// ```
     ///
     /// [pdqsort]: https://github.com/orlp/pdqsort
-    // FIXME #40585: Mention `sort_unstable_by` in the documentation for `sort_by`.
-    #[unstable(feature = "sort_unstable", issue = "40585")]
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
     #[inline]
     pub fn sort_unstable_by<F>(&mut self, compare: F)
         where F: FnMut(&T, &T) -> Ordering
@@ -1328,8 +1334,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(sort_unstable)]
-    ///
     /// let mut v = [-5i32, 4, 1, -3, 2];
     ///
     /// v.sort_unstable_by_key(|k| k.abs());
@@ -1337,8 +1341,7 @@ impl<T> [T] {
     /// ```
     ///
     /// [pdqsort]: https://github.com/orlp/pdqsort
-    // FIXME #40585: Mention `sort_unstable_by_key` in the documentation for `sort_by_key`.
-    #[unstable(feature = "sort_unstable", issue = "40585")]
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
     #[inline]
     pub fn sort_unstable_by_key<B, F>(&mut self, f: F)
         where F: FnMut(&T) -> B,
@@ -1794,7 +1797,7 @@ unsafe fn merge<T, F>(v: &mut [T], mid: usize, buf: *mut T, is_less: &mut F)
 
     impl<T> Drop for MergeHole<T> {
         fn drop(&mut self) {
-            // `T` is not a zero-sized type, so it's okay to divide by it's size.
+            // `T` is not a zero-sized type, so it's okay to divide by its size.
             let len = (self.end as usize - self.start as usize) / mem::size_of::<T>();
             unsafe { ptr::copy_nonoverlapping(self.start, self.dest, len); }
         }
@@ -1908,7 +1911,7 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F)
     // if `Some(r)` is returned, that means `runs[r]` and `runs[r + 1]` must be merged next. If the
     // algorithm should continue building a new run instead, `None` is returned.
     //
-    // TimSort is infamous for it's buggy implementations, as described here:
+    // TimSort is infamous for its buggy implementations, as described here:
     // http://envisage-project.eu/timsort-specification-and-verification/
     //
     // The gist of the story is: we must enforce the invariants on the top four runs on the stack.
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 79d1ccf637d..622cc68964b 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -2008,10 +2008,10 @@ impl From<Box<str>> for String {
     }
 }
 
-#[stable(feature = "box_from_str", since = "1.18.0")]
-impl Into<Box<str>> for String {
-    fn into(self) -> Box<str> {
-        self.into_boxed_str()
+#[stable(feature = "box_from_str", since = "1.20.0")]
+impl From<String> for Box<str> {
+    fn from(s: String) -> Box<str> {
+        s.into_boxed_str()
     }
 }
 
diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs
index 7fa65a2144e..c53bf15f1bf 100644
--- a/src/liballoc/tests/slice.rs
+++ b/src/liballoc/tests/slice.rs
@@ -396,18 +396,44 @@ fn test_sort() {
     let mut rng = thread_rng();
 
     for len in (2..25).chain(500..510) {
-        for _ in 0..100 {
-            let mut v: Vec<_> = rng.gen_iter::<i32>().take(len).collect();
-            let mut v1 = v.clone();
-
-            v.sort();
-            assert!(v.windows(2).all(|w| w[0] <= w[1]));
-
-            v1.sort_by(|a, b| a.cmp(b));
-            assert!(v1.windows(2).all(|w| w[0] <= w[1]));
-
-            v1.sort_by(|a, b| b.cmp(a));
-            assert!(v1.windows(2).all(|w| w[0] >= w[1]));
+        for &modulus in &[5, 10, 100, 1000] {
+            for _ in 0..10 {
+                let orig: Vec<_> = rng.gen_iter::<i32>()
+                    .map(|x| x % modulus)
+                    .take(len)
+                    .collect();
+
+                // Sort in default order.
+                let mut v = orig.clone();
+                v.sort();
+                assert!(v.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in ascending order.
+                let mut v = orig.clone();
+                v.sort_by(|a, b| a.cmp(b));
+                assert!(v.windows(2).all(|w| w[0] <= w[1]));
+
+                // Sort in descending order.
+                let mut v = orig.clone();
+                v.sort_by(|a, b| b.cmp(a));
+                assert!(v.windows(2).all(|w| w[0] >= w[1]));
+
+                // Sort with many pre-sorted runs.
+                let mut v = orig.clone();
+                v.sort();
+                v.reverse();
+                for _ in 0..5 {
+                    let a = rng.gen::<usize>() % len;
+                    let b = rng.gen::<usize>() % len;
+                    if a < b {
+                        v[a..b].reverse();
+                    } else {
+                        v.swap(a, b);
+                    }
+                }
+                v.sort();
+                assert!(v.windows(2).all(|w| w[0] <= w[1]));
+            }
         }
     }
 
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index fdf453b39cf..17f1229c206 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -274,6 +274,11 @@ fn test_dedup_by() {
     vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b));
 
     assert_eq!(vec, ["foo", "bar", "baz", "bar"]);
+
+    let mut vec = vec![("foo", 1), ("foo", 2), ("bar", 3), ("bar", 4), ("bar", 5)];
+    vec.dedup_by(|a, b| a.0 == b.0 && { b.1 += a.1; true });
+
+    assert_eq!(vec, [("foo", 3), ("bar", 12)]);
 }
 
 #[test]
diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs
index a992351653d..f2935c05d4f 100644
--- a/src/liballoc/tests/vec_deque.rs
+++ b/src/liballoc/tests/vec_deque.rs
@@ -510,8 +510,7 @@ fn test_from_iter() {
     let u: Vec<_> = deq.iter().cloned().collect();
     assert_eq!(u, v);
 
-    // FIXME #27741: Remove `.skip(0)` when Range::step_by is fully removed
-    let seq = (0..).skip(0).step_by(2).take(256);
+    let seq = (0..).step_by(2).take(256);
     let deq: VecDeque<_> = seq.collect();
     for (i, &x) in deq.iter().enumerate() {
         assert_eq!(2 * i, x);
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 5d1999a4262..780a51aec3b 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -222,7 +222,7 @@ use Bound::{Excluded, Included, Unbounded};
 /// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized
 /// types inside a `Vec`, it will not allocate space for them. *Note that in this case
 /// the `Vec` may not report a [`capacity`] of 0*. `Vec` will allocate if and only
-/// if [`mem::size_of::<T>`]` * capacity() > 0`. In general, `Vec`'s allocation
+/// if [`mem::size_of::<T>`]`() * capacity() > 0`. In general, `Vec`'s allocation
 /// details are subtle enough that it is strongly recommended that you only
 /// free memory allocated by a `Vec` by creating a new `Vec` and dropping it.
 ///
@@ -823,7 +823,8 @@ impl<T> Vec<T> {
         }
     }
 
-    /// Removes consecutive elements in the vector that resolve to the same key.
+    /// Removes all but the first of consecutive elements in the vector that resolve to the same
+    /// key.
     ///
     /// If the vector is sorted, this removes all duplicates.
     ///
@@ -842,11 +843,13 @@ impl<T> Vec<T> {
         self.dedup_by(|a, b| key(a) == key(b))
     }
 
-    /// Removes consecutive elements in the vector according to a predicate.
+    /// Removes all but the first of consecutive elements in the vector satisfying a given equality
+    /// relation.
     ///
     /// The `same_bucket` function is passed references to two elements from the vector, and
-    /// returns `true` if the elements compare equal, or `false` if they do not. Only the first
-    /// of adjacent equal items is kept.
+    /// returns `true` if the elements compare equal, or `false` if they do not. The elements are
+    /// passed in opposite order from their order in the vector, so if `same_bucket(a, b)` returns
+    /// `true`, `a` is removed.
     ///
     /// If the vector is sorted, this removes all duplicates.
     ///
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index 23677bca9f1..085f62f4b0f 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -137,8 +137,6 @@ fn main() {
         cmd.arg("--enable-debug");
     }
 
-    // Turn off broken quarantine (see jemalloc/jemalloc#161)
-    cmd.arg("--disable-fill");
     cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
     cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
 
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index 93d38a5bc83..5b06229c21f 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -99,3 +99,50 @@ fn bench_zip_add(b: &mut Bencher) {
         add_zip(&source, &mut dst)
     });
 }
+
+/// `Iterator::for_each` implemented as a plain loop.
+fn for_each_loop<I, F>(iter: I, mut f: F) where
+    I: Iterator, F: FnMut(I::Item)
+{
+    for item in iter {
+        f(item);
+    }
+}
+
+/// `Iterator::for_each` implemented with `fold` for internal iteration.
+/// (except when `by_ref()` effectively disables that optimization.)
+fn for_each_fold<I, F>(iter: I, mut f: F) where
+    I: Iterator, F: FnMut(I::Item)
+{
+    iter.fold((), move |(), item| f(item));
+}
+
+#[bench]
+fn bench_for_each_chain_loop(b: &mut Bencher) {
+    b.iter(|| {
+        let mut acc = 0;
+        let iter = (0i64..1000000).chain(0..1000000).map(black_box);
+        for_each_loop(iter, |x| acc += x);
+        acc
+    });
+}
+
+#[bench]
+fn bench_for_each_chain_fold(b: &mut Bencher) {
+    b.iter(|| {
+        let mut acc = 0;
+        let iter = (0i64..1000000).chain(0..1000000).map(black_box);
+        for_each_fold(iter, |x| acc += x);
+        acc
+    });
+}
+
+#[bench]
+fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
+    b.iter(|| {
+        let mut acc = 0;
+        let mut iter = (0i64..1000000).chain(0..1000000).map(black_box);
+        for_each_fold(iter.by_ref(), |x| acc += x);
+        acc
+    });
+}
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 6f35d0417f1..f133bd93c91 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -335,7 +335,6 @@ impl Ordering {
 /// Example usage:
 ///
 /// ```
-/// #![feature(reverse_cmp_key)]
 /// use std::cmp::Reverse;
 ///
 /// let mut v = vec![1, 2, 3, 4, 5, 6];
@@ -343,10 +342,10 @@ impl Ordering {
 /// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
 /// ```
 #[derive(PartialEq, Eq, Debug)]
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
-pub struct Reverse<T>(pub T);
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
+pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T);
 
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 impl<T: PartialOrd> PartialOrd for Reverse<T> {
     #[inline]
     fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
@@ -363,7 +362,7 @@ impl<T: PartialOrd> PartialOrd for Reverse<T> {
     fn gt(&self, other: &Self) -> bool { other.0 > self.0 }
 }
 
-#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
 impl<T: Ord> Ord for Reverse<T> {
     #[inline]
     fn cmp(&self, other: &Reverse<T>) -> Ordering {
@@ -380,8 +379,9 @@ impl<T: Ord> Ord for Reverse<T> {
 ///
 /// ## Derivable
 ///
-/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic
-/// ordering based on the top-to-bottom declaration order of the struct's members.
+/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
+/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members.
+/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order.
 ///
 /// ## How can I implement `Ord`?
 ///
@@ -513,8 +513,9 @@ impl PartialOrd for Ordering {
 ///
 /// ## Derivable
 ///
-/// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic
-/// ordering based on the top-to-bottom declaration order of the struct's members.
+/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
+/// lexicographic ordering based on the top-to-bottom declaration order of the struct's members.
+/// When `derive`d on enums, variants are ordered by their top-to-bottom declaration order.
 ///
 /// ## How can I implement `PartialOrd`?
 ///
diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs
index 102e3c0bd7b..322df6e5b47 100644
--- a/src/libcore/fmt/builders.rs
+++ b/src/libcore/fmt/builders.rs
@@ -49,9 +49,37 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> {
     }
 }
 
-/// A struct to help with `fmt::Debug` implementations.
+/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
 ///
-/// Constructed by the `Formatter::debug_struct` method.
+/// This is useful when you wish to output a formatted struct as a part of your
+/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+///
+/// This can be constructed by the
+/// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
+/// method.
+///
+/// # Example
+///
+/// ```
+/// use std::fmt;
+///
+/// struct Foo {
+///     bar: i32,
+///     baz: String,
+/// }
+///
+/// impl fmt::Debug for Foo {
+///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+///         fmt.debug_struct("Foo")
+///            .field("bar", &self.bar)
+///            .field("baz", &self.baz)
+///            .finish()
+///     }
+/// }
+///
+/// // prints "Foo { bar: 10, baz: "Hello World" }"
+/// println!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() });
+/// ```
 #[must_use]
 #[allow(missing_debug_implementations)]
 #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -116,9 +144,34 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
     }
 }
 
-/// A struct to help with `fmt::Debug` implementations.
+/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+///
+/// This is useful when you wish to output a formatted tuple as a part of your
+/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+///
+/// This can be constructed by the
+/// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
+/// method.
 ///
-/// Constructed by the `Formatter::debug_tuple` method.
+/// # Example
+///
+/// ```
+/// use std::fmt;
+///
+/// struct Foo(i32, String);
+///
+/// impl fmt::Debug for Foo {
+///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+///         fmt.debug_tuple("Foo")
+///            .field(&self.0)
+///            .field(&self.1)
+///            .finish()
+///     }
+/// }
+///
+/// // prints "Foo(10, "Hello World")"
+/// println!("{:?}", Foo(10, "Hello World".to_string()));
+/// ```
 #[must_use]
 #[allow(missing_debug_implementations)]
 #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -228,9 +281,31 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
     }
 }
 
-/// A struct to help with `fmt::Debug` implementations.
+/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+///
+/// This is useful when you wish to output a formatted set of items as a part
+/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+///
+/// This can be constructed by the
+/// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
+/// method.
+///
+/// # Example
 ///
-/// Constructed by the `Formatter::debug_set` method.
+/// ```
+/// use std::fmt;
+///
+/// struct Foo(Vec<i32>);
+///
+/// impl fmt::Debug for Foo {
+///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+///         fmt.debug_set().entries(self.0.iter()).finish()
+///     }
+/// }
+///
+/// // prints "{10, 11}"
+/// println!("{:?}", Foo(vec![10, 11]));
+/// ```
 #[must_use]
 #[allow(missing_debug_implementations)]
 #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -277,9 +352,31 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
     }
 }
 
-/// A struct to help with `fmt::Debug` implementations.
+/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+///
+/// This is useful when you wish to output a formatted list of items as a part
+/// of your [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+///
+/// This can be constructed by the
+/// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
+/// method.
+///
+/// # Example
+///
+/// ```
+/// use std::fmt;
+///
+/// struct Foo(Vec<i32>);
 ///
-/// Constructed by the `Formatter::debug_list` method.
+/// impl fmt::Debug for Foo {
+///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+///         fmt.debug_list().entries(self.0.iter()).finish()
+///     }
+/// }
+///
+/// // prints "[10, 11]"
+/// println!("{:?}", Foo(vec![10, 11]));
+/// ```
 #[must_use]
 #[allow(missing_debug_implementations)]
 #[stable(feature = "debug_builders", since = "1.2.0")]
@@ -326,9 +423,31 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
     }
 }
 
-/// A struct to help with `fmt::Debug` implementations.
+/// A struct to help with [`fmt::Debug`](trait.Debug.html) implementations.
+///
+/// This is useful when you wish to output a formatted map as a part of your
+/// [`Debug::fmt`](trait.Debug.html#tymethod.fmt) implementation.
+///
+/// This can be constructed by the
+/// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
+/// method.
+///
+/// # Example
+///
+/// ```
+/// use std::fmt;
+///
+/// struct Foo(Vec<(String, i32)>);
+///
+/// impl fmt::Debug for Foo {
+///     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+///         fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()
+///     }
+/// }
 ///
-/// Constructed by the `Formatter::debug_map` method.
+/// // prints "{"A": 10, "B": 11}"
+/// println!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)]));
+/// ```
 #[must_use]
 #[allow(missing_debug_implementations)]
 #[stable(feature = "debug_builders", since = "1.2.0")]
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 8c3d3ce7d88..bcc6d53c81d 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -897,14 +897,11 @@ pub trait UpperExp {
     fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
-/// The `write` function takes an output stream, a precompiled format string,
-/// and a list of arguments. The arguments will be formatted according to the
-/// specified format string into the output stream provided.
+/// The `write` function takes an output stream, and an `Arguments` struct
+/// that can be precompiled with the `format_args!` macro.
 ///
-/// # Arguments
-///
-///   * output - the buffer to write output to
-///   * args - the precompiled arguments generated by `format_args!`
+/// The arguments will be formatted according to the specified format string
+/// into the output stream provided.
 ///
 /// # Examples
 ///
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 30d09e5453b..d9887094fef 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -482,6 +482,53 @@ pub trait Iterator {
         Map{iter: self, f: f}
     }
 
+    /// Calls a closure on each element of an iterator.
+    ///
+    /// This is equivalent to using a [`for`] loop on the iterator, although
+    /// `break` and `continue` are not possible from a closure.  It's generally
+    /// more idiomatic to use a `for` loop, but `for_each` may be more legible
+    /// when processing items at the end of longer iterator chains.  In some
+    /// cases `for_each` may also be faster than a loop, because it will use
+    /// internal iteration on adaptors like `Chain`.
+    ///
+    /// [`for`]: ../../book/first-edition/loops.html#for
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(iterator_for_each)]
+    ///
+    /// use std::sync::mpsc::channel;
+    ///
+    /// let (tx, rx) = channel();
+    /// (0..5).map(|x| x * 2 + 1)
+    ///       .for_each(move |x| tx.send(x).unwrap());
+    ///
+    /// let v: Vec<_> =  rx.iter().collect();
+    /// assert_eq!(v, vec![1, 3, 5, 7, 9]);
+    /// ```
+    ///
+    /// For such a small example, a `for` loop may be cleaner, but `for_each`
+    /// might be preferable to keep a functional style with longer iterators:
+    ///
+    /// ```
+    /// #![feature(iterator_for_each)]
+    ///
+    /// (0..5).flat_map(|x| x * 100 .. x * 110)
+    ///       .enumerate()
+    ///       .filter(|&(i, x)| (i + x) % 3 == 0)
+    ///       .for_each(|(i, x)| println!("{}:{}", i, x));
+    /// ```
+    #[inline]
+    #[unstable(feature = "iterator_for_each", issue = "42986")]
+    fn for_each<F>(self, mut f: F) where
+        Self: Sized, F: FnMut(Self::Item),
+    {
+        self.fold((), move |(), item| f(item));
+    }
+
     /// Creates an iterator which uses a closure to determine if an element
     /// should be yielded.
     ///
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index d6a9be4437d..decd718d65e 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -314,12 +314,6 @@ pub use self::iterator::Iterator;
            reason = "likely to be replaced by finer-grained traits",
            issue = "42168")]
 pub use self::range::Step;
-#[unstable(feature = "step_by", reason = "recent addition",
-           issue = "27741")]
-#[rustc_deprecated(since = "1.19.0",
-                   reason = "replaced by `iter::StepBy`")]
-#[allow(deprecated)]
-pub use self::range::StepBy as DeprecatedStepBy;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::sources::{Repeat, repeat};
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index 9aea4477fb7..1dad8157948 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -244,219 +244,6 @@ step_impl_signed!(i64);
 step_impl_no_between!(u64 i64);
 step_impl_no_between!(u128 i128);
 
-/// An adapter for stepping range iterators by a custom amount.
-///
-/// The resulting iterator handles overflow by stopping. The `A`
-/// parameter is the type being iterated over, while `R` is the range
-/// type (usually one of `std::ops::{Range, RangeFrom, RangeInclusive}`.
-#[derive(Clone, Debug)]
-#[unstable(feature = "step_by", reason = "recent addition",
-           issue = "27741")]
-#[rustc_deprecated(since = "1.19.0",
-                   reason = "replaced by `iter::StepBy`")]
-#[allow(deprecated)]
-pub struct StepBy<A, R> {
-    step_by: A,
-    range: R,
-}
-
-impl<A: Step> ops::RangeFrom<A> {
-    /// Creates an iterator starting at the same point, but stepping by
-    /// the given amount at each iteration.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(step_by)]
-    /// fn main() {
-    ///     let result: Vec<_> = (0..).step_by(2).take(5).collect();
-    ///     assert_eq!(result, vec![0, 2, 4, 6, 8]);
-    /// }
-    /// ```
-    #[unstable(feature = "step_by", reason = "recent addition",
-               issue = "27741")]
-    #[rustc_deprecated(since = "1.19.0",
-                       reason = "replaced by `Iterator::step_by`")]
-    #[allow(deprecated)]
-    pub fn step_by(self, by: A) -> StepBy<A, Self> {
-        StepBy {
-            step_by: by,
-            range: self
-        }
-    }
-}
-
-impl<A: Step> ops::Range<A> {
-    /// Creates an iterator with the same range, but stepping by the
-    /// given amount at each iteration.
-    ///
-    /// The resulting iterator handles overflow by stopping.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(step_by)]
-    /// fn main() {
-    ///     let result: Vec<_> = (0..10).step_by(2).collect();
-    ///     assert_eq!(result, vec![0, 2, 4, 6, 8]);
-    /// }
-    /// ```
-    #[unstable(feature = "step_by", reason = "recent addition",
-               issue = "27741")]
-    #[rustc_deprecated(since = "1.19.0",
-                       reason = "replaced by `Iterator::step_by`")]
-    #[allow(deprecated)]
-    pub fn step_by(self, by: A) -> StepBy<A, Self> {
-        StepBy {
-            step_by: by,
-            range: self
-        }
-    }
-}
-
-impl<A: Step> ops::RangeInclusive<A> {
-    /// Creates an iterator with the same range, but stepping by the
-    /// given amount at each iteration.
-    ///
-    /// The resulting iterator handles overflow by stopping.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(step_by, inclusive_range_syntax)]
-    ///
-    /// let result: Vec<_> = (0...10).step_by(2).collect();
-    /// assert_eq!(result, vec![0, 2, 4, 6, 8, 10]);
-    /// ```
-    #[unstable(feature = "step_by", reason = "recent addition",
-               issue = "27741")]
-    #[rustc_deprecated(since = "1.19.0",
-                       reason = "replaced by `Iterator::step_by`")]
-    #[allow(deprecated)]
-    pub fn step_by(self, by: A) -> StepBy<A, Self> {
-        StepBy {
-            step_by: by,
-            range: self
-        }
-    }
-}
-
-#[unstable(feature = "step_by", reason = "recent addition",
-           issue = "27741")]
-#[allow(deprecated)]
-impl<A> Iterator for StepBy<A, ops::RangeFrom<A>> where
-    A: Clone,
-    for<'a> &'a A: Add<&'a A, Output = A>
-{
-    type Item = A;
-
-    #[inline]
-    fn next(&mut self) -> Option<A> {
-        let mut n = &self.range.start + &self.step_by;
-        mem::swap(&mut n, &mut self.range.start);
-        Some(n)
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (usize::MAX, None) // Too bad we can't specify an infinite lower bound
-    }
-}
-
-#[unstable(feature = "fused", issue = "35602")]
-#[allow(deprecated)]
-impl<A> FusedIterator for StepBy<A, ops::RangeFrom<A>>
-    where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {}
-
-#[unstable(feature = "step_by", reason = "recent addition",
-           issue = "27741")]
-#[allow(deprecated)]
-impl<A: Step + Clone> Iterator for StepBy<A, ops::Range<A>> {
-    type Item = A;
-
-    #[inline]
-    fn next(&mut self) -> Option<A> {
-        let rev = self.step_by.is_negative();
-        if (rev && self.range.start > self.range.end) ||
-           (!rev && self.range.start < self.range.end)
-        {
-            match self.range.start.step(&self.step_by) {
-                Some(mut n) => {
-                    mem::swap(&mut self.range.start, &mut n);
-                    Some(n)
-                },
-                None => {
-                    let mut n = self.range.end.clone();
-                    mem::swap(&mut self.range.start, &mut n);
-                    Some(n)
-                }
-            }
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        match Step::steps_between(&self.range.start,
-                                  &self.range.end,
-                                  &self.step_by) {
-            Some(hint) => (hint, Some(hint)),
-            None       => (0, None)
-        }
-    }
-}
-
-#[unstable(feature = "fused", issue = "35602")]
-#[allow(deprecated)]
-impl<A: Step + Clone> FusedIterator for StepBy<A, ops::Range<A>> {}
-
-#[unstable(feature = "inclusive_range",
-           reason = "recently added, follows RFC",
-           issue = "28237")]
-#[allow(deprecated)]
-impl<A: Step + Clone> Iterator for StepBy<A, ops::RangeInclusive<A>> {
-    type Item = A;
-
-    #[inline]
-    fn next(&mut self) -> Option<A> {
-        let rev = self.step_by.is_negative();
-
-        if (rev && self.range.start >= self.range.end) ||
-           (!rev && self.range.start <= self.range.end)
-        {
-            match self.range.start.step(&self.step_by) {
-                Some(n) => {
-                    Some(mem::replace(&mut self.range.start, n))
-                },
-                None => {
-                    let last = self.range.start.replace_one();
-                    self.range.end.replace_zero();
-                    self.step_by.replace_one();
-                    Some(last)
-                },
-            }
-        }
-        else {
-            None
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        match Step::steps_between(&self.range.start,
-                                  &self.range.end,
-                                  &self.step_by) {
-            Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
-            None       => (0, None)
-        }
-    }
-}
-
-#[unstable(feature = "fused", issue = "35602")]
-#[allow(deprecated)]
-impl<A: Step + Clone> FusedIterator for StepBy<A, ops::RangeInclusive<A>> {}
-
 macro_rules! range_exact_iter_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index b6ab1ecaf4e..97aaaffe8bc 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -36,12 +36,12 @@
 //!   These functions are often provided by the system libc, but can also be
 //!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
 //!
-//! * `rust_begin_panic` - This function takes three arguments, a
-//!   `fmt::Arguments`, a `&'static str`, and a `u32`. These three arguments
+//! * `rust_begin_panic` - This function takes four arguments, a
+//!   `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
 //!   dictate the panic message, the file at which panic was invoked, and the
-//!   line. It is up to consumers of this core library to define this panic
-//!   function; it is only required to never return. This requires a `lang`
-//!   attribute named `panic_fmt`.
+//!   line and column inside the file. It is up to consumers of this core
+//!   library to define this panic function; it is only required to never
+//!   return. This requires a `lang` attribute named `panic_fmt`.
 //!
 //! * `rust_eh_personality` - is used by the failure mechanisms of the
 //!    compiler. This is often mapped to GCC's personality function, but crates
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 5bb6a772aeb..70820dce5f9 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -17,16 +17,18 @@ macro_rules! panic {
         panic!("explicit panic")
     );
     ($msg:expr) => ({
-        static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
-        $crate::panicking::panic(&_MSG_FILE_LINE)
+        static _MSG_FILE_LINE_COL: (&'static str, &'static str, u32, u32) =
+            ($msg, file!(), line!(), column!());
+        $crate::panicking::panic(&_MSG_FILE_LINE_COL)
     });
     ($fmt:expr, $($arg:tt)*) => ({
         // The leading _'s are to avoid dead code warnings if this is
         // used inside a dead function. Just `#[allow(dead_code)]` is
         // insufficient, since the user may have
         // `#[forbid(dead_code)]` and which cannot be overridden.
-        static _FILE_LINE: (&'static str, u32) = (file!(), line!());
-        $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
+        static _MSG_FILE_LINE_COL: (&'static str, u32, u32) =
+            (file!(), line!(), column!());
+        $crate::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_MSG_FILE_LINE_COL)
     });
 }
 
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index bba42752f50..6c1e8e8960f 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -506,59 +506,7 @@ pub unsafe fn uninitialized<T>() -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn swap<T>(x: &mut T, y: &mut T) {
     unsafe {
-        // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
-        // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
-        // Haswell E processors. LLVM is more able to optimize if we give a struct a
-        // #[repr(simd)], even if we don't actually use this struct directly.
-        //
-        // FIXME repr(simd) broken on emscripten and redox
-        #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
-        struct Block(u64, u64, u64, u64);
-        struct UnalignedBlock(u64, u64, u64, u64);
-
-        let block_size = size_of::<Block>();
-
-        // Get raw pointers to the bytes of x & y for easier manipulation
-        let x = x as *mut T as *mut u8;
-        let y = y as *mut T as *mut u8;
-
-        // Loop through x & y, copying them `Block` at a time
-        // The optimizer should unroll the loop fully for most types
-        // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
-        let len = size_of::<T>();
-        let mut i = 0;
-        while i + block_size <= len {
-            // Create some uninitialized memory as scratch space
-            // Declaring `t` here avoids aligning the stack when this loop is unused
-            let mut t: Block = uninitialized();
-            let t = &mut t as *mut _ as *mut u8;
-            let x = x.offset(i as isize);
-            let y = y.offset(i as isize);
-
-            // Swap a block of bytes of x & y, using t as a temporary buffer
-            // This should be optimized into efficient SIMD operations where available
-            ptr::copy_nonoverlapping(x, t, block_size);
-            ptr::copy_nonoverlapping(y, x, block_size);
-            ptr::copy_nonoverlapping(t, y, block_size);
-            i += block_size;
-        }
-
-
-        if i < len {
-            // Swap any remaining bytes, using aligned types to copy
-            // where appropriate (this information is lost by conversion
-            // to *mut u8, so restore it manually here)
-            let mut t: UnalignedBlock = uninitialized();
-            let rem = len - i;
-
-            let t = &mut t as *mut _ as *mut u8;
-            let x = x.offset(i as isize);
-            let y = y.offset(i as isize);
-
-            ptr::copy_nonoverlapping(x, t, rem);
-            ptr::copy_nonoverlapping(y, x, rem);
-            ptr::copy_nonoverlapping(t, y, rem);
-        }
+        ptr::swap_nonoverlapping(x, y, 1);
     }
 }
 
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index cb28035682d..ebc30dc8b61 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -205,18 +205,25 @@ impl Float for f32 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+        // applies to zeros and NaNs as well.
+        #[repr(C)]
+        union F32Bytes {
+            f: f32,
+            b: u32
+        }
+        unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index ac6b1e67cd2..1a1fe4d86e0 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -205,18 +205,23 @@ impl Float for f64 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        #[repr(C)]
+        union F64Bytes {
+            f: f64,
+            b: u64
+        }
+        unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 60b7669f3b2..f5a7e78d0fa 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -17,7 +17,7 @@
 //!
 //! ```
 //! # use std::fmt;
-//! fn panic_impl(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> !
+//! fn panic_impl(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> !
 //! # { loop {} }
 //! ```
 //!
@@ -39,34 +39,55 @@
 use fmt;
 
 #[cold] #[inline(never)] // this is the slow path, always
-#[lang = "panic"]
-pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
+#[cfg_attr(not(stage0), lang = "panic")]
+pub fn panic(expr_file_line_col: &(&'static str, &'static str, u32, u32)) -> ! {
     // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially
     // reduce size overhead. The format_args! macro uses str's Display trait to
     // write expr, which calls Formatter::pad, which must accommodate string
     // truncation and padding (even though none is used here). Using
     // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
     // output binary, saving up to a few kilobytes.
+    let (expr, file, line, col) = *expr_file_line_col;
+    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line, col))
+}
+
+// FIXME: remove when SNAP
+#[cold] #[inline(never)]
+#[cfg(stage0)]
+#[lang = "panic"]
+pub fn panic_old(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
     let (expr, file, line) = *expr_file_line;
-    panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), &(file, line))
+    let expr_file_line_col = (expr, file, line, 0);
+    panic(&expr_file_line_col)
+}
+
+#[cold] #[inline(never)]
+#[cfg_attr(not(stage0), lang = "panic_bounds_check")]
+fn panic_bounds_check(file_line_col: &(&'static str, u32, u32),
+                     index: usize, len: usize) -> ! {
+    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
+                           len, index), file_line_col)
 }
 
+// FIXME: remove when SNAP
 #[cold] #[inline(never)]
+#[cfg(stage0)]
 #[lang = "panic_bounds_check"]
-fn panic_bounds_check(file_line: &(&'static str, u32),
+fn panic_bounds_check_old(file_line: &(&'static str, u32),
                      index: usize, len: usize) -> ! {
+    let (file, line) = *file_line;
     panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
-                           len, index), file_line)
+                           len, index), &(file, line, 0))
 }
 
 #[cold] #[inline(never)]
-pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
+pub fn panic_fmt(fmt: fmt::Arguments, file_line_col: &(&'static str, u32, u32)) -> ! {
     #[allow(improper_ctypes)]
     extern {
         #[lang = "panic_fmt"]
         #[unwind]
-        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32) -> !;
+        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: u32, col: u32) -> !;
     }
-    let (file, line) = *file_line;
-    unsafe { panic_impl(fmt, file, line) }
+    let (file, line, col) = *file_line_col;
+    unsafe { panic_impl(fmt, file, line, col) }
 }
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 54ae9e0d628..92470299366 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -117,6 +117,90 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     mem::forget(tmp);
 }
 
+/// Swaps a sequence of values at two mutable locations of the same type.
+///
+/// # Safety
+///
+/// The two arguments must each point to the beginning of `count` locations
+/// of valid memory, and the two memory ranges must not overlap.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// #![feature(swap_nonoverlapping)]
+///
+/// use std::ptr;
+///
+/// let mut x = [1, 2, 3, 4];
+/// let mut y = [7, 8, 9];
+///
+/// unsafe {
+///     ptr::swap_nonoverlapping(x.as_mut_ptr(), y.as_mut_ptr(), 2);
+/// }
+///
+/// assert_eq!(x, [7, 8, 3, 4]);
+/// assert_eq!(y, [1, 2, 9]);
+/// ```
+#[inline]
+#[unstable(feature = "swap_nonoverlapping", issue = "42818")]
+pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+    let x = x as *mut u8;
+    let y = y as *mut u8;
+    let len = mem::size_of::<T>() * count;
+    swap_nonoverlapping_bytes(x, y, len)
+}
+
+#[inline]
+unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
+    // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
+    // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
+    // Haswell E processors. LLVM is more able to optimize if we give a struct a
+    // #[repr(simd)], even if we don't actually use this struct directly.
+    //
+    // FIXME repr(simd) broken on emscripten and redox
+    #[cfg_attr(not(any(target_os = "emscripten", target_os = "redox")), repr(simd))]
+    struct Block(u64, u64, u64, u64);
+    struct UnalignedBlock(u64, u64, u64, u64);
+
+    let block_size = mem::size_of::<Block>();
+
+    // Loop through x & y, copying them `Block` at a time
+    // The optimizer should unroll the loop fully for most types
+    // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
+    let mut i = 0;
+    while i + block_size <= len {
+        // Create some uninitialized memory as scratch space
+        // Declaring `t` here avoids aligning the stack when this loop is unused
+        let mut t: Block = mem::uninitialized();
+        let t = &mut t as *mut _ as *mut u8;
+        let x = x.offset(i as isize);
+        let y = y.offset(i as isize);
+
+        // Swap a block of bytes of x & y, using t as a temporary buffer
+        // This should be optimized into efficient SIMD operations where available
+        copy_nonoverlapping(x, t, block_size);
+        copy_nonoverlapping(y, x, block_size);
+        copy_nonoverlapping(t, y, block_size);
+        i += block_size;
+    }
+
+    if i < len {
+        // Swap any remaining bytes
+        let mut t: UnalignedBlock = mem::uninitialized();
+        let rem = len - i;
+
+        let t = &mut t as *mut _ as *mut u8;
+        let x = x.offset(i as isize);
+        let y = y.offset(i as isize);
+
+        copy_nonoverlapping(x, t, rem);
+        copy_nonoverlapping(y, x, rem);
+        copy_nonoverlapping(t, y, rem);
+    }
+}
+
 /// Replaces the value at `dest` with `src`, returning the old
 /// value, without dropping either.
 ///
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index ce5da9ec2d5..62c7e7aa1cc 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -212,15 +212,15 @@ 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 = "sort_unstable", issue = "40585")]
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
     fn sort_unstable(&mut self)
         where Self::Item: Ord;
 
-    #[unstable(feature = "sort_unstable", issue = "40585")]
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
     fn sort_unstable_by<F>(&mut self, compare: F)
         where F: FnMut(&Self::Item, &Self::Item) -> Ordering;
 
-    #[unstable(feature = "sort_unstable", issue = "40585")]
+    #[stable(feature = "sort_unstable", since = "1.20.0")]
     fn sort_unstable_by_key<B, F>(&mut self, f: F)
         where F: FnMut(&Self::Item) -> B,
               B: Ord;
diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs
index 3b9ae5652c5..e4a4e33c172 100644
--- a/src/libcore/slice/rotate.rs
+++ b/src/libcore/slice/rotate.rs
@@ -76,7 +76,7 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
             break;
         }
 
-        ptr_swap_n(
+        ptr::swap_nonoverlapping(
             mid.offset(-(left as isize)),
             mid.offset((right-delta) as isize),
             delta);
@@ -103,10 +103,3 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
         ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right);
     }
 }
-
-unsafe fn ptr_swap_n<T>(a: *mut T, b: *mut T, n: usize) {
-    for i in 0..n {
-        // These are nonoverlapping, so use mem::swap instead of ptr::swap
-        mem::swap(&mut *a.offset(i as isize), &mut *b.offset(i as isize));
-    }
-}
diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs
index 6f9f2915dfe..518d56095d6 100644
--- a/src/libcore/slice/sort.rs
+++ b/src/libcore/slice/sort.rs
@@ -351,7 +351,7 @@ fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
 
     if start_l < end_l {
         // The left block remains.
-        // Move it's remaining out-of-order elements to the far right.
+        // Move its remaining out-of-order elements to the far right.
         debug_assert_eq!(width(l, r), block_l);
         while start_l < end_l {
             unsafe {
@@ -363,7 +363,7 @@ fn partition_in_blocks<T, F>(v: &mut [T], pivot: &T, is_less: &mut F) -> usize
         width(v.as_mut_ptr(), r)
     } else if start_r < end_r {
         // The right block remains.
-        // Move it's remaining out-of-order elements to the far left.
+        // Move its remaining out-of-order elements to the far left.
         debug_assert_eq!(width(l, r), block_r);
         while start_r < end_r {
             unsafe {
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 4f9951cd153..14f0260f571 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -12,15 +12,6 @@ use core::iter::*;
 use core::{i8, i16, isize};
 use core::usize;
 
-// FIXME #27741: This is here to simplify calling Iterator::step_by. Remove
-// once Range::step_by is completely gone (not just deprecated).
-trait IterEx: Sized {
-    fn iter_step_by(self, n: usize) -> StepBy<Self>;
-}
-impl<I:Iterator> IterEx for I {
-    fn iter_step_by(self, n: usize) -> StepBy<Self> { self.step_by(n) }
-}
-
 #[test]
 fn test_lt() {
     let empty: [isize; 0] = [];
@@ -76,7 +67,7 @@ fn test_multi_iter() {
 
 #[test]
 fn test_counter_from_iter() {
-    let it = (0..).iter_step_by(5).take(10);
+    let it = (0..).step_by(5).take(10);
     let xs: Vec<isize> = FromIterator::from_iter(it);
     assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
 }
@@ -94,7 +85,7 @@ fn test_iterator_chain() {
     }
     assert_eq!(i, expected.len());
 
-    let ys = (30..).iter_step_by(10).take(4);
+    let ys = (30..).step_by(10).take(4);
     let it = xs.iter().cloned().chain(ys);
     let mut i = 0;
     for x in it {
@@ -156,13 +147,13 @@ fn test_iterator_chain_find() {
 #[test]
 fn test_iterator_step_by() {
     // Identity
-    let mut it = (0..).iter_step_by(1).take(3);
+    let mut it = (0..).step_by(1).take(3);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next(), Some(1));
     assert_eq!(it.next(), Some(2));
     assert_eq!(it.next(), None);
 
-    let mut it = (0..).iter_step_by(3).take(4);
+    let mut it = (0..).step_by(3).take(4);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next(), Some(3));
     assert_eq!(it.next(), Some(6));
@@ -173,7 +164,7 @@ fn test_iterator_step_by() {
 #[test]
 #[should_panic]
 fn test_iterator_step_by_zero() {
-    let mut it = (0..).iter_step_by(0);
+    let mut it = (0..).step_by(0);
     it.next();
 }
 
@@ -252,7 +243,7 @@ fn test_iterator_step_by_size_hint() {
 
 #[test]
 fn test_filter_map() {
-    let it = (0..).iter_step_by(1).take(10)
+    let it = (0..).step_by(1).take(10)
         .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
     assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
 }
@@ -654,7 +645,7 @@ fn test_iterator_scan() {
 fn test_iterator_flat_map() {
     let xs = [0, 3, 6];
     let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
-    let it = xs.iter().flat_map(|&x| (x..).iter_step_by(1).take(3));
+    let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
     let mut i = 0;
     for x in it {
         assert_eq!(x, ys[i]);
@@ -680,13 +671,13 @@ fn test_inspect() {
 #[test]
 fn test_cycle() {
     let cycle_len = 3;
-    let it = (0..).iter_step_by(1).take(cycle_len).cycle();
+    let it = (0..).step_by(1).take(cycle_len).cycle();
     assert_eq!(it.size_hint(), (usize::MAX, None));
     for (i, x) in it.take(100).enumerate() {
         assert_eq!(i % cycle_len, x);
     }
 
-    let mut it = (0..).iter_step_by(1).take(0).cycle();
+    let mut it = (0..).step_by(1).take(0).cycle();
     assert_eq!(it.size_hint(), (0, Some(0)));
     assert_eq!(it.next(), None);
 }
@@ -765,7 +756,7 @@ fn test_iterator_min() {
 
 #[test]
 fn test_iterator_size_hint() {
-    let c = (0..).iter_step_by(1);
+    let c = (0..).step_by(1);
     let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
     let v2 = &[10, 11, 12];
     let vi = v.iter();
@@ -1090,8 +1081,8 @@ fn test_range_step() {
     #![allow(deprecated)]
 
     assert_eq!((0..20).step_by(5).collect::<Vec<isize>>(), [0, 5, 10, 15]);
-    assert_eq!((20..0).step_by(-5).collect::<Vec<isize>>(), [20, 15, 10, 5]);
-    assert_eq!((20..0).step_by(-6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
+    assert_eq!((1..21).rev().step_by(5).collect::<Vec<isize>>(), [20, 15, 10, 5]);
+    assert_eq!((1..21).rev().step_by(6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
     assert_eq!((200..255).step_by(50).collect::<Vec<u8>>(), [200, 250]);
     assert_eq!((200..-5).step_by(1).collect::<Vec<isize>>(), []);
     assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []);
@@ -1099,13 +1090,12 @@ fn test_range_step() {
     assert_eq!((0..20).step_by(1).size_hint(), (20, Some(20)));
     assert_eq!((0..20).step_by(21).size_hint(), (1, Some(1)));
     assert_eq!((0..20).step_by(5).size_hint(), (4, Some(4)));
-    assert_eq!((20..0).step_by(-5).size_hint(), (4, Some(4)));
-    assert_eq!((20..0).step_by(-6).size_hint(), (4, Some(4)));
+    assert_eq!((1..21).rev().step_by(5).size_hint(), (4, Some(4)));
+    assert_eq!((1..21).rev().step_by(6).size_hint(), (4, Some(4)));
     assert_eq!((20..-5).step_by(1).size_hint(), (0, Some(0)));
     assert_eq!((20..20).step_by(1).size_hint(), (0, Some(0)));
-    assert_eq!((0..1).step_by(0).size_hint(), (0, None));
-    assert_eq!((i8::MAX..i8::MIN).step_by(i8::MIN).size_hint(), (2, Some(2)));
-    assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX).size_hint(), (3, Some(3)));
+    assert_eq!((i8::MIN..i8::MAX).step_by(-(i8::MIN as i32) as usize).size_hint(), (2, Some(2)));
+    assert_eq!((i16::MIN..i16::MAX).step_by(i16::MAX as usize).size_hint(), (3, Some(3)));
     assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
 }
 
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 337f8aa31dc..8d3e367d237 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -34,9 +34,7 @@
 #![feature(slice_patterns)]
 #![feature(slice_rotate)]
 #![feature(sort_internals)]
-#![feature(sort_unstable)]
 #![feature(specialization)]
-#![feature(step_by)]
 #![feature(step_trait)]
 #![feature(test)]
 #![feature(trusted_len)]
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index ca05db15ffe..5e56b0d8ab1 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -31,7 +31,7 @@
             issue = "27703")]
 #![feature(core_intrinsics)]
 #![feature(staged_api)]
-#![feature(step_by)]
+#![feature(iterator_step_by)]
 #![feature(custom_attribute)]
 #![feature(specialization)]
 #![allow(unused_attributes)]
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 5e36bd8ec27..035640b9710 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1946,6 +1946,44 @@ Maybe you just misspelled the lint name or the lint doesn't exist anymore.
 Either way, try to update/remove it in order to fix the error.
 "##,
 
+E0621: r##"
+This error code indicates a mismatch between the function signature (i.e.,
+the parameter types and the return type) and the function body. Most of
+the time, this indicates that the function signature needs to be changed to
+match the body, but it may be that the body needs to be changed to match
+the signature.
+
+Specifically, one or more of the parameters contain borrowed data that
+needs to have a named lifetime in order for the body to type-check. Most of
+the time, this is because the borrowed data is being returned from the
+function, as in this example:
+
+```compile_fail,E0621
+fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required
+                                             // in the type of `y`
+    if x > y { x } else { y }
+}
+```
+
+Here, the function is returning data borrowed from either x or y, but the
+'a annotation indicates that it is returning data only from x. We can make
+the signature match the body by changing the type of y to &'a i32, like so:
+
+```
+fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
+    if x > y { x } else { y }
+}
+```
+
+Alternatively, you could change the body not to return data from y:
+
+```
+fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
+    x
+}
+```
+"##,
+
 }
 
 
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 62bedcdfcbe..873d39ec9e9 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2170,12 +2170,12 @@ impl<'a> LoweringContext<'a> {
                 //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
                 //       mut iter => {
                 //         [opt_ident]: loop {
-                //           let mut _next;
+                //           let mut __next;
                 //           match ::std::iter::Iterator::next(&mut iter) {
-                //             ::std::option::Option::Some(val) => _next = val,
+                //             ::std::option::Option::Some(val) => __next = val,
                 //             ::std::option::Option::None => break
                 //           };
-                //           let <pat> = _next;
+                //           let <pat> = __next;
                 //           StmtExpr(<body>);
                 //         }
                 //       }
@@ -2188,7 +2188,7 @@ impl<'a> LoweringContext<'a> {
 
                 let iter = self.str_to_ident("iter");
 
-                let next_ident = self.str_to_ident("_next");
+                let next_ident = self.str_to_ident("__next");
                 let next_pat = self.pat_ident_binding_mode(e.span,
                                                            next_ident,
                                                            hir::BindByValue(hir::MutMutable));
@@ -2237,13 +2237,13 @@ impl<'a> LoweringContext<'a> {
 
                 let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id));
 
-                // `let mut _next`
+                // `let mut __next`
                 let next_let = self.stmt_let_pat(e.span,
                     None,
                     next_pat,
                     hir::LocalSource::ForLoopDesugar);
 
-                // `let <pat> = _next`
+                // `let <pat> = __next`
                 let pat = self.lower_pat(pat);
                 let pat_let = self.stmt_let_pat(e.span,
                     Some(next_expr),
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index a1875cd46a0..02a36a372d9 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -594,8 +594,12 @@ impl<'hir> Map<'hir> {
     /// last good node id we found. Note that reaching the crate root (id == 0),
     /// is not an error, since items in the crate module have the crate root as
     /// parent.
-    fn walk_parent_nodes<F>(&self, start_id: NodeId, found: F) -> Result<NodeId, NodeId>
-        where F: Fn(&Node<'hir>) -> bool
+    fn walk_parent_nodes<F, F2>(&self,
+                                start_id: NodeId,
+                                found: F,
+                                bail_early: F2)
+        -> Result<NodeId, NodeId>
+        where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool
     {
         let mut id = start_id;
         loop {
@@ -616,6 +620,8 @@ impl<'hir> Map<'hir> {
                 Some(ref node) => {
                     if found(node) {
                         return Ok(parent_node);
+                    } else if bail_early(node) {
+                        return Err(parent_node);
                     }
                 }
                 None => {
@@ -626,6 +632,56 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    /// Retrieve the NodeId for `id`'s enclosing method, unless there's a
+    /// `while` or `loop` before reacing it, as block tail returns are not
+    /// available in them.
+    ///
+    /// ```
+    /// fn foo(x: usize) -> bool {
+    ///     if x == 1 {
+    ///         true  // `get_return_block` gets passed the `id` corresponding
+    ///     } else {  // to this, it will return `foo`'s `NodeId`.
+    ///         false
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// ```
+    /// fn foo(x: usize) -> bool {
+    ///     loop {
+    ///         true  // `get_return_block` gets passed the `id` corresponding
+    ///     }         // to this, it will return `None`.
+    ///     false
+    /// }
+    /// ```
+    pub fn get_return_block(&self, id: NodeId) -> Option<NodeId> {
+        let match_fn = |node: &Node| {
+            match *node {
+                NodeItem(_) |
+                NodeForeignItem(_) |
+                NodeTraitItem(_) |
+                NodeImplItem(_) => true,
+                _ => false,
+            }
+        };
+        let match_non_returning_block = |node: &Node| {
+            match *node {
+                NodeExpr(ref expr) => {
+                    match expr.node {
+                        ExprWhile(..) | ExprLoop(..) => true,
+                        _ => false,
+                    }
+                }
+                _ => false,
+            }
+        };
+
+        match self.walk_parent_nodes(id, match_fn, match_non_returning_block) {
+            Ok(id) => Some(id),
+            Err(_) => None,
+        }
+    }
+
     /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no
     /// parent item is in this map. The "parent item" is the closest parent node
     /// in the AST which is recorded by the map and is an item, either an item
@@ -637,7 +693,7 @@ impl<'hir> Map<'hir> {
             NodeTraitItem(_) |
             NodeImplItem(_) => true,
             _ => false,
-        }) {
+        }, |_| false) {
             Ok(id) => id,
             Err(id) => id,
         }
@@ -649,7 +705,7 @@ impl<'hir> Map<'hir> {
         let id = match self.walk_parent_nodes(id, |node| match *node {
             NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true,
             _ => false,
-        }) {
+        }, |_| false) {
             Ok(id) => id,
             Err(id) => id,
         };
@@ -668,7 +724,7 @@ impl<'hir> Map<'hir> {
             NodeImplItem(_) |
             NodeBlock(_) => true,
             _ => false,
-        }) {
+        }, |_| false) {
             Ok(id) => Some(id),
             Err(_) => None,
         }
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index a78d5ce1c16..c6f4cd585d7 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1527,7 +1527,8 @@ impl<'a> State<'a> {
             if i > 0 {
                 word(&mut self.s, "::")?
             }
-            if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" {
+            if segment.name != keywords::CrateRoot.name() &&
+               segment.name != keywords::DollarCrate.name() {
                 self.print_name(segment.name)?;
                 self.print_path_parameters(&segment.parameters, colons_before_params)?;
             }
@@ -1554,7 +1555,8 @@ impl<'a> State<'a> {
                     if i > 0 {
                         word(&mut self.s, "::")?
                     }
-                    if segment.name != keywords::CrateRoot.name() && segment.name != "$crate" {
+                    if segment.name != keywords::CrateRoot.name() &&
+                       segment.name != keywords::DollarCrate.name() {
                         self.print_name(segment.name)?;
                         self.print_path_parameters(&segment.parameters, colons_before_params)?;
                     }
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 4e78d79ef87..4f365a97f4c 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -524,10 +524,9 @@ for ty::TypeVariants<'tcx>
                 region.hash_stable(hcx, hasher);
                 pointee_ty.hash_stable(hcx, hasher);
             }
-            TyFnDef(def_id, substs, ref sig) => {
+            TyFnDef(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
-                sig.hash_stable(hcx, hasher);
             }
             TyFnPtr(ref sig) => {
                 sig.hash_stable(hcx, hasher);
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 11bac21bc42..82bbb4a1bf5 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -72,9 +72,11 @@ use ty::error::TypeError;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
 use errors::{DiagnosticBuilder, DiagnosticStyledString};
-
 mod note;
+
 mod need_type_info;
+mod named_anon_conflict;
+
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn note_and_explain_region(self,
@@ -255,34 +257,48 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    pub fn report_region_errors(&self,
-                                errors: &Vec<RegionResolutionError<'tcx>>) {
+
+    pub fn report_region_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>) {
         debug!("report_region_errors(): {} errors to start", errors.len());
 
         // try to pre-process the errors, which will group some of them
         // together into a `ProcessedErrors` group:
         let errors = self.process_errors(errors);
 
-        debug!("report_region_errors: {} errors after preprocessing", errors.len());
+        debug!("report_region_errors: {} errors after preprocessing",
+               errors.len());
 
         for error in errors {
+
             debug!("report_region_errors: error = {:?}", error);
-            match error.clone() {
-                ConcreteFailure(origin, sub, sup) => {
-                    self.report_concrete_failure(origin, sub, sup).emit();
-                }
 
-                GenericBoundFailure(kind, param_ty, sub) => {
-                    self.report_generic_bound_failure(kind, param_ty, sub);
-                }
+            if !self.try_report_named_anon_conflict(&error){
+
+               match error.clone() {
+                  // These errors could indicate all manner of different
+                  // problems with many different solutions. Rather
+                  // than generate a "one size fits all" error, what we
+                  // attempt to do is go through a number of specific
+                  // scenarios and try to find the best way to present
+                  // the error. If all of these fails, we fall back to a rather
+                  // general bit of code that displays the error information
+                  ConcreteFailure(origin, sub, sup) => {
+
+                      self.report_concrete_failure(origin, sub, sup).emit();
+                  }
 
-                SubSupConflict(var_origin,
+                  GenericBoundFailure(kind, param_ty, sub) => {
+                      self.report_generic_bound_failure(kind, param_ty, sub);
+                  }
+
+                  SubSupConflict(var_origin,
                                sub_origin, sub_r,
                                sup_origin, sup_r) => {
-                    self.report_sub_sup_conflict(var_origin,
+                      self.report_sub_sup_conflict(var_origin,
                                                  sub_origin, sub_r,
                                                  sup_origin, sup_r);
-                }
+                  }
+               }
             }
         }
     }
diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs
new file mode 100644
index 00000000000..ccbc5cdb862
--- /dev/null
+++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs
@@ -0,0 +1,199 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Error Reporting for Anonymous Region Lifetime Errors.
+use hir;
+use infer::InferCtxt;
+use ty::{self, Region};
+use infer::region_inference::RegionResolutionError::*;
+use infer::region_inference::RegionResolutionError;
+use hir::map as hir_map;
+use hir::def_id::DefId;
+
+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
+    // &hir::Arg of the function argument corresponding to the anonymous
+    // region and the Ty corresponding to the named region.
+    // Currently only the case where the function declaration consists of
+    // one named region and one anonymous region is handled.
+    // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
+    // Here, we would return the hir::Arg for y, we return the type &'a
+    // 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.
+    fn find_arg_with_anonymous_region
+        (&self,
+         anon_region: Region<'tcx>,
+         named_region: Region<'tcx>)
+         -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> {
+
+        match *anon_region {
+            ty::ReFree(ref free_region) => {
+
+                let id = free_region.scope;
+                let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
+                let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap();
+                let body = self.tcx.hir.body(body_id);
+                if let Some(tables) = self.in_progress_tables {
+                    body.arguments
+                        .iter()
+                        .enumerate()
+                        .filter_map(|(index, arg)| {
+                            let ty = tables.borrow().node_id_to_type(arg.id);
+                            let mut found_anon_region = false;
+                            let new_arg_ty = self.tcx
+                                .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region {
+                                    found_anon_region = true;
+                                    named_region
+                                } else {
+                                    r
+                                });
+                            if found_anon_region {
+                                let is_first = index == 0;
+                                Some((arg, new_arg_ty, free_region.bound_region, is_first))
+                            } else {
+                                None
+                            }
+                        })
+                        .next()
+                } else {
+                    None
+                }
+            }
+            _ => None,
+
+        }
+    }
+
+    // This method generates the error message for the case when
+    // the function arguments consist of a named region and an anonymous
+    // region and corresponds to `ConcreteFailure(..)`
+    pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
+
+        let (span, sub, sup) = match *error {
+            ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
+            _ => return false, // inapplicable
+        };
+
+        // Determine whether the sub and sup consist of one named region ('a)
+        // and one anonymous (elided) region. If so, find the parameter arg
+        // 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) =
+            if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() {
+                (sub,
+                 self.find_arg_with_anonymous_region(sup, sub).unwrap(),
+                 self.is_suitable_anonymous_region(sup).unwrap())
+            } else if sup.is_named_region() && self.is_suitable_anonymous_region(sub).is_some() {
+                (sup,
+                 self.find_arg_with_anonymous_region(sub, sup).unwrap(),
+                 self.is_suitable_anonymous_region(sub).unwrap())
+            } else {
+                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;
+                } else {
+                }
+            }
+            _ => {}
+        }
+
+        // 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) {
+            return false;
+        }
+
+        let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
+            (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
+        } else {
+            (format!("parameter type"), format!("type"))
+        };
+
+
+        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;
+
+    }
+
+    // This method returns whether the given Region is Anonymous
+    // and returns the DefId corresponding to the region.
+    pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option<DefId> {
+
+        match *region {
+            ty::ReFree(ref free_region) => {
+                match free_region.bound_region {
+                    ty::BrAnon(..) => {
+                        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(..)) => {
+                                // proceed ahead //
+                            }
+                            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
+                        }
+                        return Some(anonymous_region_binding_scope);
+                    }
+                    _ => None,
+                }
+            }
+            _ => None,
+        }
+    }
+}
diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs
index 7361d66428f..a684881c091 100644
--- a/src/librustc/infer/error_reporting/need_type_info.rs
+++ b/src/librustc/infer/error_reporting/need_type_info.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use hir::{self, map, Local, Pat, Body};
+use hir::{self, Local, Pat, Body};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use infer::InferCtxt;
 use infer::type_variable::TypeVariableOrigin;
@@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn need_type_info(&self, body_id: hir::BodyId, span: Span, ty: Ty<'tcx>) {
+    pub fn need_type_info(&self, body_id: Option<hir::BodyId>, span: Span, ty: Ty<'tcx>) {
         let ty = self.resolve_type_vars_if_possible(&ty);
         let name = self.extract_type_name(&ty);
 
@@ -103,11 +103,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             found_arg_pattern: None,
         };
 
-        // #40294: cause.body_id can also be a fn declaration.
-        // Currently, if it's anything other than NodeExpr, we just ignore it
-        match self.tcx.hir.find(body_id.node_id) {
-            Some(map::NodeExpr(expr)) => local_visitor.visit_expr(expr),
-            _ => ()
+        if let Some(body_id) = body_id {
+            let expr = self.tcx.hir.expect_expr(body_id.node_id);
+            local_visitor.visit_expr(expr);
         }
 
         if let Some(pattern) = local_visitor.found_arg_pattern {
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index f96e8c389d6..5cb1606da67 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -38,7 +38,6 @@ use errors::DiagnosticBuilder;
 use syntax_pos::{self, Span, DUMMY_SP};
 use util::nodemap::FxHashMap;
 use arena::DroplessArena;
-
 use self::combine::CombineFields;
 use self::higher_ranked::HrMatchResult;
 use self::region_inference::{RegionVarBindings, RegionSnapshot};
@@ -1077,6 +1076,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                region_map,
                                                free_regions);
         let errors = self.region_vars.resolve_regions(&region_rels);
+
         if !self.is_tainted_by_errors() {
             // As a heuristic, just skip reporting region errors
             // altogether if other errors have been reported while
@@ -1191,28 +1191,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     // types using one of these methods, and should not call span_err directly for such
     // errors.
 
-    pub fn type_error_message<M>(&self,
-                                 sp: Span,
-                                 mk_msg: M,
-                                 actual_ty: Ty<'tcx>)
-        where M: FnOnce(String) -> String,
-    {
-        self.type_error_struct(sp, mk_msg, actual_ty).emit();
-    }
-
-    // FIXME: this results in errors without an error code. Deprecate?
-    pub fn type_error_struct<M>(&self,
-                                sp: Span,
-                                mk_msg: M,
-                                actual_ty: Ty<'tcx>)
-                                -> DiagnosticBuilder<'tcx>
-        where M: FnOnce(String) -> String,
-    {
-        self.type_error_struct_with_diag(sp, |actual_ty| {
-            self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty))
-        }, actual_ty)
-    }
-
     pub fn type_error_struct_with_diag<M>(&self,
                                           sp: Span,
                                           mk_diag: M,
@@ -1369,7 +1347,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         Some(self.tcx.closure_kind(def_id))
     }
 
-    pub fn closure_type(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+    /// Obtain the signature of a function or closure.
+    /// For closures, unlike `tcx.fn_sig(def_id)`, this method will
+    /// work during the type-checking of the enclosing function and
+    /// return the closure signature in its partially inferred state.
+    pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
         if let Some(tables) = self.in_progress_tables {
             if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
                 if let Some(&ty) = tables.borrow().closure_tys.get(&id) {
@@ -1378,7 +1360,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             }
         }
 
-        self.tcx.closure_type(def_id)
+        self.tcx.fn_sig(def_id)
     }
 }
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index b81c56e5ee8..e4cf893375c 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -39,7 +39,6 @@
 #![feature(specialization)]
 #![feature(unboxed_closures)]
 #![feature(discriminant_value)]
-#![feature(sort_unstable)]
 #![feature(trace_macros)]
 #![feature(test)]
 
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index a9e0ef51102..8202c6106d1 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -291,16 +291,13 @@ impl LintStore {
         self.by_name.insert(name.into(), Removed(reason.into()));
     }
 
-    #[allow(unused_variables)]
-    fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
-                 -> Result<LintId, FindLintError>
-    {
+    fn find_lint(&self, lint_name: &str) -> Result<LintId, FindLintError> {
         match self.by_name.get(lint_name) {
             Some(&Id(lint_id)) => Ok(lint_id),
             Some(&Renamed(_, lint_id)) => {
                 Ok(lint_id)
             },
-            Some(&Removed(ref reason)) => {
+            Some(&Removed(_)) => {
                 Err(FindLintError::Removed)
             },
             None => Err(FindLintError::NotFound)
@@ -313,7 +310,7 @@ impl LintStore {
                                     &lint_name[..], level);
 
             let lint_flag_val = Symbol::intern(&lint_name);
-            match self.find_lint(&lint_name[..], sess, None) {
+            match self.find_lint(&lint_name[..]) {
                 Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))),
                 Err(FindLintError::Removed) => { }
                 Err(_) => {
@@ -513,7 +510,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
     }
 
     let name = lint.name_lower();
-    let mut def = None;
 
     // Except for possible note details, forbid behaves like deny.
     let effective_level = if level == Forbid { Deny } else { level };
@@ -528,7 +524,8 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
 
     match source {
         Default => {
-            err.note(&format!("#[{}({})] on by default", level.as_str(), name));
+            sess.diag_note_once(&mut err, lint,
+                                &format!("#[{}({})] on by default", level.as_str(), name));
         },
         CommandLine(lint_flag_val) => {
             let flag = match level {
@@ -537,20 +534,24 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
             };
             let hyphen_case_lint_name = name.replace("_", "-");
             if lint_flag_val.as_str() == name {
-                err.note(&format!("requested on the command line with `{} {}`",
-                                  flag, hyphen_case_lint_name));
+                sess.diag_note_once(&mut err, lint,
+                                    &format!("requested on the command line with `{} {}`",
+                                             flag, hyphen_case_lint_name));
             } else {
                 let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-");
-                err.note(&format!("`{} {}` implied by `{} {}`",
-                                  flag, hyphen_case_lint_name, flag, hyphen_case_flag_val));
+                sess.diag_note_once(&mut err, lint,
+                                    &format!("`{} {}` implied by `{} {}`",
+                                             flag, hyphen_case_lint_name, flag,
+                                             hyphen_case_flag_val));
             }
         },
         Node(lint_attr_name, src) => {
-            def = Some(src);
+            sess.diag_span_note_once(&mut err, lint, src, "lint level defined here");
             if lint_attr_name.as_str() != name {
                 let level_str = level.as_str();
-                err.note(&format!("#[{}({})] implied by #[{}({})]",
-                                  level_str, name, level_str, lint_attr_name));
+                sess.diag_note_once(&mut err, lint,
+                                    &format!("#[{}({})] implied by #[{}({})]",
+                                             level_str, name, level_str, lint_attr_name));
             }
         }
     }
@@ -566,10 +567,6 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
         err.note(&citation);
     }
 
-    if let Some(span) = def {
-        sess.diag_span_note_once(&mut err, lint, span, "lint level defined here");
-    }
-
     err
 }
 
@@ -724,21 +721,22 @@ pub trait LintContext<'tcx>: Sized {
         let mut pushed = 0;
 
         for result in gather_attrs(attrs) {
-            let v = match result {
+            let (is_group, lint_level_spans) = match result {
                 Err(span) => {
                     span_err!(self.sess(), span, E0452,
                               "malformed lint attribute");
                     continue;
                 }
                 Ok((lint_name, level, span)) => {
-                    match self.lints().find_lint(&lint_name.as_str(), &self.sess(), Some(span)) {
-                        Ok(lint_id) => vec![(lint_id, level, span)],
+                    match self.lints().find_lint(&lint_name.as_str()) {
+                        Ok(lint_id) => (false, vec![(lint_id, level, span)]),
                         Err(FindLintError::NotFound) => {
                             match self.lints().lint_groups.get(&*lint_name.as_str()) {
-                                Some(&(ref v, _)) => v.iter()
+                                Some(&(ref v, _)) => (true,
+                                                      v.iter()
                                                       .map(|lint_id: &LintId|
                                                            (*lint_id, level, span))
-                                                      .collect(),
+                                                      .collect()),
                                 None => {
                                     // The lint or lint group doesn't exist.
                                     // This is an error, but it was handled
@@ -754,14 +752,18 @@ pub trait LintContext<'tcx>: Sized {
 
             let lint_attr_name = result.expect("lint attribute should be well-formed").0;
 
-            for (lint_id, level, span) in v {
+            for (lint_id, level, span) in lint_level_spans {
                 let (now, now_source) = self.lint_sess().get_source(lint_id);
                 if now == Forbid && level != Forbid {
-                    let lint_name = lint_id.to_string();
+                    let forbidden_lint_name = match now_source {
+                        LintSource::Default => lint_id.to_string(),
+                        LintSource::Node(name, _) => name.to_string(),
+                        LintSource::CommandLine(name) => name.to_string(),
+                    };
                     let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
                                                             "{}({}) overruled by outer forbid({})",
-                                                            level.as_str(), lint_name,
-                                                            lint_name);
+                                                            level.as_str(), lint_attr_name,
+                                                            forbidden_lint_name);
                     diag_builder.span_label(span, "overruled by previous forbid");
                     match now_source {
                         LintSource::Default => &mut diag_builder,
@@ -772,7 +774,10 @@ pub trait LintContext<'tcx>: Sized {
                         LintSource::CommandLine(_) => {
                             diag_builder.note("`forbid` lint level was set on command line")
                         }
-                    }.emit()
+                    }.emit();
+                    if is_group { // don't set a separate error for every lint in the group
+                        break;
+                    }
                 } else if now != level {
                     let cx = self.lint_sess_mut();
                     cx.stack.push((lint_id, (now, now_source)));
@@ -1420,7 +1425,7 @@ impl Decodable for LintId {
     fn decode<D: Decoder>(d: &mut D) -> Result<LintId, D::Error> {
         let s = d.read_str()?;
         ty::tls::with(|tcx| {
-            match tcx.sess.lint_store.borrow().find_lint(&s, tcx.sess, None) {
+            match tcx.sess.lint_store.borrow().find_lint(&s) {
                 Ok(id) => Ok(id),
                 Err(_) => panic!("invalid lint-id `{}`", s),
             }
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 74e1225f394..eab5a8f9103 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -12,7 +12,7 @@
 //! `unsafe`.
 use self::RootUnsafeContext::*;
 
-use ty::{self, Ty, TyCtxt};
+use ty::{self, TyCtxt};
 use lint;
 
 use syntax::ast;
@@ -40,14 +40,6 @@ enum RootUnsafeContext {
     UnsafeBlock(ast::NodeId),
 }
 
-fn type_is_unsafe_function(ty: Ty) -> bool {
-    match ty.sty {
-        ty::TyFnDef(.., f) |
-        ty::TyFnPtr(f) => f.unsafety() == hir::Unsafety::Unsafe,
-        _ => false,
-    }
-}
-
 struct EffectCheckVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
@@ -174,10 +166,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
         match expr.node {
             hir::ExprMethodCall(..) => {
                 let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
-                let base_type = self.tcx.type_of(def_id);
-                debug!("effect: method call case, base type is {:?}",
-                        base_type);
-                if type_is_unsafe_function(base_type) {
+                let sig = self.tcx.fn_sig(def_id);
+                debug!("effect: method call case, signature is {:?}",
+                        sig);
+
+                if sig.0.unsafety == hir::Unsafety::Unsafe {
                     self.require_unsafe(expr.span,
                                         "invocation of unsafe method")
                 }
@@ -186,8 +179,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
                 let base_type = self.tables.expr_ty_adjusted(base);
                 debug!("effect: call case, base type is {:?}",
                         base_type);
-                if type_is_unsafe_function(base_type) {
-                    self.require_unsafe(expr.span, "call to unsafe function")
+                match base_type.sty {
+                    ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+                        if base_type.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
+                            self.require_unsafe(expr.span, "call to unsafe function")
+                        }
+                    }
+                    _ => {}
                 }
             }
             hir::ExprUnary(hir::UnDeref, ref base) => {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 58e77f40d98..259bd4f0999 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -816,7 +816,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
         debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
 
-        let tcx = self.tcx();
         let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
         return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| {
             if let PatKind::Binding(bmode, def_id, ..) = pat.node {
@@ -864,13 +863,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
             match def {
                 Def::Variant(variant_did) |
                 Def::VariantCtor(variant_did, ..) => {
-                    let enum_did = tcx.parent_def_id(variant_did).unwrap();
-                    let downcast_cmt = if tcx.adt_def(enum_did).is_univariant() {
-                        cmt_pat
-                    } else {
-                        let cmt_pat_ty = cmt_pat.ty;
-                        mc.cat_downcast(pat, cmt_pat, cmt_pat_ty, variant_did)
-                    };
+                    let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
 
                     debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
                     delegate.matched_pat(pat, downcast_cmt, match_mode);
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index f180ae53b8a..fde207e4b2f 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -66,11 +66,8 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
     fn def_id_is_transmute(&self, def_id: DefId) -> bool {
-        let intrinsic = match self.tcx.type_of(def_id).sty {
-            ty::TyFnDef(.., bfty) => bfty.abi() == RustIntrinsic,
-            _ => return false
-        };
-        intrinsic && self.tcx.item_name(def_id) == "transmute"
+        self.tcx.fn_sig(def_id).abi() == RustIntrinsic &&
+        self.tcx.item_name(def_id) == "transmute"
     }
 
     fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
@@ -153,22 +150,14 @@ impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
         } else {
             Def::Err
         };
-        match def {
-            Def::Fn(did) if self.def_id_is_transmute(did) => {
+        if let Def::Fn(did) = def {
+            if self.def_id_is_transmute(did) {
                 let typ = self.tables.node_id_to_type(expr.id);
-                let typ = self.tcx.lift_to_global(&typ).unwrap();
-                match typ.sty {
-                    ty::TyFnDef(.., sig) if sig.abi() == RustIntrinsic => {
-                        let from = sig.inputs().skip_binder()[0];
-                        let to = *sig.output().skip_binder();
-                        self.check_transmute(expr.span, from, to);
-                    }
-                    _ => {
-                        span_bug!(expr.span, "transmute wasn't a bare fn?!");
-                    }
-                }
+                let sig = typ.fn_sig(self.tcx);
+                let from = sig.inputs().skip_binder()[0];
+                let to = *sig.output().skip_binder();
+                self.check_transmute(expr.span, from, to);
             }
-            _ => {}
         }
 
         intravisit::walk_expr(self, expr);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 259079cf160..5c741eccf83 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1032,22 +1032,29 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         ret
     }
 
-    pub fn cat_downcast<N:ast_node>(&self,
-                                    node: &N,
-                                    base_cmt: cmt<'tcx>,
-                                    downcast_ty: Ty<'tcx>,
-                                    variant_did: DefId)
-                                    -> cmt<'tcx> {
-        let ret = Rc::new(cmt_ {
-            id: node.id(),
-            span: node.span(),
-            mutbl: base_cmt.mutbl.inherit(),
-            cat: Categorization::Downcast(base_cmt, variant_did),
-            ty: downcast_ty,
-            note: NoteNone
-        });
-        debug!("cat_downcast ret={:?}", ret);
-        ret
+    pub fn cat_downcast_if_needed<N:ast_node>(&self,
+                                              node: &N,
+                                              base_cmt: cmt<'tcx>,
+                                              variant_did: DefId)
+                                              -> cmt<'tcx> {
+        // univariant enums do not need downcasts
+        let base_did = self.tcx.parent_def_id(variant_did).unwrap();
+        if !self.tcx.adt_def(base_did).is_univariant() {
+            let base_ty = base_cmt.ty;
+            let ret = Rc::new(cmt_ {
+                id: node.id(),
+                span: node.span(),
+                mutbl: base_cmt.mutbl.inherit(),
+                cat: Categorization::Downcast(base_cmt, variant_did),
+                ty: base_ty,
+                note: NoteNone
+            });
+            debug!("cat_downcast ret={:?}", ret);
+            ret
+        } else {
+            debug!("cat_downcast univariant={:?}", base_cmt);
+            base_cmt
+        }
     }
 
     pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
@@ -1109,45 +1116,23 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
 
         op(cmt.clone(), pat);
 
-        // Note: This goes up here (rather than within the PatKind::TupleStruct arm
-        // alone) because PatKind::Struct can also refer to variants.
-        let cmt = match pat.node {
-            PatKind::Path(hir::QPath::Resolved(_, ref path)) |
-            PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
-            PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
-                match path.def {
-                    Def::Err => {
-                        debug!("access to unresolvable pattern {:?}", pat);
-                        return Err(())
-                    }
-                    Def::Variant(variant_did) |
-                    Def::VariantCtor(variant_did, ..) => {
-                        // univariant enums do not need downcasts
-                        let enum_did = self.tcx.parent_def_id(variant_did).unwrap();
-                        if !self.tcx.adt_def(enum_did).is_univariant() {
-                            self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
-                        } else {
-                            cmt
-                        }
-                    }
-                    _ => cmt
-                }
-            }
-            _ => cmt
-        };
-
         match pat.node {
           PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
             let def = self.tables.qpath_def(qpath, pat.id);
-            let expected_len = match def {
+            let (cmt, expected_len) = match def {
+                Def::Err => {
+                    debug!("access to unresolvable pattern {:?}", pat);
+                    return Err(())
+                }
                 Def::VariantCtor(def_id, CtorKind::Fn) => {
                     let enum_def = self.tcx.parent_def_id(def_id).unwrap();
-                    self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()
+                    (self.cat_downcast_if_needed(pat, cmt, def_id),
+                     self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
                 }
                 Def::StructCtor(_, CtorKind::Fn) => {
                     match self.pat_ty(&pat)?.sty {
                         ty::TyAdt(adt_def, _) => {
-                            adt_def.struct_variant().fields.len()
+                            (cmt, adt_def.struct_variant().fields.len())
                         }
                         ref ty => {
                             span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
@@ -1168,8 +1153,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             }
           }
 
-          PatKind::Struct(_, ref field_pats, _) => {
+          PatKind::Struct(ref qpath, ref field_pats, _) => {
             // {f1: p1, ..., fN: pN}
+            let def = self.tables.qpath_def(qpath, pat.id);
+            let cmt = match def {
+                Def::Err => {
+                    debug!("access to unresolvable pattern {:?}", pat);
+                    return Err(())
+                },
+                Def::Variant(variant_did) |
+                Def::VariantCtor(variant_did, ..) => {
+                    self.cat_downcast_if_needed(pat, cmt, variant_did)
+                },
+                _ => cmt
+            };
+
             for fp in field_pats {
                 let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
                 let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty);
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index ce5d58f5800..b347a931851 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -28,6 +28,7 @@ use syntax::attr;
 use syntax::ptr::P;
 use syntax_pos::Span;
 use errors::DiagnosticBuilder;
+use util::common::ErrorReported;
 use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap};
 use rustc_back::slice;
 
@@ -255,7 +256,7 @@ const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
 
 pub fn krate(sess: &Session,
              hir_map: &Map)
-             -> Result<NamedRegionMap, usize> {
+             -> Result<NamedRegionMap, ErrorReported> {
     let krate = hir_map.krate();
     let mut map = NamedRegionMap {
         defs: NodeMap(),
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 70c07982f83..8bafdda234a 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -21,7 +21,7 @@ use session::search_paths::PathKind;
 use session::config::DebugInfoLevel;
 use ty::tls;
 use util::nodemap::{FxHashMap, FxHashSet};
-use util::common::duration_to_secs_str;
+use util::common::{duration_to_secs_str, ErrorReported};
 
 use syntax::ast::NodeId;
 use errors::{self, DiagnosticBuilder};
@@ -79,10 +79,10 @@ pub struct Session {
     pub working_dir: (String, bool),
     pub lint_store: RefCell<lint::LintStore>,
     pub lints: RefCell<lint::LintTable>,
-    /// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics
-    /// that have been set once, but should not be set again, in order to avoid
-    /// redundantly verbose output (Issue #24690).
-    pub one_time_diagnostics: RefCell<FxHashSet<(lint::LintId, Span, String)>>,
+    /// Set of (LintId, Option<Span>, message) tuples tracking lint
+    /// (sub)diagnostics that have been set once, but should not be set again,
+    /// in order to avoid redundantly verbose output (Issue #24690).
+    pub one_time_diagnostics: RefCell<FxHashSet<(lint::LintId, Option<Span>, String)>>,
     pub plugin_llvm_passes: RefCell<Vec<String>>,
     pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
     pub crate_types: RefCell<Vec<config::CrateType>>,
@@ -157,6 +157,13 @@ pub struct PerfStats {
     pub decode_def_path_tables_time: Cell<Duration>,
 }
 
+/// Enum to support dispatch of one-time diagnostics (in Session.diag_once)
+enum DiagnosticBuilderMethod {
+    Note,
+    SpanNote,
+    // add more variants as needed to support one-time diagnostics
+}
+
 impl Session {
     pub fn local_crate_disambiguator(&self) -> Symbol {
         *self.crate_disambiguator.borrow()
@@ -248,7 +255,10 @@ impl Session {
     pub fn abort_if_errors(&self) {
         self.diagnostic().abort_if_errors();
     }
-    pub fn track_errors<F, T>(&self, f: F) -> Result<T, usize>
+    pub fn compile_status(&self) -> Result<(), CompileIncomplete> {
+        compile_result_from_err_count(self.err_count())
+    }
+    pub fn track_errors<F, T>(&self, f: F) -> Result<T, ErrorReported>
         where F: FnOnce() -> T
     {
         let old_count = self.err_count();
@@ -257,7 +267,7 @@ impl Session {
         if errors == 0 {
             Ok(result)
         } else {
-            Err(errors)
+            Err(ErrorReported)
         }
     }
     pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
@@ -329,34 +339,53 @@ impl Session {
         &self.parse_sess.span_diagnostic
     }
 
-    /// Analogous to calling `.span_note` on the given DiagnosticBuilder, but
-    /// deduplicates on lint ID, span, and message for this `Session` if we're
-    /// not outputting in JSON mode.
-    //
-    // FIXME: if the need arises for one-time diagnostics other than
-    // `span_note`, we almost certainly want to generalize this
-    // "check/insert-into the one-time diagnostics map, then set message if
-    // it's not already there" code to accomodate all of them
-    pub fn diag_span_note_once<'a, 'b>(&'a self,
-                                       diag_builder: &'b mut DiagnosticBuilder<'a>,
-                                       lint: &'static lint::Lint, span: Span, message: &str) {
+    /// Analogous to calling methods on the given `DiagnosticBuilder`, but
+    /// deduplicates on lint ID, span (if any), and message for this `Session`
+    /// if we're not outputting in JSON mode.
+    fn diag_once<'a, 'b>(&'a self,
+                         diag_builder: &'b mut DiagnosticBuilder<'a>,
+                         method: DiagnosticBuilderMethod,
+                         lint: &'static lint::Lint, message: &str, span: Option<Span>) {
+        let mut do_method = || {
+            match method {
+                DiagnosticBuilderMethod::Note => {
+                    diag_builder.note(message);
+                },
+                DiagnosticBuilderMethod::SpanNote => {
+                    diag_builder.span_note(span.expect("span_note expects a span"), message);
+                }
+            }
+        };
+
         match self.opts.error_format {
             // when outputting JSON for tool consumption, the tool might want
             // the duplicates
             config::ErrorOutputType::Json => {
-                diag_builder.span_note(span, &message);
+                do_method()
             },
             _ => {
                 let lint_id = lint::LintId::of(lint);
                 let id_span_message = (lint_id, span, message.to_owned());
                 let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message);
                 if fresh {
-                    diag_builder.span_note(span, &message);
+                    do_method()
                 }
             }
         }
     }
 
+    pub fn diag_span_note_once<'a, 'b>(&'a self,
+                                       diag_builder: &'b mut DiagnosticBuilder<'a>,
+                                       lint: &'static lint::Lint, span: Span, message: &str) {
+        self.diag_once(diag_builder, DiagnosticBuilderMethod::SpanNote, lint, message, Some(span));
+    }
+
+    pub fn diag_note_once<'a, 'b>(&'a self,
+                                  diag_builder: &'b mut DiagnosticBuilder<'a>,
+                                  lint: &'static lint::Lint, message: &str) {
+        self.diag_once(diag_builder, DiagnosticBuilderMethod::Note, lint, message, None);
+    }
+
     pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
         self.parse_sess.codemap()
     }
@@ -776,15 +805,23 @@ pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
     handler.emit(&MultiSpan::new(), msg, errors::Level::Warning);
 }
 
-// Err(0) means compilation was stopped, but no errors were found.
-// This would be better as a dedicated enum, but using try! is so convenient.
-pub type CompileResult = Result<(), usize>;
+#[derive(Copy, Clone, Debug)]
+pub enum CompileIncomplete {
+    Stopped,
+    Errored(ErrorReported)
+}
+impl From<ErrorReported> for CompileIncomplete {
+    fn from(err: ErrorReported) -> CompileIncomplete {
+        CompileIncomplete::Errored(err)
+    }
+}
+pub type CompileResult = Result<(), CompileIncomplete>;
 
 pub fn compile_result_from_err_count(err_count: usize) -> CompileResult {
     if err_count == 0 {
         Ok(())
     } else {
-        Err(err_count)
+        Err(CompileIncomplete::Errored(ErrorReported))
     }
 }
 
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 247fb079fe7..0bf0e21baaf 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -45,7 +45,8 @@ use syntax_pos::{DUMMY_SP, Span};
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn report_fulfillment_errors(&self,
-                                     errors: &Vec<FulfillmentError<'tcx>>) {
+                                     errors: &Vec<FulfillmentError<'tcx>>,
+                                     body_id: Option<hir::BodyId>) {
         #[derive(Debug)]
         struct ErrorDescriptor<'tcx> {
             predicate: ty::Predicate<'tcx>,
@@ -105,7 +106,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
         for (error, suppressed) in errors.iter().zip(is_suppressed) {
             if !suppressed {
-                self.report_fulfillment_error(error);
+                self.report_fulfillment_error(error, body_id);
             }
         }
     }
@@ -148,7 +149,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         false
     }
 
-    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) {
+    fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>,
+                                body_id: Option<hir::BodyId>) {
         debug!("report_fulfillment_errors({:?})", error);
         match error.code {
             FulfillmentErrorCode::CodeSelectionError(ref e) => {
@@ -158,7 +160,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 self.report_projection_error(&error.obligation, e);
             }
             FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation);
+                self.maybe_report_ambiguity(&error.obligation, body_id);
             }
             FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
                 self.report_mismatched_types(&error.obligation.cause,
@@ -869,14 +871,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
+    fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>,
+                              body_id: Option<hir::BodyId>) {
         // Unable to successfully determine, probably means
         // insufficient type information, but could mean
         // ambiguous impls. The latter *ought* to be a
         // coherence violation, so we don't report it here.
 
         let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
-        let body_id = hir::BodyId { node_id: obligation.cause.body_id };
         let span = obligation.cause.span;
 
         debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
@@ -953,7 +955,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
                     // both must be type variables, or the other would've been instantiated
                     assert!(a.is_ty_var() && b.is_ty_var());
-                    self.need_type_info(hir::BodyId { node_id: obligation.cause.body_id },
+                    self.need_type_info(body_id,
                                         obligation.cause.span,
                                         a);
                 }
@@ -1058,7 +1060,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 err.note("slice and array elements must have `Sized` type");
             }
             ObligationCauseCode::TupleElem => {
-                err.note("tuple elements must have `Sized` type");
+                err.note("only the last element of a tuple may have a dynamically sized type");
             }
             ObligationCauseCode::ProjectionWf(data) => {
                 err.note(&format!("required so that the projection `{}` is well-formed",
@@ -1088,13 +1090,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             ObligationCauseCode::VariableType(_) => {
                 err.note("all local variables must have a statically known size");
             }
-            ObligationCauseCode::ReturnType => {
+            ObligationCauseCode::SizedReturnType => {
                 err.note("the return type of a function must have a \
                           statically known size");
             }
             ObligationCauseCode::AssignmentLhsSized => {
                 err.note("the left-hand-side of an assignment must have a statically known size");
             }
+            ObligationCauseCode::TupleInitializerSized => {
+                err.note("tuples must have a statically known size to be initialized");
+            }
             ObligationCauseCode::StructInitializerSized => {
                 err.note("structs must have a statically known size to be initialized");
             }
@@ -1133,6 +1138,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                               but not on the corresponding trait method",
                              predicate));
             }
+            ObligationCauseCode::ReturnType(_) |
+            ObligationCauseCode::BlockTailExpression(_) => (),
         }
     }
 
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index e9196cd1243..16c41c816b4 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -118,27 +118,34 @@ pub enum ObligationCauseCode<'tcx> {
     /// Obligation incurred due to an object cast.
     ObjectCastObligation(/* Object type */ Ty<'tcx>),
 
-    /// Various cases where expressions must be sized/copy/etc:
-    AssignmentLhsSized,        // L = X implies that L is Sized
-    StructInitializerSized,    // S { ... } must be Sized
-    VariableType(ast::NodeId), // Type of each variable must be Sized
-    ReturnType,                // Return type must be Sized
-    RepeatVec,                 // [T,..n] --> T must be Copy
-
-    // Types of fields (other than the last) in a struct must be sized.
+    // Various cases where expressions must be sized/copy/etc:
+    /// L = X implies that L is Sized
+    AssignmentLhsSized,
+    /// (x1, .., xn) must be Sized
+    TupleInitializerSized,
+    /// S { ... } must be Sized
+    StructInitializerSized,
+    /// Type of each variable must be Sized
+    VariableType(ast::NodeId),
+    /// Return type must be Sized
+    SizedReturnType,
+    /// [T,..n] --> T must be Copy
+    RepeatVec,
+
+    /// Types of fields (other than the last) in a struct must be sized.
     FieldSized,
 
-    // Constant expressions must be sized.
+    /// Constant expressions must be sized.
     ConstSized,
 
-    // static items must have `Sync` type
+    /// static items must have `Sync` type
     SharedStatic,
 
     BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
 
     ImplDerivedObligation(DerivedObligationCause<'tcx>),
 
-    // error derived when matching traits/impls; see ObligationCause for more details
+    /// error derived when matching traits/impls; see ObligationCause for more details
     CompareImplMethodObligation {
         item_name: ast::Name,
         impl_item_def_id: DefId,
@@ -146,37 +153,43 @@ pub enum ObligationCauseCode<'tcx> {
         lint_id: Option<ast::NodeId>,
     },
 
-    // Checking that this expression can be assigned where it needs to be
+    /// Checking that this expression can be assigned where it needs to be
     // FIXME(eddyb) #11161 is the original Expr required?
     ExprAssignable,
 
-    // Computing common supertype in the arms of a match expression
+    /// Computing common supertype in the arms of a match expression
     MatchExpressionArm { arm_span: Span,
                          source: hir::MatchSource },
 
-    // Computing common supertype in an if expression
+    /// Computing common supertype in an if expression
     IfExpression,
 
-    // Computing common supertype of an if expression with no else counter-part
+    /// Computing common supertype of an if expression with no else counter-part
     IfExpressionWithNoElse,
 
-    // `where a == b`
+    /// `where a == b`
     EquatePredicate,
 
-    // `main` has wrong type
+    /// `main` has wrong type
     MainFunctionType,
 
-    // `start` has wrong type
+    /// `start` has wrong type
     StartFunctionType,
 
-    // intrinsic has wrong type
+    /// intrinsic has wrong type
     IntrinsicType,
 
-    // method receiver
+    /// method receiver
     MethodReceiver,
 
-    // `return` with no expression
+    /// `return` with no expression
     ReturnNoExpression,
+
+    /// `return` with an expression
+    ReturnType(ast::NodeId),
+
+    /// Block implicit return
+    BlockTailExpression(ast::NodeId),
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -498,7 +511,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ) {
             Ok(predicates) => predicates,
             Err(errors) => {
-                infcx.report_fulfillment_errors(&errors);
+                infcx.report_fulfillment_errors(&errors, None);
                 // An unnormalized env is better than nothing.
                 return elaborated_env;
             }
@@ -597,7 +610,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("normalize_and_test_predicates(predicates={:?})",
            predicates);
 
-    tcx.infer_ctxt().enter(|infcx| {
+    let result = tcx.infer_ctxt().enter(|infcx| {
         let param_env = ty::ParamEnv::empty(Reveal::All);
         let mut selcx = SelectionContext::new(&infcx);
         let mut fulfill_cx = FulfillmentContext::new();
@@ -613,7 +626,10 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
 
         fulfill_cx.select_all_or_error(&infcx).is_ok()
-    })
+    });
+    debug!("normalize_and_test_predicates(predicates={:?}) = {:?}",
+           predicates, result);
+    result
 }
 
 /// Given a trait `trait_ref`, iterates the vtable entries
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 0e3a53129d1..c6c052fa4b1 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         // The `Self` type is erased, so it should not appear in list of
         // arguments or return type apart from the receiver.
-        let ref sig = self.type_of(method.def_id).fn_sig();
+        let ref sig = self.fn_sig(method.def_id);
         for input_ty in &sig.skip_binder().inputs()[1..] {
             if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
                 return Some(MethodViolationCode::ReferencesSelf);
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 787452121d3..c356e53234d 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1137,9 +1137,19 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>(
     -> Progress<'tcx>
 {
     let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty);
-    let sig = fn_type.fn_sig();
+    let sig = fn_type.fn_sig(selcx.tcx());
+    let Normalized {
+        value: sig,
+        obligations
+    } = normalize_with_depth(selcx,
+                             obligation.param_env,
+                             obligation.cause.clone(),
+                             obligation.recursion_depth+1,
+                             &sig);
+
     confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
         .with_addl_obligations(fn_pointer_vtable.nested)
+        .with_addl_obligations(obligations)
 }
 
 fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
@@ -1149,7 +1159,7 @@ fn confirm_closure_candidate<'cx, 'gcx, 'tcx>(
     -> Progress<'tcx>
 {
     let closure_typer = selcx.closure_typer();
-    let closure_type = closure_typer.closure_type(vtable.closure_def_id)
+    let closure_type = closure_typer.fn_sig(vtable.closure_def_id)
         .subst(selcx.tcx(), vtable.substs.substs);
     let Normalized {
         value: closure_type,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 10710d963a0..856fea7c2c4 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1404,19 +1404,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             }
 
             // provide an impl, but only for suitable `fn` pointers
-            ty::TyFnDef(.., ty::Binder(ty::FnSig {
-                unsafety: hir::Unsafety::Normal,
-                abi: Abi::Rust,
-                variadic: false,
-                ..
-            })) |
-            ty::TyFnPtr(ty::Binder(ty::FnSig {
-                unsafety: hir::Unsafety::Normal,
-                abi: Abi::Rust,
-                variadic: false,
-                ..
-            })) => {
-                candidates.vec.push(FnPointerCandidate);
+            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+                if let ty::Binder(ty::FnSig {
+                    unsafety: hir::Unsafety::Normal,
+                    abi: Abi::Rust,
+                    variadic: false,
+                    ..
+                }) = self_ty.fn_sig(self.tcx()) {
+                    candidates.vec.push(FnPointerCandidate);
+                }
             }
 
             _ => { }
@@ -1655,6 +1651,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 def_id_a == def_id_b
             }
 
+            // (.., T) -> (.., U).
+            (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => {
+                tys_a.len() == tys_b.len()
+            }
+
             _ => false
         };
 
@@ -2348,7 +2349,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         // ok to skip binder; it is reintroduced below
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let sig = self_ty.fn_sig();
+        let sig = self_ty.fn_sig(self.tcx());
         let trait_ref =
             self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
                                                          self_ty,
@@ -2356,11 +2357,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                                          util::TupleArgumentsFlag::Yes)
             .map_bound(|(trait_ref, _)| trait_ref);
 
+        let Normalized { value: trait_ref, obligations } =
+            project::normalize_with_depth(self,
+                                          obligation.param_env,
+                                          obligation.cause.clone(),
+                                          obligation.recursion_depth + 1,
+                                          &trait_ref);
+
         self.confirm_poly_trait_refs(obligation.cause.clone(),
                                      obligation.param_env,
                                      obligation.predicate.to_poly_trait_ref(),
                                      trait_ref)?;
-        Ok(VtableFnPointerData { fn_ty: self_ty, nested: vec![] })
+        Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
     }
 
     fn confirm_closure_candidate(&mut self,
@@ -2588,8 +2596,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 let inner_source = field.subst(tcx, substs_a);
                 let inner_target = field.subst(tcx, substs_b);
 
-                // Check that the source structure with the target's
-                // type parameters is a subtype of the target.
+                // Check that the source struct with the target's
+                // unsized parameters is equal to the target.
                 let params = substs_a.iter().enumerate().map(|(i, &k)| {
                     if ty_params.contains(i) {
                         Kind::from(substs_b.type_at(i))
@@ -2614,6 +2622,37 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     &[inner_target]));
             }
 
+            // (.., T) -> (.., U).
+            (&ty::TyTuple(tys_a, _), &ty::TyTuple(tys_b, _)) => {
+                assert_eq!(tys_a.len(), tys_b.len());
+
+                // The last field of the tuple has to exist.
+                let (a_last, a_mid) = if let Some(x) = tys_a.split_last() {
+                    x
+                } else {
+                    return Err(Unimplemented);
+                };
+                let b_last = tys_b.last().unwrap();
+
+                // Check that the source tuple with the target's
+                // last element is equal to the target.
+                let new_tuple = tcx.mk_tup(a_mid.iter().chain(Some(b_last)), false);
+                let InferOk { obligations, .. } =
+                    self.infcx.at(&obligation.cause, obligation.param_env)
+                              .eq(target, new_tuple)
+                              .map_err(|_| Unimplemented)?;
+                self.inferred_obligations.extend(obligations);
+
+                // Construct the nested T: Unsize<U> predicate.
+                nested.push(tcx.predicate_for_trait_def(
+                    obligation.param_env,
+                    obligation.cause.clone(),
+                    obligation.predicate.def_id(),
+                    obligation.recursion_depth + 1,
+                    a_last,
+                    &[b_last]));
+            }
+
             _ => bug!()
         };
 
@@ -2799,7 +2838,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                       substs: ty::ClosureSubsts<'tcx>)
                                       -> ty::PolyTraitRef<'tcx>
     {
-        let closure_type = self.infcx.closure_type(closure_def_id)
+        let closure_type = self.infcx.fn_sig(closure_def_id)
             .subst(self.tcx(), substs.substs);
         let ty::Binder((trait_ref, _)) =
             self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 4abb0cb549d..c4479e69032 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -189,9 +189,11 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                 tcx.lift(&ty).map(super::ObjectCastObligation)
             }
             super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
+            super::TupleInitializerSized => Some(super::TupleInitializerSized),
             super::StructInitializerSized => Some(super::StructInitializerSized),
             super::VariableType(id) => Some(super::VariableType(id)),
-            super::ReturnType => Some(super::ReturnType),
+            super::ReturnType(id) => Some(super::ReturnType(id)),
+            super::SizedReturnType => Some(super::SizedReturnType),
             super::RepeatVec => Some(super::RepeatVec),
             super::FieldSized => Some(super::FieldSized),
             super::ConstSized => Some(super::ConstSized),
@@ -213,34 +215,19 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                     lint_id: lint_id,
                 })
             }
-            super::ExprAssignable => {
-                Some(super::ExprAssignable)
-            }
+            super::ExprAssignable => Some(super::ExprAssignable),
             super::MatchExpressionArm { arm_span, source } => {
                 Some(super::MatchExpressionArm { arm_span: arm_span,
                                                  source: source })
             }
-            super::IfExpression => {
-                Some(super::IfExpression)
-            }
-            super::IfExpressionWithNoElse => {
-                Some(super::IfExpressionWithNoElse)
-            }
-            super::EquatePredicate => {
-                Some(super::EquatePredicate)
-            }
-            super::MainFunctionType => {
-                Some(super::MainFunctionType)
-            }
-            super::StartFunctionType => {
-                Some(super::StartFunctionType)
-            }
-            super::IntrinsicType => {
-                Some(super::IntrinsicType)
-            }
-            super::MethodReceiver => {
-                Some(super::MethodReceiver)
-            }
+            super::IfExpression => Some(super::IfExpression),
+            super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
+            super::EquatePredicate => Some(super::EquatePredicate),
+            super::MainFunctionType => Some(super::MainFunctionType),
+            super::StartFunctionType => Some(super::StartFunctionType),
+            super::IntrinsicType => Some(super::IntrinsicType),
+            super::MethodReceiver => Some(super::MethodReceiver),
+            super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
         }
     }
 }
@@ -490,14 +477,17 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
             super::TupleElem |
             super::ItemObligation(_) |
             super::AssignmentLhsSized |
+            super::TupleInitializerSized |
             super::StructInitializerSized |
             super::VariableType(_) |
-            super::ReturnType |
+            super::ReturnType(_) |
+            super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
             super::FieldSized |
             super::ConstSized |
             super::SharedStatic |
+            super::BlockTailExpression(_) |
             super::CompareImplMethodObligation { .. } => self.clone(),
 
             super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)),
@@ -535,14 +525,17 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
             super::TupleElem |
             super::ItemObligation(_) |
             super::AssignmentLhsSized |
+            super::TupleInitializerSized |
             super::StructInitializerSized |
             super::VariableType(_) |
-            super::ReturnType |
+            super::ReturnType(_) |
+            super::SizedReturnType |
             super::ReturnNoExpression |
             super::RepeatVec |
             super::FieldSized |
             super::ConstSized |
             super::SharedStatic |
+            super::BlockTailExpression(_) |
             super::CompareImplMethodObligation { .. } => false,
 
             super::ProjectionWf(proj) => proj.visit_with(visitor),
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 2d81606329e..5f869fc5567 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1378,9 +1378,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn mk_fn_def(self, def_id: DefId,
-                     substs: &'tcx Substs<'tcx>,
-                     fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyFnDef(def_id, substs, fty))
+                     substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyFnDef(def_id, substs))
     }
 
     pub fn mk_fn_ptr(self, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 3d2cc4c598a..68f85ba7d33 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -68,6 +68,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             // view of possibly unifying
             simplify_type(tcx, mt.ty, can_simplify_params)
         }
+        ty::TyFnDef(def_id, _) |
         ty::TyClosure(def_id, _) => {
             Some(ClosureSimplifiedType(def_id))
         }
@@ -75,7 +76,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::TyTuple(ref tys, _) => {
             Some(TupleSimplifiedType(tys.len()))
         }
-        ty::TyFnDef(.., ref f) | ty::TyFnPtr(ref f) => {
+        ty::TyFnPtr(ref f) => {
             Some(FunctionSimplifiedType(f.skip_binder().inputs().len()))
         }
         ty::TyProjection(_) | ty::TyParam(_) => {
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 46afa6ee7d0..d5aa9f55ff0 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -155,9 +155,8 @@ impl FlagComputation {
                 self.add_tys(&ts[..]);
             }
 
-            &ty::TyFnDef(_, substs, f) => {
+            &ty::TyFnDef(_, substs) => {
                 self.add_substs(substs);
-                self.add_fn_sig(f);
             }
 
             &ty::TyFnPtr(f) => {
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 09a3bcd0613..b9896e0cecf 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -348,7 +348,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
                                       .filter_map(|ty| characteristic_def_id_of_type(ty))
                                       .next(),
 
-        ty::TyFnDef(def_id, ..) |
+        ty::TyFnDef(def_id, _) |
         ty::TyClosure(def_id, _) => Some(def_id),
 
         ty::TyBool |
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 12af56d5c3d..e1aa89078a3 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1220,12 +1220,16 @@ impl<'a, 'tcx> Layout {
             }
 
             ty::TyTuple(tys, _) => {
-                // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked.
-                // See the univariant case below to learn how.
+                let kind = if tys.len() == 0 {
+                    StructKind::AlwaysSizedUnivariant
+                } else {
+                    StructKind::MaybeUnsizedUnivariant
+                };
+
                 let st = Struct::new(dl,
                     &tys.iter().map(|ty| ty.layout(tcx, param_env))
                       .collect::<Result<Vec<_>, _>>()?,
-                    &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
+                    &ReprOptions::default(), kind, ty)?;
                 Univariant { variant: st, non_zero: false }
             }
 
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index 524cf57472b..a6c59d4c223 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -875,13 +875,12 @@ define_maps! { <'tcx>
     /// for trans. This is also the only query that can fetch non-local MIR, at present.
     [] optimized_mir: Mir(DefId) -> &'tcx mir::Mir<'tcx>,
 
-    /// Records the type of each closure. The def ID is the ID of the
+    /// Type of each closure. The def ID is the ID of the
     /// expression defining the closure.
     [] closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
 
-    /// Records the type of each closure. The def ID is the ID of the
-    /// expression defining the closure.
-    [] closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
+    /// The signature of functions and closures.
+    [] fn_sig: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
     [] coerce_unsized_info: ItemSignature(DefId)
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 13e46a265c6..548ee7bcbe5 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -206,7 +206,7 @@ impl AssociatedItem {
                 // late-bound regions, and we don't want method signatures to show up
                 // `as for<'r> fn(&'r MyType)`.  Pretty-printing handles late-bound
                 // regions just fine, showing `fn(&MyType)`.
-                format!("{}", tcx.type_of(self.def_id).fn_sig().skip_binder())
+                format!("{}", tcx.fn_sig(self.def_id).skip_binder())
             }
             ty::AssociatedKind::Type => format!("type {};", self.name.to_string()),
             ty::AssociatedKind::Const => {
@@ -481,6 +481,18 @@ impl<'tcx> TyS<'tcx> {
             _ => false,
         }
     }
+
+    pub fn is_suggestable(&self) -> bool {
+        match self.sty {
+            TypeVariants::TyAnon(..) |
+            TypeVariants::TyFnDef(..) |
+            TypeVariants::TyFnPtr(..) |
+            TypeVariants::TyDynamic(..) |
+            TypeVariants::TyClosure(..) |
+            TypeVariants::TyProjection(..) => false,
+            _ => true,
+        }
+    }
 }
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::TyS<'tcx> {
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index d4f06a902ee..2e9780572c9 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -291,7 +291,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> {
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+            let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::TraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -308,7 +308,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
         if a.def_id != b.def_id {
             Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
         } else {
-            let substs = relation.relate_item_substs(a.def_id, a.substs, b.substs)?;
+            let substs = relate_substs(relation, None, a.substs, b.substs)?;
             Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
         }
     }
@@ -440,13 +440,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             }
         }
 
-        (&ty::TyFnDef(a_def_id, a_substs, a_fty),
-         &ty::TyFnDef(b_def_id, b_substs, b_fty))
+        (&ty::TyFnDef(a_def_id, a_substs), &ty::TyFnDef(b_def_id, b_substs))
             if a_def_id == b_def_id =>
         {
-            let substs = relate_substs(relation, None, a_substs, b_substs)?;
-            let fty = relation.relate(&a_fty, &b_fty)?;
-            Ok(tcx.mk_fn_def(a_def_id, substs, fty))
+            let substs = relation.relate_item_substs(a_def_id, a_substs, b_substs)?;
+            Ok(tcx.mk_fn_def(a_def_id, substs))
         }
 
         (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) =>
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 1e268924390..d05262965d7 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -531,10 +531,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::TyDynamic(ref trait_ty, ref region) =>
                 ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)),
             ty::TyTuple(ts, defaulted) => ty::TyTuple(ts.fold_with(folder), defaulted),
-            ty::TyFnDef(def_id, substs, f) => {
-                ty::TyFnDef(def_id,
-                            substs.fold_with(folder),
-                            f.fold_with(folder))
+            ty::TyFnDef(def_id, substs) => {
+                ty::TyFnDef(def_id, substs.fold_with(folder))
             }
             ty::TyFnPtr(f) => ty::TyFnPtr(f.fold_with(folder)),
             ty::TyRef(ref r, tm) => {
@@ -568,9 +566,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::TyDynamic(ref trait_ty, ref reg) =>
                 trait_ty.visit_with(visitor) || reg.visit_with(visitor),
             ty::TyTuple(ts, _) => ts.visit_with(visitor),
-            ty::TyFnDef(_, substs, ref f) => {
-                substs.visit_with(visitor) || f.visit_with(visitor)
-            }
+            ty::TyFnDef(_, substs) => substs.visit_with(visitor),
             ty::TyFnPtr(ref f) => f.visit_with(visitor),
             ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 6923a6d21d6..452775e9e13 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -14,7 +14,7 @@ use hir::def_id::DefId;
 use hir::map::DefPathHash;
 
 use middle::region;
-use ty::subst::Substs;
+use ty::subst::{Substs, Subst};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
 use ty::subst::Kind;
@@ -138,7 +138,7 @@ pub enum TypeVariants<'tcx> {
 
     /// The anonymous type of a function declaration/definition. Each
     /// function has a unique type.
-    TyFnDef(DefId, &'tcx Substs<'tcx>, PolyFnSig<'tcx>),
+    TyFnDef(DefId, &'tcx Substs<'tcx>),
 
     /// A pointer to a function.  Written as `fn() -> i32`.
     TyFnPtr(PolyFnSig<'tcx>),
@@ -990,6 +990,20 @@ impl RegionKind {
 
         flags
     }
+
+    // This method returns whether the given Region is Named
+    pub fn is_named_region(&self) -> bool {
+
+        match *self {
+            ty::ReFree(ref free_region) => {
+                match free_region.bound_region {
+                    ty::BrNamed(..) => true,
+                    _ => false,
+                }
+            }
+            _ => false,
+        }
+    }
 }
 
 /// Type utilities
@@ -1329,9 +1343,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
         }
     }
 
-    pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
+    pub fn fn_sig(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PolyFnSig<'tcx> {
         match self.sty {
-            TyFnDef(.., f) | TyFnPtr(f) => f,
+            TyFnDef(def_id, substs) => {
+                tcx.fn_sig(def_id).subst(tcx, substs)
+            }
+            TyFnPtr(f) => f,
             _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
         }
     }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 1bbc7673485..df4bbad3859 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -317,15 +317,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                  target: Ty<'tcx>)
                                  -> (Ty<'tcx>, Ty<'tcx>) {
         let (mut a, mut b) = (source, target);
-        while let (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs)) = (&a.sty, &b.sty) {
-            if a_def != b_def || !a_def.is_struct() {
-                break;
-            }
-            match a_def.struct_variant().fields.last() {
-                Some(f) => {
-                    a = f.ty(self, a_substs);
-                    b = f.ty(self, b_substs);
-                }
+        loop {
+            match (&a.sty, &b.sty) {
+                (&TyAdt(a_def, a_substs), &TyAdt(b_def, b_substs))
+                        if a_def == b_def && a_def.is_struct() => {
+                    if let Some(f) = a_def.struct_variant().fields.last() {
+                        a = f.ty(self, a_substs);
+                        b = f.ty(self, b_substs);
+                    } else {
+                        break;
+                    }
+                },
+                (&TyTuple(a_tys, _), &TyTuple(b_tys, _))
+                        if a_tys.len() == b_tys.len() => {
+                    if let Some(a_last) = a_tys.last() {
+                        a = a_last;
+                        b = b_tys.last().unwrap();
+                    } else {
+                        break;
+                    }
+                },
                 _ => break,
             }
         }
@@ -679,7 +690,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
             TyRef(_, m) => self.hash(m.mutbl),
             TyClosure(def_id, _) |
             TyAnon(def_id, _) |
-            TyFnDef(def_id, ..) => self.def_id(def_id),
+            TyFnDef(def_id, _) => self.def_id(def_id),
             TyAdt(d, _) => self.def_id(d.did),
             TyFnPtr(f) => {
                 self.hash(f.unsafety());
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index d7954953aba..71844abfe53 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -115,9 +115,8 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::TyTuple(ts, _) => {
             stack.extend(ts.iter().cloned().rev());
         }
-        ty::TyFnDef(_, substs, ft) => {
+        ty::TyFnDef(_, substs) => {
             stack.extend(substs.types().rev());
-            push_sig_subtypes(stack, ft);
         }
         ty::TyFnPtr(ft) => {
             push_sig_subtypes(stack, ft);
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 1fa63577196..eb6bffc29c5 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -753,8 +753,14 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
                 }
                 write!(f, ")")
             }
-            TyFnDef(def_id, substs, ref bare_fn) => {
-                write!(f, "{} {{", bare_fn.0)?;
+            TyFnDef(def_id, substs) => {
+                ty::tls::with(|tcx| {
+                    let mut sig = tcx.fn_sig(def_id);
+                    if let Some(substs) = tcx.lift(&substs) {
+                        sig = sig.subst(tcx, substs);
+                    }
+                    write!(f, "{} {{", sig.0)
+                })?;
                 parameterized(f, substs, def_id, &[])?;
                 write!(f, "}}")
             }
diff --git a/src/librustc_asan/build.rs b/src/librustc_asan/build.rs
index 3a80baa0485..cb7721affe7 100644
--- a/src/librustc_asan/build.rs
+++ b/src/librustc_asan/build.rs
@@ -32,4 +32,5 @@ fn main() {
             .build_target("asan")
             .build();
     }
+    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
 }
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index c72bdd04011..3be7c43cab9 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -18,8 +18,6 @@ pub use self::bckerr_code::*;
 pub use self::AliasableViolationKind::*;
 pub use self::MovedValueUseKind::*;
 
-pub use self::mir::elaborate_drops::ElaborateDrops;
-
 use self::InteriorKind::*;
 
 use rustc::hir::map as hir_map;
@@ -55,8 +53,6 @@ pub mod gather_loans;
 
 pub mod move_data;
 
-mod mir;
-
 #[derive(Clone, Copy)]
 pub struct LoanDataFlowOperator;
 
@@ -100,26 +96,21 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) {
     }
 
     let body_id = tcx.hir.body_owned_by(owner_id);
-    let attributes = tcx.get_attrs(owner_def_id);
     let tables = tcx.typeck_tables_of(owner_def_id);
     let region_maps = tcx.region_maps(owner_def_id);
     let mut bccx = &mut BorrowckCtxt { tcx, tables, region_maps, owner_def_id };
 
     let body = bccx.tcx.hir.body(body_id);
 
-    if bccx.tcx.has_attr(owner_def_id, "rustc_mir_borrowck") {
-        mir::borrowck_mir(bccx, owner_id, &attributes);
-    } else {
-        // Eventually, borrowck will always read the MIR, but at the
-        // moment we do not. So, for now, we always force MIR to be
-        // constructed for a given fn, since this may result in errors
-        // being reported and we want that to happen.
-        //
-        // Note that `mir_validated` is a "stealable" result; the
-        // thief, `optimized_mir()`, forces borrowck, so we know that
-        // is not yet stolen.
-        tcx.mir_validated(owner_def_id).borrow();
-    }
+    // Eventually, borrowck will always read the MIR, but at the
+    // moment we do not. So, for now, we always force MIR to be
+    // constructed for a given fn, since this may result in errors
+    // being reported and we want that to happen.
+    //
+    // Note that `mir_validated` is a "stealable" result; the
+    // thief, `optimized_mir()`, forces borrowck, so we know that
+    // is not yet stolen.
+    tcx.mir_validated(owner_def_id).borrow();
 
     let cfg = cfg::CFG::new(bccx.tcx, &body);
     let AnalysisData { all_loans,
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 9c980ddf08a..a2b1e3c2663 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -21,7 +21,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(associated_consts)]
-#![feature(nonzero)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -39,7 +38,7 @@ extern crate core; // for NonZero
 
 pub use borrowck::check_crate;
 pub use borrowck::build_borrowck_dataflow_data_for_fn;
-pub use borrowck::{AnalysisData, BorrowckCtxt, ElaborateDrops};
+pub use borrowck::{AnalysisData, BorrowckCtxt};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index d175920e8a6..0a966b0c170 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -12,7 +12,7 @@ use eval;
 
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
 use rustc::mir::{Field, BorrowKind, Mutability};
-use rustc::ty::{self, TyCtxt, AdtDef, Ty, TypeVariants, Region};
+use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
 use rustc::hir::def::{Def, CtorKind};
@@ -549,8 +549,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
                 let adt_def = self.tcx.adt_def(enum_id);
                 if adt_def.variants.len() > 1 {
                     let substs = match ty.sty {
-                        TypeVariants::TyAdt(_, substs) => substs,
-                        TypeVariants::TyFnDef(_, substs, _) => substs,
+                        ty::TyAdt(_, substs) |
+                        ty::TyFnDef(_, substs) => substs,
                         _ => bug!("inappropriate type for def: {:?}", ty.sty),
                     };
                     PatternKind::Variant {
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 159fee6aa4c..a3e1cf7c1a8 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -13,7 +13,8 @@ use rustc::hir::lowering::lower_crate;
 use rustc::ich::Fingerprint;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_mir as mir;
-use rustc::session::{Session, CompileResult, compile_result_from_err_count};
+use rustc::session::{Session, CompileResult};
+use rustc::session::CompileIncomplete;
 use rustc::session::config::{self, Input, OutputFilenames, OutputType,
                              OutputTypes};
 use rustc::session::search_paths::PathKind;
@@ -23,7 +24,7 @@ use rustc::middle::privacy::AccessLevels;
 use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes};
 use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
 use rustc::traits;
-use rustc::util::common::time;
+use rustc::util::common::{ErrorReported, time};
 use rustc::util::nodemap::NodeSet;
 use rustc::util::fs::rename_or_copy_remove;
 use rustc_borrowck as borrowck;
@@ -78,7 +79,9 @@ pub fn compile_input(sess: &Session,
             }
 
             if control.$point.stop == Compilation::Stop {
-                return compile_result_from_err_count($tsess.err_count());
+                // FIXME: shouldn't this return Err(CompileIncomplete::Stopped)
+                // if there are no errors?
+                return $tsess.compile_status();
             }
         }}
     }
@@ -91,7 +94,7 @@ pub fn compile_input(sess: &Session,
             Ok(krate) => krate,
             Err(mut parse_error) => {
                 parse_error.emit();
-                return Err(1);
+                return Err(CompileIncomplete::Errored(ErrorReported));
             }
         };
 
@@ -194,7 +197,7 @@ pub fn compile_input(sess: &Session,
                 (control.after_analysis.callback)(&mut state);
 
                 if control.after_analysis.stop == Compilation::Stop {
-                    return result.and_then(|_| Err(0usize));
+                    return result.and_then(|_| Err(CompileIncomplete::Stopped));
                 }
             }
 
@@ -564,7 +567,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
                                        addl_plugins: Option<Vec<String>>,
                                        make_glob_map: MakeGlobMap,
                                        after_expand: F)
-                                       -> Result<ExpansionResult, usize>
+                                       -> Result<ExpansionResult, CompileIncomplete>
     where F: FnOnce(&ast::Crate) -> CompileResult,
 {
     let time_passes = sess.time_passes();
@@ -636,7 +639,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     // Lint plugins are registered; now we can process command line flags.
     if sess.opts.describe_lints {
         super::describe_lints(&sess.lint_store.borrow(), true);
-        return Err(0);
+        return Err(CompileIncomplete::Stopped);
     }
     sess.track_errors(|| sess.lint_store.borrow_mut().process_command_line(sess))?;
 
@@ -839,7 +842,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                arenas: &'tcx GlobalArenas<'tcx>,
                                                name: &str,
                                                f: F)
-                                               -> Result<R, usize>
+                                               -> Result<R, CompileIncomplete>
     where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
                             ty::CrateAnalysis,
                             IncrementalHashesMap,
@@ -920,6 +923,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // What we need to do constant evaluation.
     passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial"));
     passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir);
+    passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck);
 
     // What we need to run borrowck etc.
     passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
@@ -934,7 +938,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // From here on out, regions are gone.
     passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AddCallGuards);
-    passes.push_pass(MIR_OPTIMIZED, borrowck::ElaborateDrops);
+    passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
     passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
 
@@ -1018,7 +1022,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
         // lint warnings and so on -- kindck used to do this abort, but
         // kindck is gone now). -nmatsakis
         if sess.err_count() > 0 {
-            return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count())));
+            return Ok(f(tcx, analysis, incremental_hashes_map, sess.compile_status()));
         }
 
         analysis.reachable =
@@ -1034,12 +1038,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
         time(time_passes, "lint checking", || lint::check_crate(tcx));
 
-        // The above three passes generate errors w/o aborting
-        if sess.err_count() > 0 {
-            return Ok(f(tcx, analysis, incremental_hashes_map, Err(sess.err_count())));
-        }
-
-        Ok(f(tcx, analysis, incremental_hashes_map, Ok(())))
+        return Ok(f(tcx, analysis, incremental_hashes_map, tcx.sess.compile_status()));
     })
 }
 
@@ -1115,11 +1114,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
          "serialize work products",
          move || rustc_incremental::save_work_products(sess));
 
-    if sess.err_count() > 0 {
-        Err(sess.err_count())
-    } else {
-        Ok(())
-    }
+    sess.compile_status()
 }
 
 /// Run the linker on any artifacts that resulted from the LLVM run.
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 54e7c398fe6..802ed2a489b 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -67,6 +67,7 @@ use rustc_trans::back::link;
 use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
 use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config, Session, build_session, CompileResult};
+use rustc::session::CompileIncomplete;
 use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
 use rustc::session::config::nightly_options;
 use rustc::session::{early_error, early_warn};
@@ -74,7 +75,7 @@ use rustc::lint::Lint;
 use rustc::lint;
 use rustc_metadata::locator;
 use rustc_metadata::cstore::CStore;
-use rustc::util::common::time;
+use rustc::util::common::{time, ErrorReported};
 
 use serialize::json::ToJson;
 
@@ -83,10 +84,11 @@ use std::cmp::max;
 use std::cmp::Ordering::Equal;
 use std::default::Default;
 use std::env;
+use std::ffi::OsString;
 use std::io::{self, Read, Write};
 use std::iter::repeat;
 use std::path::PathBuf;
-use std::process;
+use std::process::{self, Command, Stdio};
 use std::rc::Rc;
 use std::str;
 use std::sync::{Arc, Mutex};
@@ -109,18 +111,14 @@ mod derive_registrar;
 const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
                                       md#bug-reports";
 
-#[inline]
-fn abort_msg(err_count: usize) -> String {
-    match err_count {
-        0 => "aborting with no errors (maybe a bug?)".to_owned(),
-        _ => "aborting due to previous error(s)".to_owned(),
-    }
-}
-
-pub fn abort_on_err<T>(result: Result<T, usize>, sess: &Session) -> T {
+pub fn abort_on_err<T>(result: Result<T, CompileIncomplete>, sess: &Session) -> T {
     match result {
-        Err(err_count) => {
-            sess.fatal(&abort_msg(err_count));
+        Err(CompileIncomplete::Errored(ErrorReported)) => {
+            sess.abort_if_errors();
+            panic!("error reported but abort_if_errors didn't abort???");
+        }
+        Err(CompileIncomplete::Stopped) => {
+            sess.fatal("compilation terminated");
         }
         Ok(x) => x,
     }
@@ -131,19 +129,20 @@ pub fn run<F>(run_compiler: F) -> isize
 {
     monitor(move || {
         let (result, session) = run_compiler();
-        if let Err(err_count) = result {
-            if err_count > 0 {
-                match session {
-                    Some(sess) => sess.fatal(&abort_msg(err_count)),
-                    None => {
-                        let emitter =
-                            errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None);
-                        let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
-                        handler.emit(&MultiSpan::new(),
-                                     &abort_msg(err_count),
-                                     errors::Level::Fatal);
-                        exit_on_err();
-                    }
+        if let Err(CompileIncomplete::Errored(_)) = result {
+            match session {
+                Some(sess) => {
+                    sess.abort_if_errors();
+                    panic!("error reported but abort_if_errors didn't abort???");
+                }
+                None => {
+                    let emitter =
+                        errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None);
+                    let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
+                    handler.emit(&MultiSpan::new(),
+                                 "aborting due to previous error(s)",
+                                 errors::Level::Fatal);
+                    exit_on_err();
                 }
             }
         }
@@ -345,6 +344,31 @@ pub trait CompilerCalls<'a> {
 #[derive(Copy, Clone)]
 pub struct RustcDefaultCalls;
 
+// FIXME remove these and use winapi 0.3 instead
+// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs
+#[cfg(unix)]
+fn stdout_isatty() -> bool {
+    unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
+}
+
+#[cfg(windows)]
+fn stdout_isatty() -> bool {
+    type DWORD = u32;
+    type BOOL = i32;
+    type HANDLE = *mut u8;
+    type LPDWORD = *mut u32;
+    const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
+    extern "system" {
+        fn GetStdHandle(which: DWORD) -> HANDLE;
+        fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
+    }
+    unsafe {
+        let handle = GetStdHandle(STD_OUTPUT_HANDLE);
+        let mut out = 0;
+        GetConsoleMode(handle, &mut out) != 0
+    }
+}
+
 fn handle_explain(code: &str,
                   descriptions: &errors::registry::Registry,
                   output: ErrorOutputType) {
@@ -356,6 +380,8 @@ fn handle_explain(code: &str,
     match descriptions.find_description(&normalised) {
         Some(ref description) => {
             let mut is_in_code_block = false;
+            let mut text = String::new();
+
             // Slice off the leading newline and print.
             for line in description[1..].lines() {
                 let indent_level = line.find(|c: char| !c.is_whitespace())
@@ -363,12 +389,19 @@ fn handle_explain(code: &str,
                 let dedented_line = &line[indent_level..];
                 if dedented_line.starts_with("```") {
                     is_in_code_block = !is_in_code_block;
-                    println!("{}", &line[..(indent_level+3)]);
+                    text.push_str(&line[..(indent_level+3)]);
                 } else if is_in_code_block && dedented_line.starts_with("# ") {
                     continue;
                 } else {
-                    println!("{}", line);
+                    text.push_str(line);
                 }
+                text.push('\n');
+            }
+
+            if stdout_isatty() {
+                show_content_with_pager(&text);
+            } else {
+                print!("{}", text);
             }
         }
         None => {
@@ -377,6 +410,39 @@ fn handle_explain(code: &str,
     }
 }
 
+fn show_content_with_pager(content: &String) {
+    let pager_name = env::var_os("PAGER").unwrap_or_else(|| if cfg!(windows) {
+        OsString::from("more.com")
+    } else {
+        OsString::from("less")
+    });
+
+    let mut fallback_to_println = false;
+
+    match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
+        Ok(mut pager) => {
+            if let Some(mut pipe) = pager.stdin.as_mut() {
+                if pipe.write_all(content.as_bytes()).is_err() {
+                    fallback_to_println = true;
+                }
+            }
+
+            if pager.wait().is_err() {
+                fallback_to_println = true;
+            }
+        }
+        Err(_) => {
+            fallback_to_println = true;
+        }
+    }
+
+    // If pager fails for whatever reason, we should still print the content
+    // to standard output
+    if fallback_to_println {
+        print!("{}", content);
+    }
+}
+
 impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
     fn early_callback(&mut self,
                       matches: &getopts::Matches,
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 2d25d12d3a9..4b71aa6b85f 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -47,7 +47,12 @@ impl Emitter for EmitterWriter {
                // don't display multiline suggestions as labels
                sugg.substitution_parts[0].substitutions[0].find('\n').is_none() {
                 let substitution = &sugg.substitution_parts[0].substitutions[0];
-                let msg = format!("help: {} `{}`", sugg.msg, substitution);
+                let msg = if substitution.len() == 0 {
+                    // This substitution is only removal, don't show it
+                    format!("help: {}", sugg.msg)
+                } else {
+                    format!("help: {} `{}`", sugg.msg, substitution)
+                };
                 primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg);
             } else {
                 // if there are multiple suggestions, print them all in full
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index ada1c632bc0..dd25f969414 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -506,7 +506,10 @@ impl Handler {
 
                 return;
             }
-            _ => s = "aborting due to previous error(s)".to_string(),
+            1 => s = "aborting due to previous error".to_string(),
+            _ => {
+                s = format!("aborting due to {} previous errors", self.err_count.get());
+            }
         }
 
         panic!(self.fatal(&s));
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index 5bd7a24bdaf..ac3149b90b8 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -20,7 +20,6 @@
 
 #![feature(rand)]
 #![feature(conservative_impl_trait)]
-#![feature(sort_unstable)]
 
 extern crate graphviz;
 #[macro_use] extern crate rustc;
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 9800012917c..2b331509025 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -684,13 +684,9 @@ fn fl_lit_check_expr(cx: &EarlyContext, expr: &ast::Expr) {
         // These may occur in patterns
         // and can maybe contain float literals
         ExprKind::Unary(_, ref f) => fl_lit_check_expr(cx, f),
-        // These may occur in patterns
-        // and can't contain float literals
-        ExprKind::Path(..) => (),
-        // If something unhandled is encountered, we need to expand the
-        // search or ignore more ExprKinds.
-        _ => span_bug!(expr.span, "Unhandled expression {:?} in float lit pattern lint",
-                       expr.node),
+        // Other kinds of exprs can't occur in patterns so we don't have to check them
+        // (ast_validation will emit an error if they occur)
+        _ => (),
     }
 }
 
@@ -1154,24 +1150,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
-                let typ = cx.tables.node_id_to_type(expr.id);
-                match typ.sty {
-                    ty::TyFnDef(.., bare_fn) if bare_fn.abi() == RustIntrinsic => {
-                        let from = bare_fn.inputs().skip_binder()[0];
-                        let to = *bare_fn.output().skip_binder();
-                        return Some((&from.sty, &to.sty));
-                    }
-                    _ => (),
-                }
+                let sig = cx.tables.node_id_to_type(expr.id).fn_sig(cx.tcx);
+                let from = sig.inputs().skip_binder()[0];
+                let to = *sig.output().skip_binder();
+                return Some((&from.sty, &to.sty));
             }
             None
         }
 
         fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool {
-            match cx.tcx.type_of(def_id).sty {
-                ty::TyFnDef(.., bfty) if bfty.abi() == RustIntrinsic => (),
-                _ => return false,
-            }
+            cx.tcx.fn_sig(def_id).abi() == RustIntrinsic &&
             cx.tcx.item_name(def_id) == "transmute"
         }
     }
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 32bde42b526..ac3977bd216 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -659,7 +659,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
     fn check_foreign_fn(&mut self, id: ast::NodeId, decl: &hir::FnDecl) {
         let def_id = self.cx.tcx.hir.local_def_id(id);
-        let sig = self.cx.tcx.type_of(def_id).fn_sig();
+        let sig = self.cx.tcx.fn_sig(def_id);
         let sig = self.cx.tcx.erase_late_bound_regions(&sig);
 
         for (input_ty, input_hir) in sig.inputs().iter().zip(&decl.inputs) {
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 01b37a55f4f..3f0f5369607 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -60,11 +60,7 @@ fn main() {
         });
 
     println!("cargo:rerun-if-changed={}", llvm_config.display());
-
-    if let Some(cfg_toml) = env::var_os("CFG_LLVM_TOML") {
-        let cfg_path = PathBuf::from(cfg_toml);
-        println!("cargo:rerun-if-changed={}", cfg_path.display());
-    }
+    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
 
     // Test whether we're cross-compiling LLVM. This is a pretty rare case
     // currently where we're producing an LLVM for a different platform than
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index 312b5a38d6e..770d16e5c02 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -1597,7 +1597,13 @@ extern "C" {
                                    Output: *const c_char,
                                    FileType: FileType)
                                    -> LLVMRustResult;
-    pub fn LLVMRustPrintModule(PM: PassManagerRef, M: ModuleRef, Output: *const c_char);
+    pub fn LLVMRustPrintModule(PM: PassManagerRef,
+                               M: ModuleRef,
+                               Output: *const c_char,
+                               Demangle: extern fn(*const c_char,
+                                                   size_t,
+                                                   *mut c_char,
+                                                   size_t) -> size_t);
     pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
     pub fn LLVMRustPrintPasses();
     pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char);
diff --git a/src/librustc_lsan/build.rs b/src/librustc_lsan/build.rs
index da53571a243..3d2ae480de6 100644
--- a/src/librustc_lsan/build.rs
+++ b/src/librustc_lsan/build.rs
@@ -32,4 +32,5 @@ fn main() {
             .build_target("lsan")
             .build();
     }
+    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
 }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index ff5febadeb7..54138e2e3b0 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -107,7 +107,7 @@ provide! { <'tcx> tcx, def_id, cdata,
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
     typeck_tables_of => { cdata.item_body_tables(def_id.index, tcx) }
     closure_kind => { cdata.closure_kind(def_id.index) }
-    closure_type => { cdata.closure_ty(def_id.index, tcx) }
+    fn_sig => { cdata.fn_sig(def_id.index, tcx) }
     inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
     is_const_fn => { cdata.is_const_fn(def_id.index) }
     is_foreign_item => { cdata.is_foreign_item(def_id.index) }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index b974541ef25..ad3a9dd9fef 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -1084,14 +1084,20 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn closure_ty(&self,
-                      closure_id: DefIndex,
-                      tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                      -> ty::PolyFnSig<'tcx> {
-        match self.entry(closure_id).kind {
-            EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)),
+    pub fn fn_sig(&self,
+                  id: DefIndex,
+                  tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                  -> ty::PolyFnSig<'tcx> {
+        let sig = match self.entry(id).kind {
+            EntryKind::Fn(data) |
+            EntryKind::ForeignFn(data) => data.decode(self).sig,
+            EntryKind::Method(data) => data.decode(self).fn_data.sig,
+            EntryKind::Variant(data) |
+            EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(),
+            EntryKind::Closure(data) => data.decode(self).sig,
             _ => bug!(),
-        }
+        };
+        sig.decode((self, tcx))
     }
 
     #[inline]
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 63a24c7db18..f74aac255a0 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -16,6 +16,7 @@ use schema::*;
 use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
                             EncodedMetadata, EncodedMetadataHashes,
                             EncodedMetadataHash};
+use rustc::hir::def::CtorKind;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
 use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
 use rustc::ich::Fingerprint;
@@ -499,6 +500,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             struct_ctor: None,
+            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+                Some(self.lazy(&tcx.fn_sig(def_id)))
+            } else {
+                None
+            }
         };
 
         let enum_id = tcx.hir.as_local_node_id(enum_did).unwrap();
@@ -518,7 +524,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if variant.ctor_kind == CtorKind::Fn {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -617,6 +627,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
             ctor_kind: variant.ctor_kind,
             discr: variant.discr,
             struct_ctor: Some(def_id.index),
+            ctor_sig: if variant.ctor_kind == CtorKind::Fn {
+                Some(self.lazy(&tcx.fn_sig(def_id)))
+            } else {
+                None
+            }
         };
 
         let struct_id = tcx.hir.as_local_node_id(adt_def_id).unwrap();
@@ -641,7 +656,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if variant.ctor_kind == CtorKind::Fn {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -695,7 +714,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     };
                     FnData {
                         constness: hir::Constness::NotConst,
-                        arg_names: arg_names
+                        arg_names: arg_names,
+                        sig: self.lazy(&tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
@@ -732,7 +752,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 }
             },
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if trait_item.kind == ty::AssociatedKind::Method {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -747,6 +771,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
         debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
+        let tcx = self.tcx;
+
         let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
         let ast_item = self.tcx.hir.expect_impl_item(node_id);
         let impl_item = self.tcx.associated_item(def_id);
@@ -768,6 +794,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     FnData {
                         constness: sig.constness,
                         arg_names: self.encode_fn_arg_names_for_body(body),
+                        sig: self.lazy(&tcx.fn_sig(def_id)),
                     }
                 } else {
                     bug!()
@@ -806,7 +833,11 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: if impl_item.kind == ty::AssociatedKind::Method {
+                self.encode_variances_of(def_id)
+            } else {
+                LazySeq::empty()
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
@@ -881,6 +912,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 let data = FnData {
                     constness: constness,
                     arg_names: self.encode_fn_arg_names_for_body(body),
+                    sig: self.lazy(&tcx.fn_sig(def_id)),
                 };
 
                 EntryKind::Fn(self.lazy(&data))
@@ -910,6 +942,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     struct_ctor: struct_ctor,
+                    ctor_sig: None,
                 }), repr_options)
             }
             hir::ItemUnion(..) => {
@@ -920,6 +953,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     ctor_kind: variant.ctor_kind,
                     discr: variant.discr,
                     struct_ctor: None,
+                    ctor_sig: None,
                 }), repr_options)
             }
             hir::ItemDefaultImpl(..) => {
@@ -1037,7 +1071,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 hir::ItemEnum(..) |
                 hir::ItemStruct(..) |
                 hir::ItemUnion(..) |
-                hir::ItemTrait(..) => self.encode_variances_of(def_id),
+                hir::ItemFn(..) => self.encode_variances_of(def_id),
                 _ => LazySeq::empty(),
             },
             generics: match item.node {
@@ -1176,7 +1210,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
         let data = ClosureData {
             kind: tcx.closure_kind(def_id),
-            ty: self.lazy(&tcx.closure_type(def_id)),
+            sig: self.lazy(&tcx.fn_sig(def_id)),
         };
 
         Entry {
@@ -1364,6 +1398,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 let data = FnData {
                     constness: hir::Constness::NotConst,
                     arg_names: self.encode_fn_arg_names(names),
+                    sig: self.lazy(&tcx.fn_sig(def_id)),
                 };
                 EntryKind::ForeignFn(self.lazy(&data))
             }
@@ -1382,7 +1417,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
             ty: Some(self.encode_item_type(def_id)),
             inherent_impls: LazySeq::empty(),
-            variances: LazySeq::empty(),
+            variances: match nitem.node {
+                hir::ForeignItemFn(..) => self.encode_variances_of(def_id),
+                _ => LazySeq::empty(),
+            },
             generics: Some(self.encode_generics(def_id)),
             predicates: Some(self.encode_predicates(def_id)),
 
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 12997f24c74..99b718ea07b 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -26,7 +26,6 @@
 #![feature(specialization)]
 #![feature(discriminant_value)]
 #![feature(rustc_private)]
-#![feature(sort_unstable)]
 
 #[macro_use]
 extern crate log;
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 1337f90efa7..9ef5b940830 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -343,18 +343,18 @@ pub enum EntryKind<'tcx> {
     Type,
     Enum(ReprOptions),
     Field,
-    Variant(Lazy<VariantData>),
-    Struct(Lazy<VariantData>, ReprOptions),
-    Union(Lazy<VariantData>, ReprOptions),
-    Fn(Lazy<FnData>),
-    ForeignFn(Lazy<FnData>),
+    Variant(Lazy<VariantData<'tcx>>),
+    Struct(Lazy<VariantData<'tcx>>, ReprOptions),
+    Union(Lazy<VariantData<'tcx>>, ReprOptions),
+    Fn(Lazy<FnData<'tcx>>),
+    ForeignFn(Lazy<FnData<'tcx>>),
     Mod(Lazy<ModData>),
     MacroDef(Lazy<MacroDef>),
     Closure(Lazy<ClosureData<'tcx>>),
     Trait(Lazy<TraitData<'tcx>>),
     Impl(Lazy<ImplData<'tcx>>),
     DefaultImpl(Lazy<ImplData<'tcx>>),
-    Method(Lazy<MethodData>),
+    Method(Lazy<MethodData<'tcx>>),
     AssociatedType(AssociatedContainer),
     AssociatedConst(AssociatedContainer, u8),
 }
@@ -439,27 +439,33 @@ pub struct MacroDef {
 impl_stable_hash_for!(struct MacroDef { body, legacy });
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct FnData {
+pub struct FnData<'tcx> {
     pub constness: hir::Constness,
     pub arg_names: LazySeq<ast::Name>,
+    pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
 
-impl_stable_hash_for!(struct FnData { constness, arg_names });
+impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct VariantData {
+pub struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
     pub discr: ty::VariantDiscr,
 
     /// If this is a struct's only variant, this
     /// is the index of the "struct ctor" item.
     pub struct_ctor: Option<DefIndex>,
+
+    /// If this is a tuple struct or variant
+    /// ctor, this is its "function" signature.
+    pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct VariantData {
+impl_stable_hash_for!(struct VariantData<'tcx> {
     ctor_kind,
     discr,
-    struct_ctor
+    struct_ctor,
+    ctor_sig
 });
 
 #[derive(RustcEncodable, RustcDecodable)]
@@ -543,16 +549,16 @@ impl AssociatedContainer {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct MethodData {
-    pub fn_data: FnData,
+pub struct MethodData<'tcx> {
+    pub fn_data: FnData<'tcx>,
     pub container: AssociatedContainer,
     pub has_self: bool,
 }
-impl_stable_hash_for!(struct MethodData { fn_data, container, has_self });
+impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ClosureData<'tcx> {
     pub kind: ty::ClosureKind,
-    pub ty: Lazy<ty::PolyFnSig<'tcx>>,
+    pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
-impl_stable_hash_for!(struct ClosureData<'tcx> { kind, ty });
+impl_stable_hash_for!(struct ClosureData<'tcx> { kind, sig });
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index b7abc707a38..326c1df69eb 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -205,11 +205,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // FIXME(canndrew): This is_never should probably be an is_uninhabited
                 let diverges = expr.ty.is_never();
                 let intrinsic = match ty.sty {
-                    ty::TyFnDef(def_id, _, ref f) if
-                        f.abi() == Abi::RustIntrinsic ||
-                        f.abi() == Abi::PlatformIntrinsic =>
-                    {
-                        Some(this.hir.tcx().item_name(def_id).as_str())
+                    ty::TyFnDef(def_id, _)  => {
+                        let f = ty.fn_sig(this.hir.tcx());
+                        if f.abi() == Abi::RustIntrinsic ||
+                           f.abi() == Abi::PlatformIntrinsic {
+                            Some(this.hir.tcx().item_name(def_id).as_str())
+                        } else {
+                            None
+                        }
                     }
                     _ => None
                 };
diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs
index e3b99b9d4bd..daafbecc5df 100644
--- a/src/librustc_borrowck/borrowck/mir/mod.rs
+++ b/src/librustc_mir/dataflow/drop_flag_effects.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,33 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrowck::BorrowckCtxt;
-
 use syntax::ast::{self, MetaItem};
 use syntax_pos::DUMMY_SP;
 
-use rustc::mir::{self, BasicBlock, BasicBlockData, Mir, Statement, Terminator, Location};
+
+use rustc::mir::{self, Mir, BasicBlock, Location};
 use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
-use rustc_mir::util::elaborate_drops::DropFlagState;
-use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
-
-mod abs_domain;
-pub mod elaborate_drops;
-mod dataflow;
-mod gather_moves;
-// mod graphviz;
-
-use self::dataflow::{BitDenotation};
-use self::dataflow::{DataflowOperator};
-use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults};
-use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
-use self::dataflow::{DefinitelyInitializedLvals};
-use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+use util::elaborate_drops::DropFlagState;
+use rustc_data_structures::indexed_set::{IdxSet};
 
 use std::fmt;
 
-fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
+use super::{Dataflow, DataflowBuilder, DataflowAnalysis};
+use super::{BitDenotation, DataflowOperator, DataflowResults};
+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();
@@ -50,69 +41,11 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem>
 }
 
 pub struct MoveDataParamEnv<'tcx> {
-    move_data: MoveData<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    pub(crate) move_data: MoveData<'tcx>,
+    pub(crate) param_env: ty::ParamEnv<'tcx>,
 }
 
-pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
-                    id: ast::NodeId,
-                    attributes: &[ast::Attribute]) {
-    let tcx = bcx.tcx;
-    let def_id = tcx.hir.local_def_id(id);
-    debug!("borrowck_mir({:?}) UNIMPLEMENTED", def_id);
-
-    // It is safe for us to borrow `mir_validated()`: `optimized_mir`
-    // steals it, but it forces the `borrowck` query.
-    let mir = &tcx.mir_validated(def_id).borrow();
-
-    let param_env = tcx.param_env(def_id);
-    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_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 flow_def_inits =
-        do_dataflow(tcx, mir, id, attributes, &dead_unwinds,
-                    DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
-                    |bd, i| &bd.move_data().move_paths[i]);
-
-    if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_inits);
-    }
-    if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_uninits);
-    }
-    if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits);
-    }
-
-    if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() {
-        bcx.tcx.sess.fatal("stop_after_dataflow ended compilation");
-    }
-
-    let mut mbcx = MirBorrowckCtxt {
-        bcx: bcx,
-        mir: mir,
-        node_id: id,
-        move_data: &mdpe.move_data,
-        flow_inits: flow_inits,
-        flow_uninits: flow_uninits,
-    };
-
-    for bb in mir.basic_blocks().indices() {
-        mbcx.process_basic_block(bb);
-    }
-
-    debug!("borrowck_mir done");
-}
-
-fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, '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],
@@ -142,7 +75,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let print_postflow_to =
         name_found(tcx.sess, attributes, "borrowck_graphviz_postflow");
 
-    let mut mbcx = MirBorrowckCtxtPreDataflow {
+    let mut mbcx = DataflowBuilder {
         node_id: node_id,
         print_preflow_to: print_preflow_to,
         print_postflow_to: print_postflow_to,
@@ -153,46 +86,7 @@ fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mbcx.flow_state.results()
 }
 
-
-pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation
-{
-    node_id: ast::NodeId,
-    flow_state: DataflowAnalysis<'a, 'tcx, BD>,
-    print_preflow_to: Option<String>,
-    print_postflow_to: Option<String>,
-}
-
-#[allow(dead_code)]
-pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> {
-    bcx: &'b mut BorrowckCtxt<'a, 'tcx>,
-    mir: &'b Mir<'tcx>,
-    node_id: ast::NodeId,
-    move_data: &'b MoveData<'tcx>,
-    flow_inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
-    flow_uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>
-}
-
-impl<'b, 'a: 'b, 'tcx: 'a> MirBorrowckCtxt<'b, 'a, 'tcx> {
-    fn process_basic_block(&mut self, bb: BasicBlock) {
-        let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } =
-            self.mir[bb];
-        for stmt in statements {
-            self.process_statement(bb, stmt);
-        }
-
-        self.process_terminator(bb, terminator);
-    }
-
-    fn process_statement(&mut self, bb: BasicBlock, stmt: &Statement<'tcx>) {
-        debug!("MirBorrowckCtxt::process_statement({:?}, {:?}", bb, stmt);
-    }
-
-    fn process_terminator(&mut self, bb: BasicBlock, term: &Option<Terminator<'tcx>>) {
-        debug!("MirBorrowckCtxt::process_terminator({:?}, {:?})", bb, term);
-    }
-}
-
-fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
+pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>,
                                         path: MovePathIndex,
                                         mut cond: F)
                                         -> Option<MovePathIndex>
@@ -253,7 +147,7 @@ fn lvalue_contents_drop_state_cannot_differ<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx
     }
 }
 
-fn on_lookup_result_bits<'a, 'tcx, F>(
+pub(crate) fn on_lookup_result_bits<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     move_data: &MoveData<'tcx>,
@@ -271,7 +165,7 @@ fn on_lookup_result_bits<'a, 'tcx, F>(
     }
 }
 
-fn on_all_children_bits<'a, 'tcx, F>(
+pub(crate) fn on_all_children_bits<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     move_data: &MoveData<'tcx>,
@@ -312,7 +206,7 @@ fn on_all_children_bits<'a, 'tcx, F>(
     on_all_children_bits(tcx, mir, move_data, move_path_index, &mut each_child);
 }
 
-fn on_all_drop_children_bits<'a, 'tcx, F>(
+pub(crate) fn on_all_drop_children_bits<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
@@ -333,7 +227,7 @@ fn on_all_drop_children_bits<'a, 'tcx, F>(
     })
 }
 
-fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
+pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
@@ -350,7 +244,7 @@ fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
     }
 }
 
-fn drop_flag_effects_for_location<'a, 'tcx, F>(
+pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &Mir<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index 7f95f07f48d..e6d77aa2686 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -15,7 +15,6 @@ 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 rustc_mir::util as mir_util;
 
 use dot;
 use dot::IntoCow;
@@ -28,8 +27,10 @@ use std::marker::PhantomData;
 use std::mem;
 use std::path::Path;
 
-use super::super::MirBorrowckCtxtPreDataflow;
+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)
@@ -86,7 +87,7 @@ pub trait MirWithFlowState<'tcx> {
     fn flow_state(&self) -> &DataflowState<Self::BD>;
 }
 
-impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
+impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
     where 'tcx: 'a, BD: BitDenotation
 {
     type BD = BD;
@@ -103,8 +104,8 @@ struct Graph<'a, 'tcx, MWF:'a, P> where
     render_idx: P,
 }
 
-pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
-    mbcx: &MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>,
+pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
+    mbcx: &DataflowBuilder<'a, 'tcx, BD>,
     path: &Path,
     render_idx: P)
     -> io::Result<()>
@@ -220,7 +221,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
             }
             Ok(())
         }
-        mir_util::write_graphviz_node_label(
+        util::write_graphviz_node_label(
             *n, self.mbcx.mir(), &mut v, 4,
             |w| {
                 let flow = self.mbcx.flow_state();
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_mir/dataflow/impls/mod.rs
index 1a1ac7f9c74..97c996dea68 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
+++ b/src/librustc_mir/dataflow/impls/mod.rs
@@ -8,25 +8,26 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Dataflow analyses are built upon some interpretation of the
+//! bitvectors attached to each basic block, represented via a
+//! zero-sized structure.
+
 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 rustc_mir::util::elaborate_drops::DropFlagState;
 
-use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
-use super::super::MoveDataParamEnv;
-use super::super::drop_flag_effects_for_function_entry;
-use super::super::drop_flag_effects_for_location;
-use super::super::on_lookup_result_bits;
+use super::MoveDataParamEnv;
+use util::elaborate_drops::DropFlagState;
 
+use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
 use super::{BitDenotation, BlockSets, DataflowOperator};
 
-// Dataflow analyses are built upon some interpretation of the
-// bitvectors attached to each basic block, represented via a
-// zero-sized structure.
+use super::drop_flag_effects_for_function_entry;
+use super::drop_flag_effects_for_location;
+use super::on_lookup_result_bits;
 
 /// `MaybeInitializedLvals` tracks all l-values that might be
 /// initialized upon reaching a particular point in the control flow
@@ -219,6 +220,16 @@ pub struct MovingOutStatements<'a, 'tcx: 'a> {
     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 }
 }
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index f0f082a2561..d7ad9f9c09a 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -8,11 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use syntax::ast;
+
 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::ty::{TyCtxt};
 use rustc::mir::{self, Mir};
 
 use std::fmt::Debug;
@@ -21,21 +23,31 @@ use std::mem;
 use std::path::PathBuf;
 use std::usize;
 
-use super::MirBorrowckCtxtPreDataflow;
-
-pub use self::sanity_check::sanity_check_via_rustc_peek;
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
 pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements};
 
+pub(crate) use self::drop_flag_effects::*;
+
+mod drop_flag_effects;
 mod graphviz;
-mod sanity_check;
 mod impls;
+pub mod move_paths;
+
+pub(crate) use self::move_paths::indexes;
+
+pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
+{
+    node_id: ast::NodeId,
+    flow_state: DataflowAnalysis<'a, 'tcx, BD>,
+    print_preflow_to: Option<String>,
+    print_postflow_to: Option<String>,
+}
 
 pub trait Dataflow<BD: BitDenotation> {
     fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug;
 }
 
-impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
+impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD>
     where BD: BitDenotation + DataflowOperator
 {
     fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
@@ -135,7 +147,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
     path
 }
 
-impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
+impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD>
     where BD: BitDenotation
 {
     fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
@@ -195,7 +207,7 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
     pub fn mir(&self) -> &'a Mir<'tcx> { self.mir }
 }
 
-pub struct DataflowResults<O>(DataflowState<O>) where O: BitDenotation;
+pub struct DataflowResults<O>(pub(crate) DataflowState<O>) where O: BitDenotation;
 
 impl<O: BitDenotation> DataflowResults<O> {
     pub fn sets(&self) -> &AllSets<O::Idx> {
@@ -213,7 +225,7 @@ pub struct DataflowState<O: BitDenotation>
     pub sets: AllSets<O::Idx>,
 
     /// operator used to initialize, combine, and interpret bits.
-    operator: O,
+    pub(crate) operator: O,
 }
 
 #[derive(Debug)]
@@ -240,9 +252,9 @@ pub struct AllSets<E: Idx> {
 }
 
 pub struct BlockSets<'a, E: Idx> {
-    on_entry: &'a mut IdxSet<E>,
-    gen_set: &'a mut IdxSet<E>,
-    kill_set: &'a mut IdxSet<E>,
+    pub(crate) on_entry: &'a mut IdxSet<E>,
+    pub(crate) gen_set: &'a mut IdxSet<E>,
+    pub(crate) kill_set: &'a mut IdxSet<E>,
 }
 
 impl<'a, E:Idx> BlockSets<'a, E> {
diff --git a/src/librustc_borrowck/borrowck/mir/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
index 5e61c2ec7a2..5e61c2ec7a2 100644
--- a/src/librustc_borrowck/borrowck/mir/abs_domain.rs
+++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index a0ecdcc8e2f..d7ed0938e88 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -21,14 +21,16 @@ use std::fmt;
 use std::mem;
 use std::ops::{Index, IndexMut};
 
-use super::abs_domain::{AbstractElem, Lift};
+use self::abs_domain::{AbstractElem, Lift};
+
+mod abs_domain;
 
 // This submodule holds some newtype'd Index wrappers that are using
 // NonZero to ensure that Option<Index> occupies only a single word.
 // They are in a submodule to impose privacy restrictions; namely, to
 // ensure that other code does not accidentally access `index.0`
 // (which is likely to yield a subtle off-by-one error).
-mod indexes {
+pub(crate) mod indexes {
     use std::fmt;
     use core::nonzero::NonZero;
     use rustc_data_structures::indexed_vec::Idx;
@@ -65,7 +67,7 @@ mod indexes {
 pub use self::indexes::MovePathIndex;
 pub use self::indexes::MoveOutIndex;
 
-impl self::indexes::MoveOutIndex {
+impl MoveOutIndex {
     pub fn move_path_index(&self, move_data: &MoveData) -> MovePathIndex {
         move_data.moves[*self].path
     }
@@ -128,7 +130,7 @@ pub trait HasMoveData<'tcx> {
 pub struct LocationMap<T> {
     /// Location-indexed (BasicBlock for outer index, index within BB
     /// for inner index) map.
-    map: IndexVec<BasicBlock, Vec<T>>,
+    pub(crate) map: IndexVec<BasicBlock, Vec<T>>,
 }
 
 impl<T> Index<Location> for LocationMap<T> {
@@ -188,7 +190,7 @@ pub struct MovePathLookup<'tcx> {
     projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex>
 }
 
-struct MoveDataBuilder<'a, 'tcx: 'a> {
+pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 474feefabbb..0010f312ef9 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -19,7 +19,6 @@ use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, AdtKind, VariantDef, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
 use rustc::ty::cast::CastKind as TyCastKind;
-use rustc::ty::subst::Subst;
 use rustc::hir;
 
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
@@ -586,7 +585,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     });
     Expr {
         temp_lifetime: temp_lifetime,
-        ty: cx.tcx.type_of(def_id).subst(cx.tcx, substs),
+        ty: cx.tcx().mk_fn_def(def_id, substs),
         span: expr.span,
         kind: ExprKind::Literal {
             literal: Literal::Value {
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index bfa31c052e4..71855d3805e 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -26,6 +26,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(rustc_diagnostic_macros)]
 #![feature(placement_in_syntax)]
 #![feature(collection_placement)]
+#![feature(nonzero)]
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
@@ -40,10 +41,12 @@ extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_const_math;
 extern crate rustc_const_eval;
+extern crate core; // for NonZero
 
 pub mod diagnostics;
 
 mod build;
+pub mod dataflow;
 mod hair;
 mod shim;
 pub mod transform;
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 54779cbe301..11ad5d1509d 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -58,7 +58,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             // types in the MIR. They will be substituted again with
             // the param-substs, but because they are concrete, this
             // will not do any harm.
-            let sig = tcx.erase_late_bound_regions(&ty.fn_sig());
+            let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
             let arg_tys = sig.inputs();
 
             build_call_shim(
@@ -153,8 +153,8 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
     } else {
         Substs::identity_for_item(tcx, def_id)
     };
-    let fn_ty = tcx.type_of(def_id).subst(tcx, substs);
-    let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+    let sig = tcx.fn_sig(def_id).subst(tcx, substs);
+    let sig = tcx.erase_late_bound_regions(&sig);
     let span = tcx.def_span(def_id);
 
     let source_info = SourceInfo { span, scope: ARGUMENT_VISIBILITY_SCOPE };
@@ -276,8 +276,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             call_kind={:?}, untuple_args={:?})",
            def_id, rcvr_adjustment, call_kind, untuple_args);
 
-    let fn_ty = tcx.type_of(def_id);
-    let sig = tcx.erase_late_bound_regions(&fn_ty.fn_sig());
+    let sig = tcx.fn_sig(def_id);
+    let sig = tcx.erase_late_bound_regions(&sig);
     let span = tcx.def_span(def_id);
 
     debug!("build_call_shim: sig={:?}", sig);
@@ -409,11 +409,8 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
 {
     let tcx = infcx.tcx;
     let def_id = tcx.hir.local_def_id(ctor_id);
-    let sig = match tcx.type_of(def_id).sty {
-        ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty)
-            .expect("LBR in ADT constructor signature"),
-        _ => bug!("unexpected type for ctor {:?}", def_id)
-    };
+    let sig = tcx.no_late_bound_regions(&tcx.fn_sig(def_id))
+        .expect("LBR in ADT constructor signature");
     let sig = tcx.erase_regions(&sig);
 
     let (adt_def, substs) = match sig.output().sty {
diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 83369772608..b158cb43ce7 100644
--- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
-use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
-use super::dataflow::{DataflowResults};
-use super::{on_all_children_bits, on_all_drop_children_bits};
-use super::{drop_flag_effects_for_location, on_lookup_result_bits};
-use super::MoveDataParamEnv;
+use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
+use dataflow::{DataflowResults};
+use dataflow::{on_all_children_bits, on_all_drop_children_bits};
+use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits};
+use dataflow::MoveDataParamEnv;
+use dataflow;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
 use rustc::mir::transform::{MirPass, MirSource};
@@ -21,9 +22,9 @@ use rustc::middle::const_val::ConstVal;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_mir::util::patch::MirPatch;
-use rustc_mir::util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
-use rustc_mir::util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
+use util::patch::MirPatch;
+use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
+use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
 use syntax::ast;
 use syntax_pos::Span;
 
@@ -54,13 +55,13 @@ impl MirPass for ElaborateDrops {
             };
             let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
             let flow_inits =
-                super::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
-                                   MaybeInitializedLvals::new(tcx, mir, &env),
-                                   |bd, p| &bd.move_data().move_paths[p]);
+                dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                                      MaybeInitializedLvals::new(tcx, mir, &env),
+                                      |bd, p| &bd.move_data().move_paths[p]);
             let flow_uninits =
-                super::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
-                                   MaybeUninitializedLvals::new(tcx, mir, &env),
-                                   |bd, p| &bd.move_data().move_paths[p]);
+                dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                                      MaybeUninitializedLvals::new(tcx, mir, &env),
+                                      |bd, p| &bd.move_data().move_paths[p]);
 
             ElaborateDropsCtxt {
                 tcx: tcx,
@@ -91,7 +92,7 @@ fn find_dead_unwinds<'a, 'tcx>(
     // reach cleanup blocks, which can't have unwind edges themselves.
     let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
     let flow_inits =
-        super::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+        dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
                            MaybeInitializedLvals::new(tcx, mir, &env),
                            |bd, p| &bd.move_data().move_paths[p]);
     for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
@@ -242,7 +243,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path> {
-        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
             match p {
                 &Projection {
                     elem: ProjectionElem::Field(idx, _), ..
@@ -253,7 +254,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
-        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
             match p {
                 &Projection { elem: ProjectionElem::Deref, .. } => true,
                 _ => false
@@ -262,7 +263,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path> {
-        super::move_path_children_matching(self.ctxt.move_data(), path, |p| {
+        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
             match p {
                 &Projection {
                     elem: ProjectionElem::Downcast(_, idx), ..
@@ -560,7 +561,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
     fn drop_flags_for_args(&mut self) {
         let loc = Location { block: START_BLOCK, statement_index: 0 };
-        super::drop_flag_effects_for_function_entry(
+        dataflow::drop_flag_effects_for_function_entry(
             self.tcx, self.mir, self.env, |path, ds| {
                 self.set_drop_flag(loc, path, ds);
             }
@@ -605,7 +606,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                     }
                 }
                 let loc = Location { block: bb, statement_index: i };
-                super::drop_flag_effects_for_location(
+                dataflow::drop_flag_effects_for_location(
                     self.tcx, self.mir, self.env, loc, |path, ds| {
                         if ds == DropFlagState::Absent || allow_initializations {
                             self.set_drop_flag(loc, path, ds)
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index e809695c180..eb283df869f 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -67,12 +67,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
     }
 
     fn visit_statement(&mut self,
-                       _block: BasicBlock,
+                       block: BasicBlock,
                        statement: &mut Statement<'tcx>,
-                       _location: Location) {
+                       location: Location) {
         if let StatementKind::EndRegion(_) = statement.kind {
             statement.kind = StatementKind::Nop;
         }
+        self.super_statement(block, statement, location);
     }
 }
 
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 0ac35a5fdd4..5f80c7bee14 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -87,7 +87,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                 let terminator = bb_data.terminator();
                 if let TerminatorKind::Call {
                     func: Operand::Constant(ref f), .. } = terminator.kind {
-                    if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+                    if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
                         callsites.push_back(CallSite {
                             callee: callee_def_id,
                             substs: substs,
@@ -131,7 +131,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                     let terminator = bb_data.terminator();
                     if let TerminatorKind::Call {
                         func: Operand::Constant(ref f), .. } = terminator.kind {
-                        if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+                        if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty {
                             // Don't inline the same function multiple times.
                             if callsite.callee != callee_def_id {
                                 callsites.push_back(CallSite {
@@ -270,8 +270,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
                 }
 
                 TerminatorKind::Call {func: Operand::Constant(ref f), .. } => {
-                    if let ty::TyFnDef(.., f) = f.ty.sty {
+                    if let ty::TyFnDef(def_id, _) = f.ty.sty {
                         // Don't give intrinsics the extra penalty for calls
+                        let f = tcx.fn_sig(def_id);
                         if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
                             cost += INSTR_COST;
                         } else {
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 4594c611d59..1530ea8e0df 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -30,6 +30,8 @@ pub mod simplify;
 pub mod erase_regions;
 pub mod no_landing_pads;
 pub mod type_check;
+pub mod rustc_peek;
+pub mod elaborate_drops;
 pub mod add_call_guards;
 pub mod promote_consts;
 pub mod qualify_consts;
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 05a6cdd57ff..68b687a2e61 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -750,8 +750,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
 
             let fn_ty = func.ty(self.mir, self.tcx);
             let (is_shuffle, is_const_fn) = match fn_ty.sty {
-                ty::TyFnDef(def_id, _, f) => {
-                    (f.abi() == Abi::PlatformIntrinsic &&
+                ty::TyFnDef(def_id, _) => {
+                    (self.tcx.fn_sig(def_id).abi() == Abi::PlatformIntrinsic &&
                      self.tcx.item_name(def_id).as_str().starts_with("simd_shuffle"),
                      self.tcx.is_const_fn(def_id))
                 }
@@ -996,7 +996,7 @@ impl MirPass for QualifyAndPromoteConstants {
                                               tcx.require_lang_item(lang_items::SyncTraitLangItem),
                                               cause);
                 if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                    infcx.report_fulfillment_errors(&err);
+                    infcx.report_fulfillment_errors(&err, None);
                 }
             });
         }
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_mir/transform/rustc_peek.rs
index 2c55460fb30..5918de0c688 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -14,12 +14,67 @@ use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir};
+use rustc::mir::transform::{MirPass, MirSource};
+use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::super::gather_moves::{MovePathIndex, LookupResult};
-use super::BitDenotation;
-use super::DataflowResults;
-use super::super::gather_moves::HasMoveData;
+use dataflow::do_dataflow;
+use dataflow::MoveDataParamEnv;
+use dataflow::BitDenotation;
+use dataflow::DataflowResults;
+use dataflow::{DefinitelyInitializedLvals, MaybeInitializedLvals, MaybeUninitializedLvals};
+use dataflow::move_paths::{MovePathIndex, LookupResult};
+use dataflow::move_paths::{HasMoveData, MoveData};
+use dataflow;
+
+use dataflow::has_rustc_mir_with;
+
+pub struct SanityCheck;
+
+impl MirPass for SanityCheck {
+    fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          src: MirSource, mir: &mut Mir<'tcx>) {
+        let id = src.item_id();
+        let def_id = tcx.hir.local_def_id(id);
+        if !tcx.has_attr(def_id, "rustc_mir_borrowck") {
+            debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id));
+            return;
+        } else {
+            debug!("running rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id));
+        }
+
+        let attributes = tcx.get_attrs(def_id);
+        let param_env = tcx.param_env(def_id);
+        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_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 flow_def_inits =
+            do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
+                        DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
+                        |bd, i| &bd.move_data().move_paths[i]);
+
+        if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() {
+            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits);
+        }
+        if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() {
+            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits);
+        }
+        if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() {
+            sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits);
+        }
+        if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() {
+            tcx.sess.fatal("stop_after_dataflow ended compilation");
+        }
+    }
+}
 
 /// This function scans `mir` for all calls to the intrinsic
 /// `rustc_peek` that have the expression form `rustc_peek(&expr)`.
@@ -92,7 +147,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // of the argument at time immediate preceding Call to
     // `rustc_peek`).
 
-    let mut sets = super::BlockSets { on_entry: &mut entry,
+    let mut sets = dataflow::BlockSets { on_entry: &mut entry,
                                       gen_set: &mut gen,
                                       kill_set: &mut kill };
 
@@ -161,18 +216,13 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            terminator: &'a Option<mir::Terminator<'tcx>>)
                            -> Option<(&'a [mir::Operand<'tcx>], Span)> {
     if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator {
-        if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind
-        {
-            if let mir::Operand::Constant(ref func) = *oper
-            {
-                if let ty::TyFnDef(def_id, _, sig) = func.ty.sty
-                {
-                    let abi = sig.abi();
+        if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind {
+            if let mir::Operand::Constant(ref func) = *oper {
+                if let ty::TyFnDef(def_id, _) = func.ty.sty {
+                    let abi = tcx.fn_sig(def_id).abi();
                     let name = tcx.item_name(def_id);
-                    if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
-                        if name == "rustc_peek" {
-                            return Some((args, source_info.span));
-                        }
+                    if abi == Abi::RustIntrinsic &&  name == "rustc_peek" {
+                        return Some((args, source_info.span));
                     }
                 }
             }
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index efde39ad6a4..7e6fccf3019 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -462,7 +462,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 let func_ty = func.ty(mir, tcx);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let sig = match func_ty.sty {
-                    ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => sig,
+                    ty::TyFnDef(..) | ty::TyFnPtr(_) => func_ty.fn_sig(tcx),
                     _ => {
                         span_mirbug!(self, term, "call to non-function {:?}", func_ty);
                         return;
diff --git a/src/librustc_msan/build.rs b/src/librustc_msan/build.rs
index dcadbe86966..7e2a82dd0ab 100644
--- a/src/librustc_msan/build.rs
+++ b/src/librustc_msan/build.rs
@@ -32,4 +32,5 @@ fn main() {
             .build_target("msan")
             .build();
     }
+    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
 }
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 7c443a4ac75..6ad03186dc7 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -93,6 +93,17 @@ impl<'a> AstValidator<'a> {
             }
         }
     }
+
+    /// matches '-' lit | lit (cf. parser::Parser::parse_pat_literal_maybe_minus)
+    fn check_expr_within_pat(&self, expr: &Expr) {
+        match expr.node {
+            ExprKind::Lit(..) | ExprKind::Path(..) => {}
+            ExprKind::Unary(UnOp::Neg, ref inner)
+                if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
+            _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \
+                                                         in patterns")
+        }
+    }
 }
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
@@ -308,6 +319,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         }
         visit::walk_generics(self, g)
     }
+
+    fn visit_pat(&mut self, pat: &'a Pat) {
+        match pat.node {
+            PatKind::Lit(ref expr) => {
+                self.check_expr_within_pat(expr);
+            }
+            PatKind::Range(ref start, ref end, _) => {
+                self.check_expr_within_pat(start);
+                self.check_expr_within_pat(end);
+            }
+            _ => {}
+        }
+
+        visit::walk_pat(self, pat)
+    }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate) {
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
index 8d455adc23c..0dbb2d1d4d0 100644
--- a/src/librustc_passes/static_recursion.rs
+++ b/src/librustc_passes/static_recursion.rs
@@ -12,8 +12,9 @@
 // recursively.
 
 use rustc::hir::map as hir_map;
-use rustc::session::{CompileResult, Session};
+use rustc::session::Session;
 use rustc::hir::def::{Def, CtorKind};
+use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::{NodeMap, NodeSet};
 
 use syntax::ast;
@@ -86,7 +87,9 @@ impl<'a, 'hir: 'a> Visitor<'hir> for CheckCrateVisitor<'a, 'hir> {
     }
 }
 
-pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> CompileResult {
+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,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index fb7258d4266..9eb96fea527 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -400,7 +400,13 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
     }
 
     fn ty(&mut self) -> &mut Self {
-        self.ev.tcx.type_of(self.item_def_id).visit_with(self);
+        let ty = self.ev.tcx.type_of(self.item_def_id);
+        ty.visit_with(self);
+        if let ty::TyFnDef(def_id, _) = ty.sty {
+            if def_id == self.item_def_id {
+                self.ev.tcx.fn_sig(def_id).visit_with(self);
+            }
+        }
         self
     }
 
@@ -910,7 +916,13 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     }
 
     fn ty(&mut self) -> &mut Self {
-        self.tcx.type_of(self.item_def_id).visit_with(self);
+        let ty = self.tcx.type_of(self.item_def_id);
+        ty.visit_with(self);
+        if let ty::TyFnDef(def_id, _) = ty.sty {
+            if def_id == self.item_def_id {
+                self.tcx.fn_sig(def_id).visit_with(self);
+            }
+        }
         self
     }
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index b97c08b5bde..4b6b754dca6 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -149,14 +149,15 @@ impl<'a> Resolver<'a> {
                             resolve_error(self,
                                           view_path.span,
                                           ResolutionError::SelfImportsOnlyAllowedWithin);
-                        } else if source_name == "$crate" && full_path.segments.len() == 1 {
+                        } else if source_name == keywords::DollarCrate.name() &&
+                                  full_path.segments.len() == 1 {
                             let crate_root = self.resolve_crate_root(source.ctxt);
                             let crate_name = match crate_root.kind {
                                 ModuleKind::Def(_, name) => name,
                                 ModuleKind::Block(..) => unreachable!(),
                             };
                             source.name = crate_name;
-                            if binding.name == "$crate" {
+                            if binding.name == keywords::DollarCrate.name() {
                                 binding.name = crate_name;
                             }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 8c11aa7def8..4bfe4d25ded 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2665,7 +2665,8 @@ impl<'a> Resolver<'a> {
         };
 
         if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
-           path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" {
+           path[0].name != keywords::CrateRoot.name() &&
+           path[0].name != keywords::DollarCrate.name() {
             let unqualified_result = {
                 match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span) {
                     PathResult::NonModule(path_res) => path_res.base_def(),
@@ -2718,7 +2719,7 @@ impl<'a> Resolver<'a> {
             if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() {
                 module = Some(self.resolve_crate_root(ident.ctxt.modern()));
                 continue
-            } else if i == 0 && ns == TypeNS && ident.name == "$crate" {
+            } else if i == 0 && ns == TypeNS && ident.name == keywords::DollarCrate.name() {
                 module = Some(self.resolve_crate_root(ident.ctxt));
                 continue
             }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 60c07eda4d5..0fbc596f2e1 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -128,7 +128,7 @@ impl<'a> base::Resolver for Resolver<'a> {
         impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
             fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
                 let ident = path.segments[0].identifier;
-                if ident.name == "$crate" {
+                if ident.name == keywords::DollarCrate.name() {
                     path.segments[0].identifier.name = keywords::CrateRoot.name();
                     let module = self.0.resolve_crate_root(ident.ctxt);
                     if !module.is_local() {
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 86590bff4ff..a512cf2f02a 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -15,6 +15,7 @@ flate2 = "0.2"
 jobserver = "0.1.5"
 log = "0.3"
 owning_ref = "0.3.3"
+rustc-demangle = "0.1.4"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs
index 8e14335ceac..10b66fb1991 100644
--- a/src/librustc_trans/back/symbol_names.rs
+++ b/src/librustc_trans/back/symbol_names.rs
@@ -154,6 +154,13 @@ fn get_symbol_hash<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         assert!(!item_type.has_erasable_regions());
         hasher.visit_ty(item_type);
 
+        // If this is a function, we hash the signature as well.
+        // This is not *strictly* needed, but it may help in some
+        // situations, see the `run-make/a-b-a-linker-guard` test.
+        if let ty::TyFnDef(..) = item_type.sty {
+            item_type.fn_sig(tcx).visit_with(&mut hasher);
+        }
+
         // also include any type parameters (for generic items)
         if let Some(substs) = substs {
             assert!(!substs.has_erasable_regions());
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 7e99ea0ee19..562d7171156 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -29,15 +29,18 @@ use syntax_pos::MultiSpan;
 use context::{is_pie_binary, get_reloc_model};
 use jobserver::{Client, Acquired};
 use crossbeam::{scope, Scope};
+use rustc_demangle;
 
 use std::cmp;
 use std::ffi::CString;
 use std::fs;
 use std::io;
+use std::io::Write;
 use std::path::{Path, PathBuf};
 use std::str;
 use std::sync::mpsc::{channel, Sender};
-use libc::{c_uint, c_void};
+use std::slice;
+use libc::{c_uint, c_void, c_char, size_t};
 
 pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [
     ("pic", llvm::RelocMode::PIC),
@@ -510,8 +513,40 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
         if config.emit_ir {
             let out = output_names.temp_path(OutputType::LlvmAssembly, module_name);
             let out = path2cstr(&out);
+
+            extern "C" fn demangle_callback(input_ptr: *const c_char,
+                                            input_len: size_t,
+                                            output_ptr: *mut c_char,
+                                            output_len: size_t) -> size_t {
+                let input = unsafe {
+                    slice::from_raw_parts(input_ptr as *const u8, input_len as usize)
+                };
+
+                let input = match str::from_utf8(input) {
+                    Ok(s) => s,
+                    Err(_) => return 0,
+                };
+
+                let output = unsafe {
+                    slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize)
+                };
+                let mut cursor = io::Cursor::new(output);
+
+                let demangled = match rustc_demangle::try_demangle(input) {
+                    Ok(d) => d,
+                    Err(_) => return 0,
+                };
+
+                if let Err(_) = write!(cursor, "{:#}", demangled) {
+                    // Possible only if provided buffer is not big enough
+                    return 0;
+                }
+
+                cursor.position() as size_t
+            }
+
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
-                llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
+                llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
                 llvm::LLVMDisposePassManager(cpm);
             })
         }
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index d723cf32571..a76abcf7b49 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -195,7 +195,7 @@ use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
 use rustc::traits;
-use rustc::ty::subst::{Substs, Subst};
+use rustc::ty::subst::Substs;
 use rustc::ty::{self, TypeFoldable, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::mir::{self, Location};
@@ -304,6 +304,11 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         scx.tcx().hir.krate().visit_all_item_likes(&mut visitor);
     }
 
+    // We can only translate items that are instantiable - items all of
+    // whose predicates hold. Luckily, items that aren't instantiable
+    // can't actually be used, so we can just skip translating them.
+    roots.retain(|root| root.is_instantiable(scx.tcx()));
+
     roots
 }
 
@@ -587,7 +592,7 @@ fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
                           is_direct_call: bool,
                           output: &mut Vec<TransItem<'tcx>>)
 {
-    if let ty::TyFnDef(def_id, substs, _) = ty.sty {
+    if let ty::TyFnDef(def_id, substs) = ty.sty {
         let instance = monomorphize::resolve(scx, def_id, substs);
         visit_instance_use(scx, instance, is_direct_call, output);
     }
@@ -937,14 +942,9 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, '
                     let instance =
                         monomorphize::resolve(scx, method.def_id, callee_substs);
 
-                    let predicates = tcx.predicates_of(instance.def_id()).predicates
-                        .subst(tcx, instance.substs);
-                    if !traits::normalize_and_test_predicates(tcx, predicates) {
-                        continue;
-                    }
-
-                    if should_trans_locally(tcx, &instance) {
-                        output.push(create_fn_trans_item(instance));
+                    let trans_item = create_fn_trans_item(instance);
+                    if trans_item.is_instantiable(tcx) && should_trans_locally(tcx, &instance) {
+                        output.push(trans_item);
                     }
                 }
             }
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index a6f3fb709a0..9b0803908b1 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -495,12 +495,12 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                            -> ty::PolyFnSig<'tcx>
 {
     match ty.sty {
-        ty::TyFnDef(_, _, sig) => sig,
+        ty::TyFnDef(..) |
         // Shims currently have type TyFnPtr. Not sure this should remain.
-        ty::TyFnPtr(sig) => sig,
+        ty::TyFnPtr(_) => ty.fn_sig(ccx.tcx()),
         ty::TyClosure(def_id, substs) => {
             let tcx = ccx.tcx();
-            let sig = tcx.closure_type(def_id).subst(tcx, substs.substs);
+            let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
 
             let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
             let env_ty = match tcx.closure_kind(def_id) {
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 95ceec610ea..0cc19936011 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -488,7 +488,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     debug!("type_metadata: {:?}", t);
 
-    let sty = &t.sty;
     let ptr_metadata = |ty: Ty<'tcx>| {
         match ty.sty {
             ty::TySlice(typ) => {
@@ -518,7 +517,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
     };
 
-    let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
+    let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty {
         ty::TyNever    |
         ty::TyBool     |
         ty::TyChar     |
@@ -557,10 +556,10 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 Err(metadata) => return metadata,
             }
         }
-        ty::TyFnDef(.., sig) | ty::TyFnPtr(sig) => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
             let fn_metadata = subroutine_type_metadata(cx,
                                                        unique_type_id,
-                                                       sig,
+                                                       t.fn_sig(cx.tcx()),
                                                        usage_site_span).metadata;
             match debug_context(cx).type_map
                                    .borrow()
@@ -610,7 +609,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    usage_site_span).finalize(cx)
         }
         _ => {
-            bug!("debuginfo: unexpected type in type_metadata: {:?}", sty)
+            bug!("debuginfo: unexpected type in type_metadata: {:?}", t)
         }
     };
 
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 13ff6646e66..bfca4fec706 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -96,8 +96,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 push_type_params(cx, principal.substs, output);
             }
         },
-        ty::TyFnDef(.., sig) |
-        ty::TyFnPtr(sig) => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+            let sig = t.fn_sig(cx.tcx());
             if sig.unsafety() == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
             }
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index 367f0398fa8..c2f44c089a2 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -76,7 +76,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
     }
     assert!(!info.is_null());
     match t.sty {
-        ty::TyAdt(def, substs) => {
+        ty::TyAdt(..) | ty::TyTuple(..) => {
             let ccx = bcx.ccx;
             // First get the size of all statically known fields.
             // Don't use size_of because it also rounds up to alignment, which we
@@ -101,8 +101,14 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
 
             // Recurse to get the size of the dynamically sized field (must be
             // the last field).
-            let last_field = def.struct_variant().fields.last().unwrap();
-            let field_ty = monomorphize::field_ty(bcx.tcx(), substs, last_field);
+            let field_ty = match t.sty {
+                ty::TyAdt(def, substs) => {
+                    let last_field = def.struct_variant().fields.last().unwrap();
+                    monomorphize::field_ty(bcx.tcx(), substs, last_field)
+                },
+                ty::TyTuple(tys, _) => tys.last().unwrap(),
+                _ => unreachable!(),
+            };
             let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
 
             // FIXME (#26403, #27023): We should be adding padding
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index de908bb24a7..9956c28e641 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -95,11 +95,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
     let ccx = bcx.ccx;
     let tcx = ccx.tcx();
 
-    let (def_id, substs, sig) = match callee_ty.sty {
-        ty::TyFnDef(def_id, substs, sig) => (def_id, substs, sig),
+    let (def_id, substs) = match callee_ty.sty {
+        ty::TyFnDef(def_id, substs) => (def_id, substs),
         _ => bug!("expected fn item type, found {}", callee_ty)
     };
 
+    let sig = callee_ty.fn_sig(tcx);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     let arg_tys = sig.inputs();
     let ret_ty = sig.output();
@@ -986,7 +987,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
 
 
     let tcx = bcx.tcx();
-    let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig());
+    let sig = tcx.erase_late_bound_regions_and_normalize(&callee_ty.fn_sig(tcx));
     let arg_tys = sig.inputs();
 
     // every intrinsic takes a SIMD vector as its first argument
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 859c6574787..6acd10cb887 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -34,7 +34,6 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
-#![feature(command_envs)]
 
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
@@ -53,6 +52,7 @@ extern crate rustc_const_math;
 #[macro_use]
 #[no_link]
 extern crate rustc_bitflags;
+extern crate rustc_demangle;
 extern crate jobserver;
 
 #[macro_use] extern crate log;
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 8863c7ffae6..48b166c61de 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -28,6 +28,7 @@ use type_of;
 use type_::Type;
 
 use syntax::symbol::Symbol;
+use syntax_pos::Pos;
 
 use std::cmp;
 
@@ -333,6 +334,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 let filename = Symbol::intern(&loc.file.name).as_str();
                 let filename = C_str_slice(bcx.ccx, filename);
                 let line = C_u32(bcx.ccx, loc.line as u32);
+                let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1);
 
                 // Put together the arguments to the panic entry point.
                 let (lang_item, args, const_err) = match *msg {
@@ -347,29 +349,29 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                                     index: index as u64
                                 }));
 
-                        let file_line = C_struct(bcx.ccx, &[filename, line], false);
-                        let align = llalign_of_min(bcx.ccx, common::val_ty(file_line));
-                        let file_line = consts::addr_of(bcx.ccx,
-                                                        file_line,
-                                                        align,
-                                                        "panic_bounds_check_loc");
+                        let file_line_col = C_struct(bcx.ccx, &[filename, line, col], false);
+                        let align = llalign_of_min(bcx.ccx, common::val_ty(file_line_col));
+                        let file_line_col = consts::addr_of(bcx.ccx,
+                                                            file_line_col,
+                                                            align,
+                                                            "panic_bounds_check_loc");
                         (lang_items::PanicBoundsCheckFnLangItem,
-                         vec![file_line, index, len],
+                         vec![file_line_col, index, len],
                          const_err)
                     }
                     mir::AssertMessage::Math(ref err) => {
                         let msg_str = Symbol::intern(err.description()).as_str();
                         let msg_str = C_str_slice(bcx.ccx, msg_str);
-                        let msg_file_line = C_struct(bcx.ccx,
-                                                     &[msg_str, filename, line],
+                        let msg_file_line_col = C_struct(bcx.ccx,
+                                                     &[msg_str, filename, line, col],
                                                      false);
-                        let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line));
-                        let msg_file_line = consts::addr_of(bcx.ccx,
-                                                            msg_file_line,
-                                                            align,
-                                                            "panic_loc");
+                        let align = llalign_of_min(bcx.ccx, common::val_ty(msg_file_line_col));
+                        let msg_file_line_col = consts::addr_of(bcx.ccx,
+                                                                msg_file_line_col,
+                                                                align,
+                                                                "panic_loc");
                         (lang_items::PanicFnLangItem,
-                         vec![msg_file_line],
+                         vec![msg_file_line_col],
                          Some(ErrKind::Math(err.clone())))
                     }
                 };
@@ -404,20 +406,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
                 let callee = self.trans_operand(&bcx, func);
 
-                let (instance, mut llfn, sig) = match callee.ty.sty {
-                    ty::TyFnDef(def_id, substs, sig) => {
+                let (instance, mut llfn) = match callee.ty.sty {
+                    ty::TyFnDef(def_id, substs) => {
                         (Some(monomorphize::resolve(bcx.ccx.shared(), def_id, substs)),
-                         None,
-                         sig)
+                         None)
                     }
-                    ty::TyFnPtr(sig) => {
-                        (None,
-                         Some(callee.immediate()),
-                         sig)
+                    ty::TyFnPtr(_) => {
+                        (None, Some(callee.immediate()))
                     }
                     _ => bug!("{} is not callable", callee.ty)
                 };
                 let def = instance.map(|i| i.def);
+                let sig = callee.ty.fn_sig(bcx.tcx());
                 let sig = bcx.tcx().erase_late_bound_regions_and_normalize(&sig);
                 let abi = sig.abi;
 
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 16ef32ccf57..fcb4b25e6fe 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -334,7 +334,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                     let fn_ty = func.ty(self.mir, tcx);
                     let fn_ty = self.monomorphize(&fn_ty);
                     let (def_id, substs) = match fn_ty.sty {
-                        ty::TyFnDef(def_id, substs, _) => (def_id, substs),
+                        ty::TyFnDef(def_id, substs) => (def_id, substs),
                         _ => span_bug!(span, "calling {:?} (of type {}) in constant",
                                        func, fn_ty)
                     };
@@ -560,7 +560,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                 let val = match *kind {
                     mir::CastKind::ReifyFnPointer => {
                         match operand.ty.sty {
-                            ty::TyFnDef(def_id, substs, _) => {
+                            ty::TyFnDef(def_id, substs) => {
                                 callee::resolve_and_get_fn(self.ccx, def_id, substs)
                             }
                             _ => {
@@ -579,7 +579,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                                     .find(|it| it.kind == ty::AssociatedKind::Method)
                                     .unwrap().def_id;
                                 // Now create its substs [Closure, Tuple]
-                                let input = tcx.closure_type(def_id)
+                                let input = tcx.fn_sig(def_id)
                                     .subst(tcx, substs.substs).input(0);
                                 let input = tcx.erase_late_bound_regions_and_normalize(&input);
                                 let substs = tcx.mk_substs([operand.ty, input]
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 61e537c9cc0..4bd5091a4f3 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -180,7 +180,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 let val = match *kind {
                     mir::CastKind::ReifyFnPointer => {
                         match operand.ty.sty {
-                            ty::TyFnDef(def_id, substs, _) => {
+                            ty::TyFnDef(def_id, substs) => {
                                 OperandValue::Immediate(
                                     callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
                             }
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index d27eeb2b646..1f6a262162d 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -40,7 +40,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     let self_ty = tcx.mk_closure_from_closure_substs(
         closure_did, substs);
 
-    let sig = tcx.closure_type(closure_did).subst(tcx, substs.substs);
+    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     assert_eq!(sig.inputs().len(), 1);
     let substs = tcx.mk_substs([
@@ -165,9 +165,11 @@ pub fn resolve<'a, 'tcx>(
     } else {
         let item_type = def_ty(scx, def_id, substs);
         let def = match item_type.sty {
-            ty::TyFnDef(_, _, f) if
-                f.abi() == Abi::RustIntrinsic ||
-                f.abi() == Abi::PlatformIntrinsic =>
+            ty::TyFnDef(..) if {
+                    let f = item_type.fn_sig(scx.tcx());
+                    f.abi() == Abi::RustIntrinsic ||
+                    f.abi() == Abi::PlatformIntrinsic
+                } =>
             {
                 debug!(" => intrinsic");
                 ty::InstanceDef::Intrinsic(def_id)
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 0dc2bc85e30..2a6e7c5ace6 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -25,8 +25,9 @@ use llvm;
 use monomorphize::Instance;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Subst, Substs};
 use syntax::ast::{self, NodeId};
 use syntax::attr;
 use syntax_pos::Span;
@@ -250,6 +251,44 @@ impl<'a, 'tcx> TransItem<'tcx> {
         }
     }
 
+    /// Returns whether this instance is instantiable - whether it has no unsatisfied
+    /// predicates.
+    ///
+    /// In order to translate an item, all of its predicates must hold, because
+    /// otherwise the item does not make sense. Type-checking ensures that
+    /// the predicates of every item that is *used by* a valid item *do*
+    /// hold, so we can rely on that.
+    ///
+    /// However, we translate collector roots (reachable items) and functions
+    /// in vtables when they are seen, even if they are not used, and so they
+    /// might not be instantiable. For example, a programmer can define this
+    /// public function:
+    ///
+    ///     pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+    ///         <&mut () as Clone>::clone(&s);
+    ///     }
+    ///
+    /// That function can't be translated, because the method `<&mut () as Clone>::clone`
+    /// does not exist. Luckily for us, that function can't ever be used,
+    /// because that would require for `&'a mut (): Clone` to hold, so we
+    /// can just not emit any code, or even a linker reference for it.
+    ///
+    /// Similarly, if a vtable method has such a signature, and therefore can't
+    /// be used, we can just not emit it and have a placeholder (a null pointer,
+    /// which will never be accessed) in its place.
+    pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
+        debug!("is_instantiable({:?})", self);
+        let (def_id, substs) = match *self {
+            TransItem::Fn(ref instance) => (instance.def_id(), instance.substs),
+            TransItem::Static(node_id) => (tcx.hir.local_def_id(node_id), Substs::empty()),
+            // global asm never has predicates
+            TransItem::GlobalAsm(..) => return true
+        };
+
+        let predicates = tcx.predicates_of(def_id).predicates.subst(tcx, substs);
+        traits::normalize_and_test_predicates(tcx, predicates)
+    }
+
     pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
         let hir_map = &tcx.hir;
 
@@ -401,8 +440,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
                         output);
                 }
             },
-            ty::TyFnDef(.., sig) |
-            ty::TyFnPtr(sig) => {
+            ty::TyFnDef(..) |
+            ty::TyFnPtr(_) => {
+                let sig = t.fn_sig(self.tcx);
                 if sig.unsafety() == hir::Unsafety::Unsafe {
                     output.push_str("unsafe ");
                 }
diff --git a/src/librustc_tsan/build.rs b/src/librustc_tsan/build.rs
index 5ea52f17a0f..641d9c3647d 100644
--- a/src/librustc_tsan/build.rs
+++ b/src/librustc_tsan/build.rs
@@ -32,4 +32,5 @@ fn main() {
             .build_target("tsan")
             .build();
     }
+    println!("cargo:rerun-if-env-changed=LLVM_CONFIG");
 }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index bdd8169b84f..68726a7b1c4 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -619,7 +619,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // Type check the path.
         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
         // Replace constructor type with constructed type for tuple struct patterns.
-        let pat_ty = pat_ty.fn_sig().output();
+        let pat_ty = pat_ty.fn_sig(tcx).output();
         let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type");
         self.demand_eqtype(pat.span, expected, pat_ty);
 
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 385ed7eb0e3..a0801a74866 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 // haven't yet decided on whether the closure is fn vs
                 // fnmut vs fnonce. If so, we have to defer further processing.
                 if self.closure_kind(def_id).is_none() {
-                    let closure_ty = self.closure_type(def_id).subst(self.tcx, substs.substs);
+                    let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
                     let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                                    infer::FnCall,
                                                                    &closure_ty)
@@ -196,8 +196,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             expected: Expectation<'tcx>)
                             -> Ty<'tcx> {
         let (fn_sig, def_span) = match callee_ty.sty {
-            ty::TyFnDef(def_id, .., sig) => {
-                (sig, self.tcx.hir.span_if_local(def_id))
+            ty::TyFnDef(def_id, _) => {
+                (callee_ty.fn_sig(self.tcx), self.tcx.hir.span_if_local(def_id))
             }
             ty::TyFnPtr(sig) => (sig, None),
             ref t => {
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 91aeade65aa..7bd24c939ca 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -40,9 +40,11 @@
 
 use super::{Diverges, FnCtxt};
 
-use lint;
+use errors::DiagnosticBuilder;
 use hir::def_id::DefId;
+use lint;
 use rustc::hir;
+use rustc::session::Session;
 use rustc::traits;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::cast::{CastKind, CastTy};
@@ -112,6 +114,18 @@ enum CastError {
     NonScalar,
 }
 
+fn make_invalid_casting_error<'a, 'gcx, 'tcx>(sess: &'a Session,
+                                              span: Span,
+                                              expr_ty: Ty<'tcx>,
+                                              cast_ty: Ty<'tcx>,
+                                              fcx: &FnCtxt<'a, 'gcx, 'tcx>)
+                                              -> DiagnosticBuilder<'a> {
+    type_error_struct!(sess, span, expr_ty, E0606,
+                       "casting `{}` as `{}` is invalid",
+                       fcx.ty_to_string(expr_ty),
+                       fcx.ty_to_string(cast_ty))
+}
+
 impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
     pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                expr: &'tcx hir::Expr,
@@ -146,14 +160,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
         match e {
             CastError::NeedDeref => {
                 let error_span = self.span;
+                let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+                                                         self.cast_ty, fcx);
                 let cast_ty = fcx.ty_to_string(self.cast_ty);
-                let mut err = fcx.type_error_struct(error_span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   cast_ty)
-                                       },
-                                       self.expr_ty);
                 err.span_label(error_span,
                                format!("cannot cast `{}` as `{}`",
                                         fcx.ty_to_string(self.expr_ty),
@@ -166,13 +175,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
             }
             CastError::NeedViaThinPtr |
             CastError::NeedViaPtr => {
-                let mut err = fcx.type_error_struct(self.span,
-                                                    |actual| {
-                                                        format!("casting `{}` as `{}` is invalid",
-                                                                actual,
-                                                                fcx.ty_to_string(self.cast_ty))
-                                                    },
-                                                    self.expr_ty);
+                let mut err = make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty,
+                                                         self.cast_ty, fcx);
                 if self.cast_ty.is_uint() {
                     err.help(&format!("cast through {} first",
                                       match e {
@@ -184,13 +188,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                 err.emit();
             }
             CastError::NeedViaInt => {
-                fcx.type_error_struct(self.span,
-                                      |actual| {
-                                          format!("casting `{}` as `{}` is invalid",
-                                                  actual,
-                                                  fcx.ty_to_string(self.cast_ty))
-                                      },
-                                      self.expr_ty)
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
                    .help(&format!("cast through {} first",
                                   match e {
                                       CastError::NeedViaInt => "an integer",
@@ -198,6 +196,15 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                                   }))
                    .emit();
             }
+            CastError::IllegalCast => {
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+                    .emit();
+            }
+            CastError::DifferingKinds => {
+                make_invalid_casting_error(fcx.tcx.sess, self.span, self.expr_ty, self.cast_ty, fcx)
+                    .note("vtable kinds may not match")
+                    .emit();
+            }
             CastError::CastToBool => {
                 struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
                     .span_label(self.span, "unsupported cast")
@@ -205,51 +212,23 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
                     .emit();
             }
             CastError::CastToChar => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("only `u8` can be cast as `char`, not `{}`",
-                                                   actual)
-                                       },
-                                       self.expr_ty);
+                type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0604,
+                                 "only `u8` can be cast as `char`, not `{}`", self.expr_ty).emit();
             }
             CastError::NonScalar => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("non-scalar cast: `{}` as `{}`",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty);
-            }
-            CastError::IllegalCast => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty);
+                type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0605,
+                                 "non-primitive cast: `{}` as `{}`",
+                                 self.expr_ty,
+                                 fcx.ty_to_string(self.cast_ty))
+                                .note("an `as` expression can only be used to convert between \
+                                       primitive types. Consider using the `From` trait")
+                                .emit();
             }
             CastError::SizedUnsizedCast => {
-                fcx.type_error_message(self.span,
-                                       |actual| {
-                                           format!("cannot cast thin pointer `{}` to fat pointer \
-                                                    `{}`",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty)
-            }
-            CastError::DifferingKinds => {
-                fcx.type_error_struct(self.span,
-                                       |actual| {
-                                           format!("casting `{}` as `{}` is invalid",
-                                                   actual,
-                                                   fcx.ty_to_string(self.cast_ty))
-                                       },
-                                       self.expr_ty)
-                    .note("vtable kinds may not match")
-                    .emit();
+                type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0607,
+                                 "cannot cast thin pointer `{}` to fat pointer `{}`",
+                                 self.expr_ty,
+                                 fcx.ty_to_string(self.cast_ty)).emit();
             }
         }
     }
@@ -260,12 +239,10 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
         }
 
         let tstr = fcx.ty_to_string(self.cast_ty);
-        let mut err =
-            fcx.type_error_struct(self.span,
-                                  |actual| {
-                                      format!("cast to unsized type: `{}` as `{}`", actual, tstr)
-                                  },
-                                  self.expr_ty);
+        let mut err = type_error_struct!(fcx.tcx.sess, self.span, self.expr_ty, E0620,
+                                         "cast to unsized type: `{}` as `{}`",
+                                         fcx.resolve_type_vars_if_possible(&self.expr_ty),
+                                         tstr);
         match self.expr_ty.sty {
             ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
                 let mtstr = match mt {
@@ -377,8 +354,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
             (Some(t_from), Some(t_cast)) => (t_from, t_cast),
             // Function item types may need to be reified before casts.
             (None, Some(t_cast)) => {
-                if let ty::TyFnDef(.., f) = self.expr_ty.sty {
+                if let ty::TyFnDef(..) = self.expr_ty.sty {
                     // Attempt a coercion to a fn pointer type.
+                    let f = self.expr_ty.fn_sig(fcx.tcx);
                     let res = fcx.try_coerce(self.expr,
                                              self.expr_ty,
                                              self.expr_diverges,
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 30ac7b4bfb9..968e893b9a0 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -76,6 +76,7 @@ use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::Subst;
 use errors::DiagnosticBuilder;
 use syntax::abi;
+use syntax::feature_gate;
 use syntax::ptr::P;
 use syntax_pos;
 
@@ -210,13 +211,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         }
 
         match a.sty {
-            ty::TyFnDef(.., a_f) => {
+            ty::TyFnDef(..) => {
                 // Function items are coercible to any closure
                 // type; function pointers are not (that would
                 // require double indirection).
                 // Additionally, we permit coercion of function
                 // items to drop the unsafe qualifier.
-                self.coerce_from_fn_item(a, a_f, b)
+                self.coerce_from_fn_item(a, b)
             }
             ty::TyFnPtr(a_f) => {
                 // We permit coercion of fn pointers to drop the
@@ -520,6 +521,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                                                          coerce_source,
                                                          &[coerce_target]));
 
+        let mut has_unsized_tuple_coercion = false;
+
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
         // inference might unify those two inner type variables later.
@@ -527,7 +530,15 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         while let Some(obligation) = queue.pop_front() {
             debug!("coerce_unsized resolve step: {:?}", obligation);
             let trait_ref = match obligation.predicate {
-                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
+                ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => {
+                    if unsize_did == tr.def_id() {
+                        if let ty::TyTuple(..) = tr.0.input_types().nth(1).unwrap().sty {
+                            debug!("coerce_unsized: found unsized tuple coercion");
+                            has_unsized_tuple_coercion = true;
+                        }
+                    }
+                    tr.clone()
+                }
                 _ => {
                     coercion.obligations.push(obligation);
                     continue;
@@ -557,6 +568,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
             }
         }
 
+        if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion {
+            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
+                                           "unsized_tuple_coercion",
+                                           self.cause.span,
+                                           feature_gate::GateIssue::Language,
+                                           feature_gate::EXPLAIN_UNSIZED_TUPLE_COERCION);
+        }
+
         Ok(coercion)
     }
 
@@ -600,7 +619,6 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
 
     fn coerce_from_fn_item(&self,
                            a: Ty<'tcx>,
-                           fn_ty_a: ty::PolyFnSig<'tcx>,
                            b: Ty<'tcx>)
                            -> CoerceResult<'tcx> {
         //! Attempts to coerce from the type of a Rust function item
@@ -612,9 +630,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
 
         match b.sty {
             ty::TyFnPtr(_) => {
-                let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
-                self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b,
-                    simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))
+                let a_sig = a.fn_sig(self.tcx);
+                let InferOk { value: a_sig, mut obligations } =
+                    self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
+
+                let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);
+                let InferOk { value, obligations: o2 } =
+                    self.coerce_from_safe_fn(a_fn_pointer, a_sig, b,
+                        simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))?;
+
+                obligations.extend(o2);
+                Ok(InferOk { value, obligations })
             }
             _ => self.unify_and(a, b, identity),
         }
@@ -639,7 +665,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
                 // to
                 //     `fn(arg0,arg1,...) -> _`
-                let sig = self.closure_type(def_id_a).subst(self.tcx, substs_a.substs);
+                let sig = self.fn_sig(def_id_a).subst(self.tcx, substs_a.substs);
                 let converted_sig = sig.map_bound(|s| {
                     let params_iter = match s.inputs()[0].sty {
                         ty::TyTuple(params, _) => {
@@ -775,42 +801,41 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         // Special-case that coercion alone cannot handle:
         // Two function item types of differing IDs or Substs.
-        match (&prev_ty.sty, &new_ty.sty) {
-            (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
-                // The signature must always match.
-                let fty = self.at(cause, self.param_env)
-                              .trace(prev_ty, new_ty)
-                              .lub(&a_fty, &b_fty)
-                              .map(|ok| self.register_infer_ok_obligations(ok))?;
-
-                if a_def_id == b_def_id {
-                    // Same function, maybe the parameters match.
-                    let substs = self.commit_if_ok(|_| {
-                        self.at(cause, self.param_env)
-                            .trace(prev_ty, new_ty)
-                            .lub(&a_substs, &b_substs)
-                            .map(|ok| self.register_infer_ok_obligations(ok))
-                    });
-
-                    if let Ok(substs) = substs {
-                        // We have a LUB of prev_ty and new_ty, just return it.
-                        return Ok(self.tcx.mk_fn_def(a_def_id, substs, fty));
-                    }
-                }
+        if let (&ty::TyFnDef(..), &ty::TyFnDef(..)) = (&prev_ty.sty, &new_ty.sty) {
+            // Don't reify if the function types have a LUB, i.e. they
+            // are the same function and their parameters have a LUB.
+            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))
+            });
+
+            if lub_ty.is_ok() {
+                // We have a LUB of prev_ty and new_ty, just return it.
+                return lub_ty;
+            }
 
-                // Reify both sides and return the reified fn pointer type.
-                let fn_ptr = self.tcx.mk_fn_ptr(fty);
-                for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
-                    // The only adjustment that can produce an fn item is
-                    // `NeverToAny`, so this should always be valid.
-                    self.apply_adjustments(expr, vec![Adjustment {
-                        kind: Adjust::ReifyFnPointer,
-                        target: fn_ptr
-                    }]);
-                }
-                return Ok(fn_ptr);
+            // The signature must match.
+            let a_sig = prev_ty.fn_sig(self.tcx);
+            let a_sig = self.normalize_associated_types_in(new.span, &a_sig);
+            let b_sig = new_ty.fn_sig(self.tcx);
+            let b_sig = self.normalize_associated_types_in(new.span, &b_sig);
+            let sig = self.at(cause, self.param_env)
+                          .trace(prev_ty, new_ty)
+                          .lub(&a_sig, &b_sig)
+                          .map(|ok| self.register_infer_ok_obligations(ok))?;
+
+            // Reify both sides and return the reified fn pointer type.
+            let fn_ptr = self.tcx.mk_fn_ptr(sig);
+            for expr in exprs.iter().map(|e| e.as_coercion_site()).chain(Some(new)) {
+                // The only adjustment that can produce an fn item is
+                // `NeverToAny`, so this should always be valid.
+                self.apply_adjustments(expr, vec![Adjustment {
+                    kind: Adjust::ReifyFnPointer,
+                    target: fn_ptr
+                }]);
             }
-            _ => {}
+            return Ok(fn_ptr);
         }
 
         let mut coerce = Coerce::new(self, cause.clone());
@@ -1162,6 +1187,18 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                             "`return;` in a function whose return type is not `()`");
                         db.span_label(cause.span, "return type is not ()");
                     }
+                    ObligationCauseCode::BlockTailExpression(blk_id) => {
+                        db = fcx.report_mismatched_types(cause, expected, found, err);
+
+                        let expr = expression.unwrap_or_else(|| {
+                            span_bug!(cause.span,
+                                      "supposed to be part of a block tail expression, but the \
+                                       expression is empty");
+                        });
+                        fcx.suggest_mismatched_types_on_tail(&mut db, expr,
+                                                             expected, found,
+                                                             cause.span, blk_id);
+                    }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
                     }
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 29742469f84..bf134f9547d 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -256,17 +256,10 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Compute skolemized form of impl and trait method tys.
         let tcx = infcx.tcx;
 
-        let m_sig = |method: &ty::AssociatedItem| {
-            match tcx.type_of(method.def_id).sty {
-                ty::TyFnDef(_, _, f) => f,
-                _ => bug!()
-            }
-        };
-
         let (impl_sig, _) =
             infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
                                                             infer::HigherRankedType,
-                                                            &m_sig(impl_m));
+                                                            &tcx.fn_sig(impl_m.def_id));
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span,
                                               impl_m_node_id,
@@ -277,7 +270,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         let trait_sig = inh.liberate_late_bound_regions(
             impl_m.def_id,
-            &m_sig(trait_m));
+            &tcx.fn_sig(trait_m.def_id));
         let trait_sig =
             trait_sig.subst(tcx, trait_to_skol_substs);
         let trait_sig =
@@ -335,7 +328,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Check that all obligations are satisfied by the implementation's
         // version.
         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors);
+            infcx.report_fulfillment_errors(errors, None);
             return Err(ErrorReported);
         }
 
@@ -507,8 +500,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             ty::ImplContainer(_) => impl_trait_ref.self_ty(),
             ty::TraitContainer(_) => tcx.mk_self_type()
         };
-        let method_ty = tcx.type_of(method.def_id);
-        let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder();
+        let self_arg_ty = *tcx.fn_sig(method.def_id).input(0).skip_binder();
         match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) {
             ExplicitSelf::ByValue => "self".to_string(),
             ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(),
@@ -637,14 +629,8 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 trait_m: &ty::AssociatedItem,
                                                 trait_item_span: Option<Span>)
                                                 -> Result<(), ErrorReported> {
-    let m_fty = |method: &ty::AssociatedItem| {
-        match tcx.type_of(method.def_id).sty {
-            ty::TyFnDef(_, _, f) => f,
-            _ => bug!()
-        }
-    };
-    let impl_m_fty = m_fty(impl_m);
-    let trait_m_fty = m_fty(trait_m);
+    let impl_m_fty = tcx.fn_sig(impl_m.def_id);
+    let trait_m_fty = tcx.fn_sig(trait_m.def_id);
     let trait_number_args = trait_m_fty.inputs().skip_binder().len();
     let impl_number_args = impl_m_fty.inputs().skip_binder().len();
     if trait_number_args != impl_number_args {
@@ -807,7 +793,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Check that all obligations are satisfied by the implementation's
         // version.
         if let Err(ref errors) = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(errors);
+            infcx.report_fulfillment_errors(errors, None);
             return;
         }
 
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 1b6f96cf651..f54ad541872 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -73,15 +73,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) {
+        if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) {
+            err.emit();
+        }
+    }
+
     // Checks that the type of `expr` can be coerced to `expected`.
     //
     // NB: This code relies on `self.diverges` to be accurate.  In
     // particular, assignments to `!` will be permitted if the
     // diverges flag is currently "always".
-    pub fn demand_coerce(&self,
-                         expr: &hir::Expr,
-                         checked_ty: Ty<'tcx>,
-                         expected: Ty<'tcx>) {
+    pub fn demand_coerce_diag(&self,
+                              expr: &hir::Expr,
+                              checked_ty: Ty<'tcx>,
+                              expected: Ty<'tcx>) -> Option<DiagnosticBuilder<'tcx>> {
         let expected = self.resolve_type_vars_with_obligations(expected);
 
         if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) {
@@ -105,8 +111,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                       self.get_best_match(&suggestions).join("\n")));
                 }
             }
-            err.emit();
+            return Some(err);
         }
+        None
     }
 
     fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
@@ -143,12 +150,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {
         match method.def() {
             Def::Method(def_id) => {
-                match self.tcx.type_of(def_id).sty {
-                    ty::TypeVariants::TyFnDef(_, _, sig) => {
-                        sig.inputs().skip_binder().len() == 1
-                    }
-                    _ => false,
-                }
+                self.tcx.fn_sig(def_id).inputs().skip_binder().len() == 1
             }
             _ => false,
         }
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 93057f91997..ed22cd1333e 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -110,7 +110,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
 
         if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
             // this could be reached when we get lazy normalization
-            infcx.report_fulfillment_errors(errors);
+            infcx.report_fulfillment_errors(errors, None);
             return Err(ErrorReported);
         }
 
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 4d9f50b0fc0..96643ae72ab 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -13,7 +13,6 @@
 
 use intrinsics;
 use rustc::traits::{ObligationCause, ObligationCauseCode};
-use rustc::ty::subst::Substs;
 use rustc::ty::{self, TyCtxt, Ty};
 use rustc::util::nodemap::FxHashMap;
 use require_same_types;
@@ -35,22 +34,22 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    output: Ty<'tcx>) {
     let def_id = tcx.hir.local_def_id(it.id);
 
-    let substs = Substs::for_item(tcx, def_id,
-                                  |_, _| tcx.types.re_erased,
-                                  |def, _| tcx.mk_param_from_def(def));
+    match it.node {
+        hir::ForeignItemFn(..) => {}
+        _ => {
+            struct_span_err!(tcx.sess, it.span, E0622,
+                             "intrinsic must be a function")
+                .span_label(it.span, "expected a function")
+                .emit();
+            return;
+        }
+    }
 
-    let fty = tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
-        inputs.into_iter(),
-        output,
-        false,
-        hir::Unsafety::Unsafe,
-        abi
-    )));
     let i_n_tps = tcx.generics_of(def_id).types.len();
     if i_n_tps != n_tps {
         let span = match it.node {
             hir::ForeignItemFn(_, _, ref generics) => generics.span,
-            hir::ForeignItemStatic(..) => it.span
+            _ => bug!()
         };
 
         struct_span_err!(tcx.sess, span, E0094,
@@ -59,14 +58,18 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         i_n_tps, n_tps)
             .span_label(span, format!("expected {} type parameter", n_tps))
             .emit();
-    } else {
-        require_same_types(tcx,
-                           &ObligationCause::new(it.span,
-                                                 it.id,
-                                                 ObligationCauseCode::IntrinsicType),
-                           tcx.type_of(def_id),
-                           fty);
+        return;
     }
+
+    let fty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+        inputs.into_iter(),
+        output,
+        false,
+        hir::Unsafety::Unsafe,
+        abi
+    )));
+    let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType);
+    require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty);
 }
 
 /// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
@@ -376,7 +379,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
                     let mut structural_to_nomimal = FxHashMap();
 
-                    let sig = tcx.type_of(def_id).fn_sig();
+                    let sig = tcx.fn_sig(def_id);
                     let sig = tcx.no_late_bound_regions(&sig).unwrap();
                     if intr.inputs.len() != sig.inputs().len() {
                         span_err!(tcx.sess, it.span, E0444,
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 36bd6657389..209245187b1 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -375,7 +375,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
         debug!("method_predicates after subst = {:?}", method_predicates);
 
-        let sig = self.tcx.type_of(def_id).fn_sig();
+        let sig = self.tcx.fn_sig(def_id);
 
         // Instantiate late-bound regions and substitute the trait
         // parameters into the method type to get the actual method type.
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 73c1215f275..4f4169ac93d 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -235,7 +235,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // NB: Instantiate late-bound regions first so that
         // `instantiate_type_scheme` can normalize associated types that
         // may reference those regions.
-        let fn_sig = tcx.type_of(def_id).fn_sig();
+        let fn_sig = tcx.fn_sig(def_id);
         let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
                                                                     infer::FnCall,
                                                                     &fn_sig).0;
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 2518a1739f7..ee9a347ae95 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -673,7 +673,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                                expected: ty::Ty<'tcx>) -> bool {
         match method.def() {
             Def::Method(def_id) => {
-                let fty = self.tcx.type_of(def_id).fn_sig();
+                let fty = self.tcx.fn_sig(def_id);
                 self.probe(|_| {
                     let substs = self.fresh_substs_for_item(self.span, method.def_id);
                     let output = fty.output().subst(self.tcx, substs);
@@ -1288,7 +1288,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                             impl_ty: Ty<'tcx>,
                             substs: &Substs<'tcx>)
                             -> Ty<'tcx> {
-        let self_ty = self.tcx.type_of(method).fn_sig().input(0);
+        let self_ty = self.tcx.fn_sig(method).input(0);
         debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})",
                impl_ty,
                self_ty,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 2bf24d5b350..3241267bbc2 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -102,7 +102,7 @@ use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
 use errors::DiagnosticBuilder;
 use require_c_abi_if_variadic;
-use session::{Session, CompileResult};
+use session::{CompileIncomplete, Session};
 use TypeAndSubsts;
 use lint;
 use util::common::{ErrorReported, indenter};
@@ -124,6 +124,7 @@ use syntax_pos::{self, BytePos, Span};
 
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir::map::Node;
 use rustc::hir::{self, PatKind};
 use rustc::middle::lang_items;
 use rustc_back::slice;
@@ -216,6 +217,8 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// environment is for an item or something where the "callee" is
     /// not clear.
     implicit_region_bound: Option<ty::Region<'tcx>>,
+
+    body_id: Option<hir::BodyId>,
 }
 
 impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
@@ -604,6 +607,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
             deferred_cast_checks: RefCell::new(Vec::new()),
             anon_types: RefCell::new(NodeMap()),
             implicit_region_bound,
+            body_id,
         }
     }
 
@@ -687,30 +691,32 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
     fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
 }
 
-pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
+pub fn check_wf_new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
     tcx.sess.track_errors(|| {
         let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx);
         tcx.hir.krate().visit_all_item_likes(&mut visit.as_deep_visitor());
     })
 }
 
-pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
+pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), ErrorReported> {
     tcx.sess.track_errors(|| {
         tcx.hir.krate().visit_all_item_likes(&mut CheckItemTypesVisitor { tcx });
     })
 }
 
-pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
+pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Result<(), CompileIncomplete> {
     tcx.typeck_item_bodies(LOCAL_CRATE)
 }
 
-fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> CompileResult {
+fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
+                                -> Result<(), CompileIncomplete>
+{
     debug_assert!(crate_num == LOCAL_CRATE);
-    tcx.sess.track_errors(|| {
+    Ok(tcx.sess.track_errors(|| {
         for body_owner_def_id in tcx.body_owners() {
             tcx.typeck_tables_of(body_owner_def_id);
         }
-    })
+    })?)
 }
 
 pub fn provide(providers: &mut Providers) {
@@ -718,20 +724,12 @@ pub fn provide(providers: &mut Providers) {
         typeck_item_bodies,
         typeck_tables_of,
         has_typeck_tables,
-        closure_type,
         closure_kind,
         adt_destructor,
         ..*providers
     };
 }
 
-fn closure_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          def_id: DefId)
-                          -> ty::PolyFnSig<'tcx> {
-    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-    tcx.typeck_tables_of(def_id).closure_tys[&node_id]
-}
-
 fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           def_id: DefId)
                           -> ty::ClosureKind {
@@ -844,7 +842,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     Inherited::build(tcx, def_id).enter(|inh| {
         let param_env = tcx.param_env(def_id);
         let fcx = if let Some(decl) = fn_decl {
-            let fn_sig = tcx.type_of(def_id).fn_sig();
+            let fn_sig = tcx.fn_sig(def_id);
 
             check_abi(tcx, span, fn_sig.abi());
 
@@ -985,7 +983,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id);
 
     let ret_ty = fn_sig.output();
-    fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
+    fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType);
     let ret_ty = fcx.instantiate_anon_types(&ret_ty);
     fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
     fn_sig = fcx.tcx.mk_fn_sig(
@@ -1000,16 +998,17 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     // Add formal parameters.
     for (arg_ty, arg) in fn_sig.inputs().iter().zip(&body.arguments) {
-        // The type of the argument must be well-formed.
-        //
-        // NB -- this is now checked in wfcheck, but that
-        // currently only results in warnings, so we issue an
-        // old-style WF obligation here so that we still get the
-        // errors that we used to get.
-        fcx.register_old_wf_obligation(arg_ty, arg.pat.span, traits::MiscObligation);
-
         // Check the pattern.
         fcx.check_pat_arg(&arg.pat, arg_ty, true);
+
+        // Check that argument is Sized.
+        // The check for a non-trivial pattern is a hack to avoid duplicate warnings
+        // for simple cases like `fn foo(x: Trait)`,
+        // where we would error once on the parameter as a whole, and once on the binding `x`.
+        if arg.pat.simple_name().is_none() {
+            fcx.require_type_is_sized(arg_ty, decl.output.span(), traits::MiscObligation);
+        }
+
         fcx.write_ty(arg.id, arg_ty);
     }
 
@@ -1908,7 +1907,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                     // Require that the predicate holds for the concrete type.
                     let cause = traits::ObligationCause::new(span, self.body_id,
-                                                             traits::ReturnType);
+                                                             traits::SizedReturnType);
                     self.register_predicate(traits::Obligation::new(cause,
                                                                     self.param_env,
                                                                     predicate));
@@ -1987,17 +1986,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
     /// Registers an obligation for checking later, during regionck, that the type `ty` must
     /// outlive the region `r`.
-    pub fn register_region_obligation(&self,
-                                      ty: Ty<'tcx>,
-                                      region: ty::Region<'tcx>,
-                                      cause: traits::ObligationCause<'tcx>)
-    {
-        let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
-        fulfillment_cx.register_region_obligation(ty, region, cause);
-    }
-
-    /// Registers an obligation for checking later, during regionck, that the type `ty` must
-    /// outlive the region `r`.
     pub fn register_wf_obligation(&self,
                                   ty: Ty<'tcx>,
                                   span: Span,
@@ -2010,21 +1998,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                         ty::Predicate::WellFormed(ty)));
     }
 
-    pub fn register_old_wf_obligation(&self,
-                                      ty: Ty<'tcx>,
-                                      span: Span,
-                                      code: traits::ObligationCauseCode<'tcx>)
-    {
-        // Registers an "old-style" WF obligation that uses the
-        // implicator code.  This is basically a buggy version of
-        // `register_wf_obligation` that is being kept around
-        // temporarily just to help with phasing in the newer rules.
-        //
-        // FIXME(#27579) all uses of this should be migrated to register_wf_obligation eventually
-        let cause = traits::ObligationCause::new(span, self.body_id, code);
-        self.register_region_obligation(ty, self.tcx.types.re_empty, cause);
-    }
-
     /// Registers obligations that all types appearing in `substs` are well-formed.
     pub fn add_wf_bounds(&self, substs: &Substs<'tcx>, expr: &hir::Expr)
     {
@@ -2152,7 +2125,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         match fulfillment_cx.select_all_or_error(self) {
             Ok(()) => { }
-            Err(errors) => { self.report_fulfillment_errors(&errors); }
+            Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); }
         }
     }
 
@@ -2160,7 +2133,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn select_obligations_where_possible(&self) {
         match self.fulfillment_cx.borrow_mut().select_where_possible(self) {
             Ok(()) => { }
-            Err(errors) => { self.report_fulfillment_errors(&errors); }
+            Err(errors) => { self.report_fulfillment_errors(&errors, self.inh.body_id); }
         }
     }
 
@@ -2173,7 +2146,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                           -> ty::TypeAndMut<'tcx>
     {
         // extract method return type, which will be &T;
-        // all LB regions should have been instantiated during method lookup
         let ret_ty = method.sig.output();
 
         // method returns &T, but the type as visible to user is T, so deref
@@ -2580,8 +2552,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
                         variadic_error(tcx.sess, arg.span, arg_ty, "c_uint");
                     }
-                    ty::TyFnDef(.., f) => {
-                        let ptr_ty = self.tcx.mk_fn_ptr(f);
+                    ty::TyFnDef(..) => {
+                        let ptr_ty = self.tcx.mk_fn_ptr(arg_ty.fn_sig(self.tcx));
                         let ptr_ty = self.resolve_type_vars_if_possible(&ptr_ty);
                         variadic_error(tcx.sess, arg.span, arg_ty, &format!("{}", ptr_ty));
                     }
@@ -2848,10 +2820,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                              "check_return_expr called outside fn body"));
 
         let ret_ty = ret_coercion.borrow().expected_ty();
-        let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
+        let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone());
         ret_coercion.borrow_mut()
                     .coerce(self,
-                            &self.misc(return_expr.span),
+                            &self.cause(return_expr.span,
+                                        ObligationCauseCode::ReturnType(return_expr.id)),
                             return_expr,
                             return_expr_ty,
                             self.diverges.get());
@@ -3154,11 +3127,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let adt_ty_hint =
             self.expected_inputs_for_expected_output(span, expected, adt_ty, &[adt_ty])
-                .get(0).cloned().unwrap_or(adt_ty);
+            .get(0).cloned().unwrap_or(adt_ty);
+        // re-link the regions that EIfEO can erase.
+        self.demand_eqtype(span, adt_ty_hint, adt_ty);
 
-        let (substs, hint_substs, adt_kind, kind_name) = match (&adt_ty.sty, &adt_ty_hint.sty) {
-            (&ty::TyAdt(adt, substs), &ty::TyAdt(_, hint_substs)) => {
-                (substs, hint_substs, adt.adt_kind(), adt.variant_descr())
+        let (substs, adt_kind, kind_name) = match &adt_ty.sty{
+            &ty::TyAdt(adt, substs) => {
+                (substs, adt.adt_kind(), adt.variant_descr())
             }
             _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
         };
@@ -3174,14 +3149,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         // Typecheck each field.
         for field in ast_fields {
-            let final_field_type;
-            let field_type_hint;
-
             let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0;
-            if let Some(v_field) = remaining_fields.remove(&ident) {
-                final_field_type = self.field_ty(field.span, v_field, substs);
-                field_type_hint = self.field_ty(field.span, v_field, hint_substs);
-
+            let field_type = if let Some(v_field) = remaining_fields.remove(&ident) {
                 seen_fields.insert(field.name.node, field.span);
 
                 // we don't look at stability attributes on
@@ -3190,10 +3159,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 if adt_kind != ty::AdtKind::Enum {
                     tcx.check_stability(v_field.did, expr_id, field.span);
                 }
+
+                self.field_ty(field.span, v_field, substs)
             } else {
                 error_happened = true;
-                final_field_type = tcx.types.err;
-                field_type_hint = tcx.types.err;
                 if let Some(_) = variant.find_field_named(field.name.node) {
                     let mut err = struct_span_err!(self.tcx.sess,
                                                    field.name.span,
@@ -3211,12 +3180,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 } else {
                     self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name);
                 }
-            }
+
+                tcx.types.err
+            };
 
             // Make sure to give a type to the field even if there's
             // an error, so we can continue typechecking
-            let ty = self.check_expr_with_hint(&field.expr, field_type_hint);
-            self.demand_coerce(&field.expr, ty, final_field_type);
+            self.check_expr_coercable_to_type(&field.expr, field_type);
         }
 
         // Make sure the programmer specified correct number of fields.
@@ -3883,6 +3853,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             if tuple.references_error() {
                 tcx.types.err
             } else {
+                self.require_type_is_sized(tuple, expr.span, traits::TupleInitializerSized);
                 tuple
             }
           }
@@ -4170,8 +4141,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let mut coerce = ctxt.coerce.as_mut().unwrap();
             if let Some(tail_expr_ty) = tail_expr_ty {
                 let tail_expr = tail_expr.unwrap();
+                let cause = self.cause(tail_expr.span,
+                                       ObligationCauseCode::BlockTailExpression(blk.id));
                 coerce.coerce(self,
-                              &self.misc(tail_expr.span),
+                              &cause,
                               tail_expr,
                               tail_expr_ty,
                               self.diverges.get());
@@ -4210,6 +4183,130 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         ty
     }
 
+    /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is
+    /// `fn main` if it is a method, `None` otherwise.
+    pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> {
+        // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
+        // `while` before reaching it, as block tail returns are not available in them.
+        if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) {
+            let parent = self.tcx.hir.get(fn_id);
+
+            if let Node::NodeItem(&hir::Item {
+                name, node: hir::ItemFn(ref decl, ..), ..
+            }) = parent {
+                decl.clone().and_then(|decl| {
+                    // This is less than ideal, it will not present the return type span on any
+                    // method called `main`, regardless of whether it is actually the entry point.
+                    Some((decl, name == Symbol::intern("main")))
+                })
+            } else if let Node::NodeTraitItem(&hir::TraitItem {
+                node: hir::TraitItemKind::Method(hir::MethodSig {
+                    ref decl, ..
+                }, ..), ..
+            }) = parent {
+                decl.clone().and_then(|decl| {
+                    Some((decl, false))
+                })
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
+    /// On implicit return expressions with mismatched types, provide the following suggestions:
+    ///
+    ///  - Point out the method's return type as the reason for the expected type
+    ///  - Possible missing semicolon
+    ///  - Possible missing return type if the return type is the default, and not `fn main()`
+    pub fn suggest_mismatched_types_on_tail(&self,
+                                            err: &mut DiagnosticBuilder<'tcx>,
+                                            expression: &'gcx hir::Expr,
+                                            expected: Ty<'tcx>,
+                                            found: Ty<'tcx>,
+                                            cause_span: Span,
+                                            blk_id: ast::NodeId) {
+        self.suggest_missing_semicolon(err, expression, expected, cause_span);
+
+        if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) {
+            // `fn main()` must return `()`, do not suggest changing return type
+            if !is_main {
+                self.suggest_missing_return_type(err, &fn_decl, found);
+            }
+        }
+    }
+
+    /// A common error is to forget to add a semicolon at the end of a block:
+    ///
+    /// ```
+    /// fn foo() {
+    ///     bar_that_returns_u32()
+    /// }
+    /// ```
+    ///
+    /// This routine checks if the return expression in a block would make sense on its own as a
+    /// statement and the return type has been left as defaultor has been specified as `()`. If so,
+    /// it suggests adding a semicolon.
+    fn suggest_missing_semicolon(&self,
+                                     err: &mut DiagnosticBuilder<'tcx>,
+                                     expression: &'gcx hir::Expr,
+                                     expected: Ty<'tcx>,
+                                     cause_span: Span) {
+        if expected.is_nil() {
+            // `BlockTailExpression` only relevant if the tail expr would be
+            // useful on its own.
+            match expression.node {
+                hir::ExprCall(..) |
+                hir::ExprMethodCall(..) |
+                hir::ExprIf(..) |
+                hir::ExprWhile(..) |
+                hir::ExprLoop(..) |
+                hir::ExprMatch(..) |
+                hir::ExprBlock(..) => {
+                    let sp = cause_span.next_point();
+                    err.span_suggestion(sp,
+                                        "did you mean to add a semicolon here?",
+                                        ";".to_string());
+                }
+                _ => (),
+            }
+        }
+    }
+
+
+    /// A possible error is to forget to add a return type that is needed:
+    ///
+    /// ```
+    /// fn foo() {
+    ///     bar_that_returns_u32()
+    /// }
+    /// ```
+    ///
+    /// This routine checks if the return type is left as default, the method is not part of an
+    /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
+    /// type.
+    fn suggest_missing_return_type(&self,
+                                   err: &mut DiagnosticBuilder<'tcx>,
+                                   fn_decl: &hir::FnDecl,
+                                   ty: Ty<'tcx>) {
+
+        // Only recommend changing the return type for methods that
+        // haven't set a return type at all (and aren't `fn main()` or an impl).
+        if let &hir::FnDecl {
+            output: hir::FunctionRetTy::DefaultReturn(span), ..
+        } = fn_decl {
+            if ty.is_suggestable() {
+                err.span_suggestion(span,
+                                    "possibly return type missing here?",
+                                    format!("-> {} ", ty));
+            } else {
+                err.span_label(span, "possibly return type missing here?");
+            }
+        }
+    }
+
+
     /// A common error is to add an extra semicolon:
     ///
     /// ```
@@ -4245,7 +4342,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             hi: original_span.hi,
             ctxt: original_span.ctxt,
         };
-        err.span_help(span_semi, "consider removing this semicolon:");
+        err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string());
     }
 
     // Instantiates the given path, which must refer to an item with the given
@@ -4619,9 +4716,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             // If not, error.
             if alternative.is_ty_var() || alternative.references_error() {
                 if !self.is_tainted_by_errors() {
-                    self.type_error_message(sp, |_actual| {
-                        "the type of this value must be known in this context".to_string()
-                    }, ty);
+                    type_error_struct!(self.tcx.sess, sp, ty, E0619,
+                                       "the type of this value must be known in this context")
+                        .emit();
                 }
                 self.demand_suptype(sp, self.tcx.types.err, ty);
                 ty = self.tcx.types.err;
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 26f708e9345..cbda1227742 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -177,12 +177,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
                 }
                 ty::AssociatedKind::Method => {
                     reject_shadowing_type_parameters(fcx.tcx, item.def_id);
-                    let method_ty = fcx.tcx.type_of(item.def_id);
-                    let method_ty = fcx.normalize_associated_types_in(span, &method_ty);
+                    let sig = fcx.tcx.fn_sig(item.def_id);
+                    let sig = fcx.normalize_associated_types_in(span, &sig);
                     let predicates = fcx.tcx.predicates_of(item.def_id)
                         .instantiate_identity(fcx.tcx);
                     let predicates = fcx.normalize_associated_types_in(span, &predicates);
-                    let sig = method_ty.fn_sig();
                     this.check_fn_or_method(fcx, span, sig, &predicates,
                                             item.def_id, &mut implied_bounds);
                     let sig_if_method = sig_if_method.expect("bad signature for method");
@@ -331,9 +330,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
     fn check_item_fn(&mut self, item: &hir::Item) {
         self.for_item(item).with_fcx(|fcx, this| {
             let def_id = fcx.tcx.hir.local_def_id(item.id);
-            let ty = fcx.tcx.type_of(def_id);
-            let item_ty = fcx.normalize_associated_types_in(item.span, &ty);
-            let sig = item_ty.fn_sig();
+            let sig = fcx.tcx.fn_sig(def_id);
+            let sig = fcx.normalize_associated_types_in(item.span, &sig);
 
             let predicates = fcx.tcx.predicates_of(def_id).instantiate_identity(fcx.tcx);
             let predicates = fcx.normalize_associated_types_in(item.span, &predicates);
@@ -461,9 +459,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
 
         let span = method_sig.decl.inputs[0].span;
 
-        let method_ty = fcx.tcx.type_of(method.def_id);
-        let fty = fcx.normalize_associated_types_in(span, &method_ty);
-        let sig = fcx.liberate_late_bound_regions(method.def_id, &fty.fn_sig());
+        let sig = fcx.tcx.fn_sig(method.def_id);
+        let sig = fcx.normalize_associated_types_in(span, &sig);
+        let sig = fcx.liberate_late_bound_regions(method.def_id, &sig);
 
         debug!("check_method_receiver: sig={:?}", sig);
 
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 4af262bcb78..81e5dae5477 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -377,7 +377,7 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
 
     fn report_error(&self, t: Ty<'tcx>) {
         if !self.tcx.sess.has_errors() {
-            self.infcx.need_type_info(self.body.id(), self.span.to_span(&self.tcx), t);
+            self.infcx.need_type_info(Some(self.body.id()), self.span.to_span(&self.tcx), t);
         }
     }
 }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index ccbc0299041..9305eff1436 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -386,7 +386,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         // Check that all transitive obligations are satisfied.
         if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
-            infcx.report_fulfillment_errors(&errors);
+            infcx.report_fulfillment_errors(&errors, None);
         }
 
         // Finally, resolve all regions.
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fb3bcd31e21..fd6dda5ccf4 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -97,6 +97,7 @@ pub fn provide(providers: &mut Providers) {
         type_param_predicates,
         trait_def,
         adt_def,
+        fn_sig,
         impl_trait_ref,
         impl_polarity,
         is_foreign_item,
@@ -447,6 +448,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
                 tcx.generics_of(def_id);
                 tcx.type_of(def_id);
                 tcx.predicates_of(def_id);
+                if let hir::ForeignItemFn(..) = item.node {
+                    tcx.fn_sig(def_id);
+                }
             }
         }
         hir::ItemEnum(ref enum_definition, _) => {
@@ -497,6 +501,9 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
             tcx.predicates_of(def_id);
+            if let hir::ItemFn(..) = it.node {
+                tcx.fn_sig(def_id);
+            }
         }
     }
 }
@@ -511,6 +518,9 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast:
         hir::TraitItemKind::Type(_, Some(_)) |
         hir::TraitItemKind::Method(..) => {
             tcx.type_of(def_id);
+            if let hir::TraitItemKind::Method(..) = trait_item.node {
+                tcx.fn_sig(def_id);
+            }
         }
 
         hir::TraitItemKind::Type(_, None) => {}
@@ -524,6 +534,9 @@ fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::N
     tcx.generics_of(def_id);
     tcx.type_of(def_id);
     tcx.predicates_of(def_id);
+    if let hir::ImplItemKind::Method(..) = tcx.hir.expect_impl_item(impl_item_id).node {
+        tcx.fn_sig(def_id);
+    }
 }
 
 fn convert_variant_ctor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -963,10 +976,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     match tcx.hir.get(node_id) {
         NodeTraitItem(item) => {
             match item.node {
-                TraitItemKind::Method(ref sig, _) => {
-                    let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl);
+                TraitItemKind::Method(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, fty)
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 TraitItemKind::Const(ref ty, _) |
                 TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty),
@@ -978,10 +990,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         NodeImplItem(item) => {
             match item.node {
-                ImplItemKind::Method(ref sig, _) => {
-                    let fty = AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl);
+                ImplItemKind::Method(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, fty)
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
                 ImplItemKind::Type(ref ty) => {
@@ -1001,10 +1012,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemTy(ref t, _) | ItemImpl(.., ref t, _) => {
                     icx.to_ty(t)
                 }
-                ItemFn(ref decl, unsafety, _, abi, _, _) => {
-                    let tofd = AstConv::ty_of_fn(&icx, unsafety, abi, &decl);
+                ItemFn(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, tofd)
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 ItemEnum(..) |
                 ItemStruct(..) |
@@ -1029,11 +1039,10 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
 
         NodeForeignItem(foreign_item) => {
-            let abi = tcx.hir.get_foreign_abi(node_id);
-
             match foreign_item.node {
-                ForeignItemFn(ref fn_decl, _, _) => {
-                    compute_type_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
+                ForeignItemFn(..) => {
+                    let substs = Substs::identity_for_item(tcx, def_id);
+                    tcx.mk_fn_def(def_id, substs)
                 }
                 ForeignItemStatic(ref t, _) => icx.to_ty(t)
             }
@@ -1041,21 +1050,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         NodeStructCtor(&ref def) |
         NodeVariant(&Spanned { node: hir::Variant_ { data: ref def, .. }, .. }) => {
-            let ty = tcx.type_of(tcx.hir.get_parent_did(node_id));
             match *def {
-                VariantData::Unit(..) | VariantData::Struct(..) => ty,
-                VariantData::Tuple(ref fields, _) => {
-                    let inputs = fields.iter().map(|f| {
-                        tcx.type_of(tcx.hir.local_def_id(f.id))
-                    });
+                VariantData::Unit(..) | VariantData::Struct(..) => {
+                    tcx.type_of(tcx.hir.get_parent_did(node_id))
+                }
+                VariantData::Tuple(..) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    tcx.mk_fn_def(def_id, substs, ty::Binder(tcx.mk_fn_sig(
-                        inputs,
-                        ty,
-                        false,
-                        hir::Unsafety::Normal,
-                        abi::Abi::Rust
-                    )))
+                    tcx.mk_fn_def(def_id, substs)
                 }
             }
         }
@@ -1105,6 +1106,58 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    def_id: DefId)
+                    -> ty::PolyFnSig<'tcx> {
+    use rustc::hir::map::*;
+    use rustc::hir::*;
+
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+
+    let icx = ItemCtxt::new(tcx, def_id);
+
+    match tcx.hir.get(node_id) {
+        NodeTraitItem(&hir::TraitItem { node: TraitItemKind::Method(ref sig, _), .. }) |
+        NodeImplItem(&hir::ImplItem { node: ImplItemKind::Method(ref sig, _), .. }) => {
+            AstConv::ty_of_fn(&icx, sig.unsafety, sig.abi, &sig.decl)
+        }
+
+        NodeItem(&hir::Item { node: ItemFn(ref decl, unsafety, _, abi, _, _), .. }) => {
+            AstConv::ty_of_fn(&icx, unsafety, abi, decl)
+        }
+
+        NodeForeignItem(&hir::ForeignItem { node: ForeignItemFn(ref fn_decl, _, _), .. }) => {
+            let abi = tcx.hir.get_foreign_abi(node_id);
+            compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
+        }
+
+        NodeStructCtor(&VariantData::Tuple(ref fields, _)) |
+        NodeVariant(&Spanned { node: hir::Variant_ {
+            data: VariantData::Tuple(ref fields, _), ..
+        }, .. }) => {
+            let ty = tcx.type_of(tcx.hir.get_parent_did(node_id));
+            let inputs = fields.iter().map(|f| {
+                tcx.type_of(tcx.hir.local_def_id(f.id))
+            });
+            ty::Binder(tcx.mk_fn_sig(
+                inputs,
+                ty,
+                false,
+                hir::Unsafety::Normal,
+                abi::Abi::Rust
+            ))
+        }
+
+        NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => {
+            tcx.typeck_tables_of(def_id).closure_tys[&node_id]
+        }
+
+        x => {
+            bug!("unexpected sort of node in fn_sig(): {:?}", x);
+        }
+    }
+}
+
 fn impl_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             def_id: DefId)
                             -> Option<ty::TraitRef<'tcx>> {
@@ -1502,12 +1555,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
     }
 }
 
-fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
+fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
     decl: &hir::FnDecl,
     abi: abi::Abi)
-    -> Ty<'tcx>
+    -> ty::PolyFnSig<'tcx>
 {
     let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), hir::Unsafety::Unsafe, abi, decl);
 
@@ -1533,8 +1586,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
         }
     }
 
-    let substs = Substs::identity_for_item(tcx, def_id);
-    tcx.mk_fn_def(def_id, substs, fty)
+    fty
 }
 
 fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index bc5ba4c323d..37f6f3753d7 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -4208,6 +4208,104 @@ println!("{}", v[2]);
 ```
 "##,
 
+E0604: r##"
+A cast to `char` was attempted on a type other than `u8`.
+
+Erroneous code example:
+
+```compile_fail,E0604
+0u32 as char; // error: only `u8` can be cast as `char`, not `u32`
+```
+
+As the error message indicates, only `u8` can be cast into `char`. Example:
+
+```
+let c = 86u8 as char; // ok!
+assert_eq!(c, 'V');
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0605: r##"
+An invalid cast was attempted.
+
+Erroneous code examples:
+
+```compile_fail,E0605
+let x = 0u8;
+x as Vec<u8>; // error: non-primitive cast: `u8` as `std::vec::Vec<u8>`
+
+// Another example
+
+let v = 0 as *const u8; // So here, `v` is a `*const u8`.
+v as &u8; // error: non-primitive cast: `*const u8` as `&u8`
+```
+
+Only primitive types can be cast into each other. Examples:
+
+```
+let x = 0u8;
+x as u32; // ok!
+
+let v = 0 as *const u8;
+v as *const i8; // ok!
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0606: r##"
+An incompatible cast was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0606
+let x = &0u8; // Here, `x` is a `&u8`.
+let y: u32 = x as u32; // error: casting `&u8` as `u32` is invalid
+```
+
+When casting, keep in mind that only primitive types can be cast into each
+other. Example:
+
+```
+let x = &0u8;
+let y: u32 = *x as u32; // We dereference it first and then cast it.
+```
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
+E0607: r##"
+A cast between a thin and a fat pointer was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0607
+let v = 0 as *const u8;
+v as *const [u8];
+```
+
+First: what are thin and fat pointers?
+
+Thin pointers are "simple" pointers: they are purely a reference to a memory
+address.
+
+Fat pointers are pointers referencing Dynamically Sized Types (also called DST).
+DST don't have a statically known size, therefore they can only exist behind
+some kind of pointers that contain additional information. Slices and trait
+objects are DSTs. In the case of slices, the additional information the fat
+pointer holds is their size.
+
+To fix this error, don't try to cast directly between thin and fat pointers.
+
+For more information about casts, take a look at The Book:
+https://doc.rust-lang.org/book/first-edition/casting-between-types.html
+"##,
+
 E0609: r##"
 Attempted to access a non-existent field in a struct.
 
@@ -4567,6 +4665,87 @@ i_am_a_function();
 ```
 "##,
 
+E0619: r##"
+The type-checker needed to know the type of an expression, but that type had not
+yet been inferred.
+
+Erroneous code example:
+
+```compile_fail,E0619
+let mut x = vec![];
+match x.pop() {
+    Some(v) => {
+        // Here, the type of `v` is not (yet) known, so we
+        // cannot resolve this method call:
+        v.to_uppercase(); // error: the type of this value must be known in
+                          //        this context
+    }
+    None => {}
+}
+```
+
+Type inference typically proceeds from the top of the function to the bottom,
+figuring out types as it goes. In some cases -- notably method calls and
+overloadable operators like `*` -- the type checker may not have enough
+information *yet* to make progress. This can be true even if the rest of the
+function provides enough context (because the type-checker hasn't looked that
+far ahead yet). In this case, type annotations can be used to help it along.
+
+To fix this error, just specify the type of the variable. Example:
+
+```
+let mut x: Vec<String> = vec![]; // We precise the type of the vec elements.
+match x.pop() {
+    Some(v) => {
+        v.to_uppercase(); // Since rustc now knows the type of the vec elements,
+                          // we can use `v`'s methods.
+    }
+    None => {}
+}
+```
+"##,
+
+E0620: r##"
+A cast to an unsized type was attempted.
+
+Erroneous code example:
+
+```compile_fail,E0620
+let x = &[1_usize, 2] as [usize]; // error: cast to unsized type: `&[usize; 2]`
+                                  //        as `[usize]`
+```
+
+In Rust, some types don't have a known size at compile-time. For example, in a
+slice type like `[u32]`, the number of elements is not known at compile-time and
+hence the overall size cannot be computed. As a result, such types can only be
+manipulated through a reference (e.g., `&T` or `&mut T`) or other pointer-type
+(e.g., `Box` or `Rc`). Try casting to a reference instead:
+
+```
+let x = &[1_usize, 2] as &[usize]; // ok!
+```
+"##,
+
+E0622: r##"
+An intrinsic was declared without being a function.
+
+Erroneous code example:
+
+```compile_fail,E0622
+#![feature(intrinsics)]
+extern "rust-intrinsic" {
+    pub static breakpoint : unsafe extern "rust-intrinsic" fn();
+    // error: intrinsic must be a function
+}
+
+fn main() { unsafe { breakpoint(); } }
+```
+
+An intrinsic is a function available for use in a given programming language
+whose implementation is handled specially by the compiler. In order to fix this
+error, just declare a function.
+"##,
+
 }
 
 register_diagnostics! {
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 9e99af633d5..9b829e6e3ff 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -108,7 +108,7 @@ use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::traits::{FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
-use session::config;
+use session::{CompileIncomplete, config};
 use util::common::time;
 
 use syntax::ast;
@@ -166,7 +166,7 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         match fulfill_cx.select_all_or_error(infcx) {
             Ok(()) => true,
             Err(errors) => {
-                infcx.report_fulfillment_errors(&errors);
+                infcx.report_fulfillment_errors(&errors, None);
                 false
             }
         }
@@ -198,22 +198,21 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 }
                 _ => ()
             }
-            let substs = tcx.intern_substs(&[]);
-            let se_ty = tcx.mk_fn_def(main_def_id, substs,
-                ty::Binder(tcx.mk_fn_sig(
+            let se_ty = tcx.mk_fn_ptr(ty::Binder(
+                tcx.mk_fn_sig(
                     iter::empty(),
                     tcx.mk_nil(),
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust
-                ))
-            );
+                )
+            ));
 
             require_same_types(
                 tcx,
                 &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType),
                 se_ty,
-                main_t);
+                tcx.mk_fn_ptr(tcx.fn_sig(main_def_id)));
         }
         _ => {
             span_bug!(main_span,
@@ -248,9 +247,8 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 _ => ()
             }
 
-            let substs = tcx.intern_substs(&[]);
-            let se_ty = tcx.mk_fn_def(start_def_id, substs,
-                ty::Binder(tcx.mk_fn_sig(
+            let se_ty = tcx.mk_fn_ptr(ty::Binder(
+                tcx.mk_fn_sig(
                     [
                         tcx.types.isize,
                         tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
@@ -259,14 +257,14 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     false,
                     hir::Unsafety::Normal,
                     Abi::Rust
-                ))
-            );
+                )
+            ));
 
             require_same_types(
                 tcx,
                 &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType),
                 se_ty,
-                start_t);
+                tcx.mk_fn_ptr(tcx.fn_sig(start_def_id)));
         }
         _ => {
             span_bug!(start_span,
@@ -295,7 +293,8 @@ pub fn provide(providers: &mut Providers) {
 }
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                             -> Result<(), usize> {
+                             -> Result<(), CompileIncomplete>
+{
     let time_passes = tcx.sess.time_passes();
 
     // this ensures that later parts of type checking can assume that items
@@ -330,12 +329,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
 
-    let err_count = tcx.sess.err_count();
-    if err_count == 0 {
-        Ok(())
-    } else {
-        Err(err_count)
-    }
+    tcx.sess.compile_status()
 }
 
 /// A quasi-deprecated helper used in rustdoc and save-analysis to get
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index c434edb1c31..f4963619370 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -14,11 +14,9 @@
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use middle::resolve_lifetime as rl;
 use rustc::dep_graph::{AssertDepGraphSafe, DepKind};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::hir::map as hir_map;
 use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -61,10 +59,10 @@ pub struct Constraint<'a> {
 ///     }
 ///
 /// then while we are visiting `Bar<T>`, the `CurrentItem` would have
-/// the def-id and generics of `Foo`.
-pub struct CurrentItem<'a> {
+/// the def-id and the start of `Foo`'s inferreds.
+pub struct CurrentItem {
     def_id: DefId,
-    generics: &'a ty::Generics,
+    inferred_start: InferredIndex,
 }
 
 pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
@@ -91,8 +89,59 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
 
 impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
+        match item.node {
+            hir::ItemStruct(ref struct_def, _) |
+            hir::ItemUnion(ref struct_def, _) => {
+                self.visit_node_helper(item.id);
+
+                if let hir::VariantData::Tuple(..) = *struct_def {
+                    self.visit_node_helper(struct_def.id());
+                }
+            }
+
+            hir::ItemEnum(ref enum_def, _) => {
+                self.visit_node_helper(item.id);
+
+                for variant in &enum_def.variants {
+                    if let hir::VariantData::Tuple(..) = variant.node.data {
+                        self.visit_node_helper(variant.node.data.id());
+                    }
+                }
+            }
+
+            hir::ItemFn(..) => {
+                self.visit_node_helper(item.id);
+            }
+
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if let hir::ForeignItemFn(..) = foreign_item.node {
+                        self.visit_node_helper(foreign_item.id);
+                    }
+                }
+            }
+
+            _ => {}
+        }
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(..) = trait_item.node {
+            self.visit_node_helper(trait_item.id);
+        }
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+        if let hir::ImplItemKind::Method(..) = impl_item.node {
+            self.visit_node_helper(impl_item.id);
+        }
+    }
+}
+
+impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
+    fn visit_node_helper(&mut self, id: ast::NodeId) {
         let tcx = self.terms_cx.tcx;
-        let def_id = tcx.hir.local_def_id(item.id);
+        let def_id = tcx.hir.local_def_id(id);
 
         // Encapsulate constructing the constraints into a task we can
         // reference later. This can go away once the red-green
@@ -100,20 +149,11 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
         //
         // See README.md for a detailed discussion
         // on dep-graph management.
-        match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemUnion(..) => {
-                let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-                tcx.dep_graph.with_task(dep_node,
-                                        AssertDepGraphSafe(self),
-                                        def_id,
-                                        visit_item_task);
-            }
-            _ => {
-                // Nothing to do here, skip the task.
-            }
-        }
+        let dep_node = def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+        tcx.dep_graph.with_task(dep_node,
+                                AssertDepGraphSafe(self),
+                                def_id,
+                                visit_item_task);
 
         fn visit_item_task<'a, 'tcx>(ccx: AssertDepGraphSafe<&mut ConstraintContext<'a, 'tcx>>,
                                      def_id: DefId)
@@ -122,197 +162,57 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> {
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-    }
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-    }
-}
-
-/// Is `param_id` a lifetime according to `map`?
-fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool {
-    match map.find(param_id) {
-        Some(hir_map::NodeLifetime(..)) => true,
-        _ => false,
-    }
-}
-
-impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.terms_cx.tcx
     }
 
     fn build_constraints_for_item(&mut self, def_id: DefId) {
         let tcx = self.tcx();
-        let id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-        let item = tcx.hir.expect_item(id);
-        debug!("visit_item item={}", tcx.hir.node_to_string(item.id));
+        debug!("build_constraints_for_item({})", tcx.item_path_str(def_id));
 
-        match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemUnion(..) => {
-                let generics = tcx.generics_of(def_id);
-                let current_item = &CurrentItem { def_id, generics };
+        // Skip items with no generics - there's nothing to infer in them.
+        if tcx.generics_of(def_id).count() == 0 {
+            return;
+        }
 
+        let id = tcx.hir.as_local_node_id(def_id).unwrap();
+        let inferred_start = self.terms_cx.inferred_starts[&id];
+        let current_item = &CurrentItem { def_id, inferred_start };
+        match tcx.type_of(def_id).sty {
+            ty::TyAdt(def, _) => {
                 // Not entirely obvious: constraints on structs/enums do not
                 // affect the variance of their type parameters. See discussion
                 // in comment at top of module.
                 //
                 // self.add_constraints_from_generics(generics);
 
-                for field in tcx.adt_def(def_id).all_fields() {
+                for field in def.all_fields() {
                     self.add_constraints_from_ty(current_item,
                                                  tcx.type_of(field.did),
                                                  self.covariant);
                 }
             }
 
-            hir::ItemTrait(..) |
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(..) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemGlobalAsm(..) |
-            hir::ItemTy(..) |
-            hir::ItemImpl(..) |
-            hir::ItemDefaultImpl(..) => {
-                span_bug!(item.span, "`build_constraints_for_item` invoked for non-type-def");
+            ty::TyFnDef(..) => {
+                self.add_constraints_from_sig(current_item,
+                                              tcx.fn_sig(def_id),
+                                              self.covariant);
             }
-        }
-    }
-
-    /// Load the generics for another item, adding a corresponding
-    /// relation into the dependencies to indicate that the variance
-    /// for `current` relies on `def_id`.
-    fn read_generics(&mut self, current: &CurrentItem, def_id: DefId) -> &'tcx ty::Generics {
-        let generics = self.tcx().generics_of(def_id);
-        if self.tcx().dep_graph.is_fully_enabled() {
-            self.dependencies.add(current.def_id, def_id);
-        }
-        generics
-    }
 
-    fn opt_inferred_index(&self, param_id: ast::NodeId) -> Option<&InferredIndex> {
-        self.terms_cx.inferred_map.get(&param_id)
-    }
-
-    fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
-        let tcx = self.terms_cx.tcx;
-        assert!(is_lifetime(&tcx.hir, param_id));
-        match tcx.named_region_map.defs.get(&param_id) {
-            Some(&rl::Region::EarlyBound(_, lifetime_decl_id)) => lifetime_decl_id,
-            Some(_) => bug!("should not encounter non early-bound cases"),
-
-            // The lookup should only fail when `param_id` is
-            // itself a lifetime binding: use it as the decl_id.
-            None => param_id,
-        }
-
-    }
-
-    /// Is `param_id` a type parameter for which we infer variance?
-    fn is_to_be_inferred(&self, param_id: ast::NodeId) -> bool {
-        let result = self.terms_cx.inferred_map.contains_key(&param_id);
-
-        // To safe-guard against invalid inferred_map constructions,
-        // double-check if variance is inferred at some use of a type
-        // parameter (by inspecting parent of its binding declaration
-        // to see if it is introduced by a type or by a fn/impl).
-
-        let check_result = |this: &ConstraintContext| -> bool {
-            let tcx = this.terms_cx.tcx;
-            let decl_id = this.find_binding_for_lifetime(param_id);
-            // Currently only called on lifetimes; double-checking that.
-            assert!(is_lifetime(&tcx.hir, param_id));
-            let parent_id = tcx.hir.get_parent(decl_id);
-            let parent = tcx.hir
-                .find(parent_id)
-                .unwrap_or_else(|| bug!("tcx.hir missing entry for id: {}", parent_id));
-
-            let is_inferred;
-            macro_rules! cannot_happen { () => { {
-                bug!("invalid parent: {} for {}",
-                     tcx.hir.node_to_string(parent_id),
-                     tcx.hir.node_to_string(param_id));
-            } } }
-
-            match parent {
-                hir_map::NodeItem(p) => {
-                    match p.node {
-                        hir::ItemTy(..) |
-                        hir::ItemEnum(..) |
-                        hir::ItemStruct(..) |
-                        hir::ItemUnion(..) |
-                        hir::ItemTrait(..) => is_inferred = true,
-                        hir::ItemFn(..) => is_inferred = false,
-                        _ => cannot_happen!(),
-                    }
-                }
-                hir_map::NodeTraitItem(..) => is_inferred = false,
-                hir_map::NodeImplItem(..) => is_inferred = false,
-                _ => cannot_happen!(),
-            }
-
-            return is_inferred;
-        };
-
-        assert_eq!(result, check_result(self));
-
-        return result;
-    }
-
-    /// Returns a variance term representing the declared variance of the type/region parameter
-    /// with the given id.
-    fn declared_variance(&self,
-                         param_def_id: DefId,
-                         item_def_id: DefId,
-                         index: usize)
-                         -> VarianceTermPtr<'a> {
-        assert_eq!(param_def_id.krate, item_def_id.krate);
-
-        if let Some(param_node_id) = self.tcx().hir.as_local_node_id(param_def_id) {
-            // Parameter on an item defined within current crate:
-            // variance not yet inferred, so return a symbolic
-            // variance.
-            if let Some(&InferredIndex(index)) = self.opt_inferred_index(param_node_id) {
-                self.terms_cx.inferred_infos[index].term
-            } else {
-                // If there is no inferred entry for a type parameter,
-                // it must be declared on a (locally defiend) trait -- they don't
-                // get inferreds because they are always invariant.
-                if cfg!(debug_assertions) {
-                    let item_node_id = self.tcx().hir.as_local_node_id(item_def_id).unwrap();
-                    let item = self.tcx().hir.expect_item(item_node_id);
-                    let success = match item.node {
-                        hir::ItemTrait(..) => true,
-                        _ => false,
-                    };
-                    if !success {
-                        bug!("parameter {:?} has no inferred, but declared on non-trait: {:?}",
-                             item_def_id,
-                             item);
-                    }
-                }
-                self.invariant
+            _ => {
+                span_bug!(tcx.def_span(def_id),
+                          "`build_constraints_for_item` unsupported for this item");
             }
-        } else {
-            // Parameter on an item defined within another crate:
-            // variance already inferred, just look it up.
-            let variances = self.tcx().variances_of(item_def_id);
-            self.constant_term(variances[index])
         }
     }
 
     fn add_constraint(&mut self,
-                      InferredIndex(index): InferredIndex,
+                      current: &CurrentItem,
+                      index: u32,
                       variance: VarianceTermPtr<'a>) {
         debug!("add_constraint(index={}, variance={:?})", index, variance);
         self.constraints.push(Constraint {
-            inferred: InferredIndex(index),
+            inferred: InferredIndex(current.inferred_start.0 + index as usize),
             variance: variance,
         });
     }
@@ -354,15 +254,26 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
                trait_ref,
                variance);
+        self.add_constraints_from_invariant_substs(current, trait_ref.substs, variance);
+    }
 
-        let trait_generics = self.tcx().generics_of(trait_ref.def_id);
+    fn add_constraints_from_invariant_substs(&mut self,
+                                             current: &CurrentItem,
+                                             substs: &Substs<'tcx>,
+                                             variance: VarianceTermPtr<'a>) {
+        debug!("add_constraints_from_invariant_substs: substs={:?} variance={:?}",
+               substs,
+               variance);
 
-        self.add_constraints_from_substs(current,
-                                         trait_ref.def_id,
-                                         &trait_generics.types,
-                                         &trait_generics.regions,
-                                         trait_ref.substs,
-                                         variance);
+        // Trait are always invariant so we can take advantage of that.
+        let variance_i = self.invariant(variance);
+        for ty in substs.types() {
+            self.add_constraints_from_ty(current, ty, variance_i);
+        }
+
+        for region in substs.regions() {
+            self.add_constraints_from_region(current, region, variance_i);
+        }
     }
 
     /// Adds constraints appropriate for an instance of `ty` appearing
@@ -382,8 +293,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 // leaf type -- noop
             }
 
-            ty::TyClosure(..) |
-            ty::TyAnon(..) => {
+            ty::TyFnDef(..) |
+            ty::TyClosure(..) => {
                 bug!("Unexpected closure type in variance computation");
             }
 
@@ -409,26 +320,15 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             }
 
             ty::TyAdt(def, substs) => {
-                let adt_generics = self.read_generics(current, def.did);
-
-                self.add_constraints_from_substs(current,
-                                                 def.did,
-                                                 &adt_generics.types,
-                                                 &adt_generics.regions,
-                                                 substs,
-                                                 variance);
+                self.add_constraints_from_substs(current, def.did, substs, variance);
             }
 
             ty::TyProjection(ref data) => {
-                let trait_ref = &data.trait_ref;
-                let trait_generics = self.tcx().generics_of(trait_ref.def_id);
-
-                self.add_constraints_from_substs(current,
-                                                 trait_ref.def_id,
-                                                 &trait_generics.types,
-                                                 &trait_generics.regions,
-                                                 trait_ref.substs,
-                                                 variance);
+                self.add_constraints_from_trait_ref(current, data.trait_ref, variance);
+            }
+
+            ty::TyAnon(_, substs) => {
+                self.add_constraints_from_invariant_substs(current, substs, variance);
             }
 
             ty::TyDynamic(ref data, r) => {
@@ -447,26 +347,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             }
 
             ty::TyParam(ref data) => {
-                assert_eq!(current.generics.parent, None);
-                let mut i = data.idx as usize;
-                if !current.generics.has_self || i > 0 {
-                    i -= current.generics.regions.len();
-                }
-                let def_id = current.generics.types[i].def_id;
-                let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-                match self.terms_cx.inferred_map.get(&node_id) {
-                    Some(&index) => {
-                        self.add_constraint(index, variance);
-                    }
-                    None => {
-                        // We do not infer variance for type parameters
-                        // declared on methods. They will not be present
-                        // in the inferred_map.
-                    }
-                }
+                self.add_constraint(current, data.idx, variance);
             }
 
-            ty::TyFnDef(.., sig) |
             ty::TyFnPtr(sig) => {
                 self.add_constraints_from_sig(current, sig, variance);
             }
@@ -489,8 +372,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     fn add_constraints_from_substs(&mut self,
                                    current: &CurrentItem,
                                    def_id: DefId,
-                                   type_param_defs: &[ty::TypeParameterDef],
-                                   region_param_defs: &[ty::RegionParameterDef],
                                    substs: &Substs<'tcx>,
                                    variance: VarianceTermPtr<'a>) {
         debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
@@ -498,21 +379,45 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                substs,
                variance);
 
-        for p in type_param_defs {
-            let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
+        // We don't record `inferred_starts` entries for empty generics.
+        if substs.is_empty() {
+            return;
+        }
+
+        // Add a corresponding relation into the dependencies to
+        // indicate that the variance for `current` relies on `def_id`.
+        if self.tcx().dep_graph.is_fully_enabled() {
+            self.dependencies.add(current.def_id, def_id);
+        }
+
+        let (local, remote) = if let Some(id) = self.tcx().hir.as_local_node_id(def_id) {
+            (Some(self.terms_cx.inferred_starts[&id]), None)
+        } else {
+            (None, Some(self.tcx().variances_of(def_id)))
+        };
+
+        for (i, k) in substs.iter().enumerate() {
+            let variance_decl = if let Some(InferredIndex(start)) = local {
+                // Parameter on an item defined within current crate:
+                // variance not yet inferred, so return a symbolic
+                // variance.
+                self.terms_cx.inferred_terms[start + i]
+            } else {
+                // Parameter on an item defined within another crate:
+                // variance already inferred, just look it up.
+                self.constant_term(remote.as_ref().unwrap()[i])
+            };
             let variance_i = self.xform(variance, variance_decl);
-            let substs_ty = substs.type_for_def(p);
             debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
                    variance_decl,
                    variance_i);
-            self.add_constraints_from_ty(current, substs_ty, variance_i);
-        }
-
-        for p in region_param_defs {
-            let variance_decl = self.declared_variance(p.def_id, def_id, p.index as usize);
-            let variance_i = self.xform(variance, variance_decl);
-            let substs_r = substs.region_for_def(p);
-            self.add_constraints_from_region(current, substs_r, variance_i);
+            if let Some(ty) = k.as_type() {
+                self.add_constraints_from_ty(current, ty, variance_i);
+            } else if let Some(r) = k.as_region() {
+                self.add_constraints_from_region(current, r, variance_i);
+            } else {
+                bug!();
+            }
         }
     }
 
@@ -537,21 +442,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                    variance: VarianceTermPtr<'a>) {
         match *region {
             ty::ReEarlyBound(ref data) => {
-                assert_eq!(current.generics.parent, None);
-                let i = data.index as usize - current.generics.has_self as usize;
-                let def_id = current.generics.regions[i].def_id;
-                let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-                if self.is_to_be_inferred(node_id) {
-                    let &index = self.opt_inferred_index(node_id).unwrap();
-                    self.add_constraint(index, variance);
-                }
+                self.add_constraint(current, data.index, variance);
             }
 
             ty::ReStatic => {}
 
             ty::ReLateBound(..) => {
-                // We do not infer variance for region parameters on
-                // methods or in fn types.
+                // Late-bound regions do not get substituted the same
+                // way early-bound regions do, so we skip them here.
             }
 
             ty::ReFree(..) |
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index 8f9f40ca40b..7a9f35545e2 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -54,45 +54,63 @@ fn crate_variances<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum)
 
 fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId)
                             -> Rc<Vec<ty::Variance>> {
-    let item_id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
-    let item = tcx.hir.expect_item(item_id);
-    match item.node {
-        hir::ItemTrait(..) => {
-            // Traits are always invariant.
-            let generics = tcx.generics_of(item_def_id);
-            assert!(generics.parent.is_none());
-            Rc::new(vec![ty::Variance::Invariant; generics.count()])
-        }
+    let id = tcx.hir.as_local_node_id(item_def_id).expect("expected local def-id");
+    let unsupported = || {
+        // Variance not relevant.
+        span_bug!(tcx.hir.span(id), "asked to compute variance for wrong kind of item")
+    };
+    match tcx.hir.get(id) {
+        hir::map::NodeItem(item) => match item.node {
+            hir::ItemEnum(..) |
+            hir::ItemStruct(..) |
+            hir::ItemUnion(..) |
+            hir::ItemFn(..) => {}
 
-        hir::ItemEnum(..) |
-        hir::ItemStruct(..) |
-        hir::ItemUnion(..) => {
-            // Everything else must be inferred.
+            _ => unsupported()
+        },
 
-            // Lacking red/green, we read the variances for all items here
-            // but ignore the dependencies, then re-synthesize the ones we need.
-            let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
-            let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-            tcx.dep_graph.read(dep_node);
-            for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
-                if dep_def_id.is_local() {
-                    let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
-                    tcx.dep_graph.read(dep_node);
-                } else {
-                    let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
-                    tcx.dep_graph.read(dep_node);
-                }
-            }
-
-            crate_map.variances.get(&item_def_id)
-                               .unwrap_or(&crate_map.empty_variance)
-                               .clone()
-        }
+        hir::map::NodeTraitItem(item) => match item.node {
+            hir::TraitItemKind::Method(..) => {}
+
+            _ => unsupported()
+        },
+
+        hir::map::NodeImplItem(item) => match item.node {
+            hir::ImplItemKind::Method(..) => {}
+
+            _ => unsupported()
+        },
+
+        hir::map::NodeForeignItem(item) => match item.node {
+            hir::ForeignItemFn(..) => {}
 
-        _ => {
-            // Variance not relevant.
-            span_bug!(item.span, "asked to compute variance for wrong kind of item")
+            _ => unsupported()
+        },
+
+        hir::map::NodeVariant(_) | hir::map::NodeStructCtor(_) => {}
+
+        _ => unsupported()
+    }
+
+    // Everything else must be inferred.
+
+    // Lacking red/green, we read the variances for all items here
+    // but ignore the dependencies, then re-synthesize the ones we need.
+    let crate_map = tcx.dep_graph.with_ignore(|| tcx.crate_variances(LOCAL_CRATE));
+    let dep_node = item_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+    tcx.dep_graph.read(dep_node);
+    for &dep_def_id in crate_map.dependencies.less_than(&item_def_id) {
+        if dep_def_id.is_local() {
+            let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVarianceConstraints);
+            tcx.dep_graph.read(dep_node);
+        } else {
+            let dep_node = dep_def_id.to_dep_node(tcx, DepKind::ItemVariances);
+            tcx.dep_graph.read(dep_node);
         }
     }
+
+    crate_map.variances.get(&item_def_id)
+                       .unwrap_or(&crate_map.empty_variance)
+                       .clone()
 }
 
diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs
index af8ad491ec0..495eb95419a 100644
--- a/src/librustc_typeck/variance/solve.rs
+++ b/src/librustc_typeck/variance/solve.rs
@@ -36,15 +36,18 @@ struct SolveContext<'a, 'tcx: 'a> {
 pub fn solve_constraints(constraints_cx: ConstraintContext) -> ty::CrateVariancesMap {
     let ConstraintContext { terms_cx, dependencies, constraints, .. } = constraints_cx;
 
-    let solutions = terms_cx.inferred_infos
-        .iter()
-        .map(|ii| ii.initial_variance)
-        .collect();
+    let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()];
+    for &(id, ref variances) in &terms_cx.lang_items {
+        let InferredIndex(start) = terms_cx.inferred_starts[&id];
+        for (i, &variance) in variances.iter().enumerate() {
+            solutions[start + i] = variance;
+        }
+    }
 
     let mut solutions_cx = SolveContext {
-        terms_cx: terms_cx,
-        constraints: constraints,
-        solutions: solutions,
+        terms_cx,
+        constraints,
+        solutions,
     };
     solutions_cx.solve();
     let variances = solutions_cx.create_map();
@@ -71,12 +74,9 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
                 let old_value = self.solutions[inferred];
                 let new_value = glb(variance, old_value);
                 if old_value != new_value {
-                    debug!("Updating inferred {} (node {}) \
+                    debug!("Updating inferred {} \
                             from {:?} to {:?} due to {:?}",
                            inferred,
-                           self.terms_cx
-                                   .inferred_infos[inferred]
-                               .param_id,
                            old_value,
                            new_value,
                            term);
@@ -89,49 +89,28 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
     }
 
     fn create_map(&self) -> FxHashMap<DefId, Rc<Vec<ty::Variance>>> {
-        // Collect all the variances for a particular item and stick
-        // them into the variance map. We rely on the fact that we
-        // generate all the inferreds for a particular item
-        // consecutively (that is, we collect solutions for an item
-        // until we see a new item id, and we assume (1) the solutions
-        // are in the same order as the type parameters were declared
-        // and (2) all solutions or a given item appear before a new
-        // item id).
-
         let tcx = self.terms_cx.tcx;
 
-        let mut map = FxHashMap();
-
         let solutions = &self.solutions;
-        let inferred_infos = &self.terms_cx.inferred_infos;
-        let mut index = 0;
-        let num_inferred = self.terms_cx.num_inferred();
-        while index < num_inferred {
-            let item_id = inferred_infos[index].item_id;
-
-            let mut item_variances = vec![];
-
-            while index < num_inferred && inferred_infos[index].item_id == item_id {
-                let info = &inferred_infos[index];
-                let variance = solutions[index];
-                debug!("Index {} Info {} Variance {:?}",
-                       index,
-                       info.index,
-                       variance);
-
-                assert_eq!(item_variances.len(), info.index);
-                item_variances.push(variance);
-                index += 1;
-            }
+        self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
+            let def_id = tcx.hir.local_def_id(id);
+            let generics = tcx.generics_of(def_id);
 
-            debug!("item_id={} item_variances={:?}", item_id, item_variances);
+            let mut variances = solutions[start..start+generics.count()].to_vec();
 
-            let item_def_id = tcx.hir.local_def_id(item_id);
+            debug!("id={} variances={:?}", id, variances);
 
-            map.insert(item_def_id, Rc::new(item_variances));
-        }
+            // Functions can have unused type parameters: make those invariant.
+            if let ty::TyFnDef(..) = tcx.type_of(def_id).sty {
+                for variance in &mut variances {
+                    if *variance == ty::Bivariant {
+                        *variance = ty::Invariant;
+                    }
+                }
+            }
 
-        map
+            (def_id, Rc::new(variances))
+        }).collect()
     }
 
     fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index ad787c57e76..38457146a97 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -22,7 +22,6 @@
 use arena::TypedArena;
 use rustc::ty::{self, TyCtxt};
 use std::fmt;
-use std::rc::Rc;
 use syntax::ast;
 use rustc::hir;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
@@ -63,31 +62,17 @@ pub struct TermsContext<'a, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub arena: &'a TypedArena<VarianceTerm<'a>>,
 
-    pub empty_variances: Rc<Vec<ty::Variance>>,
-
     // For marker types, UnsafeCell, and other lang items where
     // variance is hardcoded, records the item-id and the hardcoded
     // variance.
     pub lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
 
-    // Maps from the node id of a type/generic parameter to the
-    // corresponding inferred index.
-    pub inferred_map: NodeMap<InferredIndex>,
-
-    // Maps from an InferredIndex to the info for that variable.
-    pub inferred_infos: Vec<InferredInfo<'a>>,
-}
-
-pub struct InferredInfo<'a> {
-    pub item_id: ast::NodeId,
-    pub index: usize,
-    pub param_id: ast::NodeId,
-    pub term: VarianceTermPtr<'a>,
+    // Maps from the node id of an item to the first inferred index
+    // used for its type & region parameters.
+    pub inferred_starts: NodeMap<InferredIndex>,
 
-    // Initial value to use for this parameter when inferring
-    // variance. For most parameters, this is Bivariant. But for lang
-    // items and input type parameters on traits, it is different.
-    pub initial_variance: ty::Variance,
+    // Maps from an InferredIndex to the term for that variable.
+    pub inferred_terms: Vec<VarianceTermPtr<'a>>,
 }
 
 pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -96,14 +81,10 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
     let mut terms_cx = TermsContext {
         tcx: tcx,
         arena: arena,
-        inferred_map: NodeMap(),
-        inferred_infos: Vec::new(),
+        inferred_starts: NodeMap(),
+        inferred_terms: vec![],
 
         lang_items: lang_items(tcx),
-
-        // cache and share the variance struct used for items with
-        // no type/region parameters
-        empty_variances: Rc::new(vec![]),
     };
 
     // See README.md for a discussion on dep-graph management.
@@ -135,67 +116,28 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec<ty::Variance>)> {
 }
 
 impl<'a, 'tcx> TermsContext<'a, 'tcx> {
-    fn add_inferreds_for_item(&mut self,
-                              item_id: ast::NodeId,
-                              generics: &hir::Generics) {
-        //! Add "inferreds" for the generic parameters declared on this
-        //! item. This has a lot of annoying parameters because we are
-        //! trying to drive this from the AST, rather than the
-        //! ty::Generics, so that we can get span info -- but this
-        //! means we must accommodate syntactic distinctions.
-        //!
+    fn add_inferreds_for_item(&mut self, id: ast::NodeId) {
+        let tcx = self.tcx;
+        let def_id = tcx.hir.local_def_id(id);
+        let count = tcx.generics_of(def_id).count();
 
-        // NB: In the code below for writing the results back into the
-        // `CrateVariancesMap`, we rely on the fact that all inferreds
-        // for a particular item are assigned continuous indices.
-
-        for (p, i) in generics.lifetimes.iter().zip(0..) {
-            let id = p.lifetime.id;
-            self.add_inferred(item_id, i, id);
-        }
-
-        for (p, i) in generics.ty_params.iter().zip(generics.lifetimes.len()..) {
-            self.add_inferred(item_id, i, p.id);
+        if count == 0 {
+            return;
         }
-    }
 
-    fn add_inferred(&mut self, item_id: ast::NodeId, index: usize, param_id: ast::NodeId) {
-        let inf_index = InferredIndex(self.inferred_infos.len());
-        let term = self.arena.alloc(InferredTerm(inf_index));
-        let initial_variance = self.pick_initial_variance(item_id, index);
-        self.inferred_infos.push(InferredInfo {
-            item_id: item_id,
-            index: index,
-            param_id: param_id,
-            term: term,
-            initial_variance: initial_variance,
-        });
-        let newly_added = self.inferred_map.insert(param_id, inf_index).is_none();
+        // Record the start of this item's inferreds.
+        let start = self.inferred_terms.len();
+        let newly_added = self.inferred_starts.insert(id, InferredIndex(start)).is_none();
         assert!(newly_added);
 
-        debug!("add_inferred(item_path={}, \
-                item_id={}, \
-                index={}, \
-                param_id={}, \
-                inf_index={:?}, \
-                initial_variance={:?})",
-               self.tcx.item_path_str(self.tcx.hir.local_def_id(item_id)),
-               item_id,
-               index,
-               param_id,
-               inf_index,
-               initial_variance);
-    }
-
-    fn pick_initial_variance(&self, item_id: ast::NodeId, index: usize) -> ty::Variance {
-        match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
-            Some(&(_, ref variances)) => variances[index],
-            None => ty::Bivariant,
-        }
-    }
+        // NB: In the code below for writing the results back into the
+        // `CrateVariancesMap`, we rely on the fact that all inferreds
+        // for a particular item are assigned continuous indices.
 
-    pub fn num_inferred(&self) -> usize {
-        self.inferred_infos.len()
+        let arena = self.arena;
+        self.inferred_terms.extend((start..start+count).map(|i| {
+            &*arena.alloc(InferredTerm(InferredIndex(i)))
+        }));
     }
 }
 
@@ -205,30 +147,50 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> {
                self.tcx.hir.node_to_string(item.id));
 
         match item.node {
-            hir::ItemEnum(_, ref generics) |
-            hir::ItemStruct(_, ref generics) |
-            hir::ItemUnion(_, ref generics) => {
-                self.add_inferreds_for_item(item.id, generics);
+            hir::ItemStruct(ref struct_def, _) |
+            hir::ItemUnion(ref struct_def, _) => {
+                self.add_inferreds_for_item(item.id);
+
+                if let hir::VariantData::Tuple(..) = *struct_def {
+                    self.add_inferreds_for_item(struct_def.id());
+                }
+            }
+
+            hir::ItemEnum(ref enum_def, _) => {
+                self.add_inferreds_for_item(item.id);
+
+                for variant in &enum_def.variants {
+                    if let hir::VariantData::Tuple(..) = variant.node.data {
+                        self.add_inferreds_for_item(variant.node.data.id());
+                    }
+                }
+            }
+
+            hir::ItemFn(..) => {
+                self.add_inferreds_for_item(item.id);
             }
 
-            hir::ItemTrait(..) |
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(..) |
-            hir::ItemDefaultImpl(..) |
-            hir::ItemImpl(..) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemGlobalAsm(..) |
-            hir::ItemTy(..) => {}
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if let hir::ForeignItemFn(..) = foreign_item.node {
+                        self.add_inferreds_for_item(foreign_item.id);
+                    }
+                }
+            }
+
+            _ => {}
         }
     }
 
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
+        if let hir::TraitItemKind::Method(..) = trait_item.node {
+            self.add_inferreds_for_item(trait_item.id);
+        }
     }
 
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
+        if let hir::ImplItemKind::Method(..) = impl_item.node {
+            self.add_inferreds_for_item(impl_item.id);
+        }
     }
 }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index aeade470482..fa5a999adf1 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -149,7 +149,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
 }
 
 fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function {
-    let sig = cx.tcx.type_of(did).fn_sig();
+    let sig = cx.tcx.fn_sig(did);
 
     let constness = if cx.tcx.is_const_fn(did) {
         hir::Constness::Const
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 8fc8ccd0cfd..478e2fc5085 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1367,7 +1367,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
             ty::AssociatedKind::Method => {
                 let generics = (cx.tcx.generics_of(self.def_id),
                                 &cx.tcx.predicates_of(self.def_id)).clean(cx);
-                let sig = cx.tcx.type_of(self.def_id).fn_sig();
+                let sig = cx.tcx.fn_sig(self.def_id);
                 let mut decl = (self.def_id, sig).clean(cx);
 
                 if self.method_has_self_argument {
@@ -1842,17 +1842,21 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 mutability: mt.mutbl.clean(cx),
                 type_: box mt.ty.clean(cx),
             },
-            ty::TyFnDef(.., sig) |
-            ty::TyFnPtr(sig) => BareFunction(box BareFunctionDecl {
-                unsafety: sig.unsafety(),
-                generics: Generics {
-                    lifetimes: Vec::new(),
-                    type_params: Vec::new(),
-                    where_predicates: Vec::new()
-                },
-                decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
-                abi: sig.abi(),
-            }),
+            ty::TyFnDef(..) |
+            ty::TyFnPtr(_) => {
+                let ty = cx.tcx.lift(self).unwrap();
+                let sig = ty.fn_sig(cx.tcx);
+                BareFunction(box BareFunctionDecl {
+                    unsafety: sig.unsafety(),
+                    generics: Generics {
+                        lifetimes: Vec::new(),
+                        type_params: Vec::new(),
+                        where_predicates: Vec::new()
+                    },
+                    decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx),
+                    abi: sig.abi(),
+                })
+            }
             ty::TyAdt(def, substs) => {
                 let did = def.did;
                 let kind = match def.adt_kind() {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 635691dd345..766e76137ca 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1019,7 +1019,11 @@ impl fmt::Display for clean::Import {
                 }
             }
             clean::Import::Glob(ref src) => {
-                write!(f, "use {}::*;", *src)
+                if src.path.segments.is_empty() {
+                    write!(f, "use *;")
+                } else {
+                    write!(f, "use {}::*;", *src)
+                }
             }
         }
     }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 1f8c88d8ecf..89a40b0db96 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -300,7 +300,7 @@ impl<'a> Classifier<'a> {
                     "Some" | "None" | "Ok" | "Err" => Class::PreludeVal,
 
                     "$crate" => Class::KeyWord,
-                    _ if tas.tok.is_any_keyword() => Class::KeyWord,
+                    _ if tas.tok.is_reserved_ident() => Class::KeyWord,
 
                     _ => {
                         if self.in_macro_nonterminal {
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index bea13397eca..03da451fd9a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -769,7 +769,7 @@ pub fn old_find_testable_code(doc: &str, tests: &mut ::test::Collector, position
                                block_info.should_panic, block_info.no_run,
                                block_info.ignore, block_info.test_harness,
                                block_info.compile_fail, block_info.error_codes,
-                               line, filename);
+                               line, filename, block_info.allow_fail);
             } else {
                 tests.add_old_test(text, filename);
             }
@@ -859,7 +859,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
                                block_info.should_panic, block_info.no_run,
                                block_info.ignore, block_info.test_harness,
                                block_info.compile_fail, block_info.error_codes,
-                               line, filename);
+                               line, filename, block_info.allow_fail);
                 prev_offset = offset;
             }
             Event::Start(Tag::Header(level)) => {
@@ -889,6 +889,7 @@ struct LangString {
     test_harness: bool,
     compile_fail: bool,
     error_codes: Vec<String>,
+    allow_fail: bool,
 }
 
 impl LangString {
@@ -902,6 +903,7 @@ impl LangString {
             test_harness: false,
             compile_fail: false,
             error_codes: Vec::new(),
+            allow_fail: false,
         }
     }
 
@@ -930,6 +932,7 @@ impl LangString {
                 }
                 "no_run" => { data.no_run = true; seen_rust_tags = !seen_other_tags; }
                 "ignore" => { data.ignore = true; seen_rust_tags = !seen_other_tags; }
+                "allow_fail" => { data.allow_fail = true; seen_rust_tags = !seen_other_tags; }
                 "rust" => { data.rust = true; seen_rust_tags = true; }
                 "test_harness" => {
                     data.test_harness = true;
@@ -1118,7 +1121,7 @@ mod tests {
     fn test_lang_string_parse() {
         fn t(s: &str,
             should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
-            compile_fail: bool, error_codes: Vec<String>) {
+            compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) {
             assert_eq!(LangString::parse(s), LangString {
                 should_panic: should_panic,
                 no_run: no_run,
@@ -1128,25 +1131,31 @@ mod tests {
                 compile_fail: compile_fail,
                 error_codes: error_codes,
                 original: s.to_owned(),
+                allow_fail: allow_fail,
             })
         }
 
+        fn v() -> Vec<String> {
+            Vec::new()
+        }
+
         // marker                | should_panic| no_run| ignore| rust | test_harness| compile_fail
-        //                       | error_codes
-        t("",                      false,        false,  false,  true,  false, false, Vec::new());
-        t("rust",                  false,        false,  false,  true,  false, false, Vec::new());
-        t("sh",                    false,        false,  false,  false, false, false, Vec::new());
-        t("ignore",                false,        false,  true,   true,  false, false, Vec::new());
-        t("should_panic",          true,         false,  false,  true,  false, false, Vec::new());
-        t("no_run",                false,        true,   false,  true,  false, false, Vec::new());
-        t("test_harness",          false,        false,  false,  true,  true,  false, Vec::new());
-        t("compile_fail",          false,        true,   false,  true,  false, true,  Vec::new());
-        t("{.no_run .example}",    false,        true,   false,  true,  false, false, Vec::new());
-        t("{.sh .should_panic}",   true,         false,  false,  false, false, false, Vec::new());
-        t("{.example .rust}",      false,        false,  false,  true,  false, false, Vec::new());
-        t("{.test_harness .rust}", false,        false,  false,  true,  true,  false, Vec::new());
-        t("text, no_run",          false,        true,   false,  false, false, false, Vec::new());
-        t("text,no_run",           false,        true,   false,  false, false, false, Vec::new());
+        //                       | allow_fail | error_codes
+        t("",                      false,        false,  false,  true,  false, false, false, v());
+        t("rust",                  false,        false,  false,  true,  false, false, false, v());
+        t("sh",                    false,        false,  false,  false, false, false, false, v());
+        t("ignore",                false,        false,  true,   true,  false, false, false, v());
+        t("should_panic",          true,         false,  false,  true,  false, false, false, v());
+        t("no_run",                false,        true,   false,  true,  false, false, false, v());
+        t("test_harness",          false,        false,  false,  true,  true,  false, false, v());
+        t("compile_fail",          false,        true,   false,  true,  false, true,  false, v());
+        t("allow_fail",            false,        false,  false,  true,  false, false, true,  v());
+        t("{.no_run .example}",    false,        true,   false,  true,  false, false, false, v());
+        t("{.sh .should_panic}",   true,         false,  false,  false, false, false, false, v());
+        t("{.example .rust}",      false,        false,  false,  true,  false, false, false, v());
+        t("{.test_harness .rust}", false,        false,  false,  true,  true,  false, false, v());
+        t("text, no_run",          false,        true,   false,  false, false, false, false, v());
+        t("text,no_run",           false,        true,   false,  false, false, false, false, v());
     }
 
     #[test]
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index cfe2fad0fa4..f012fd974b5 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -25,7 +25,7 @@ use rustc_lint;
 use rustc::dep_graph::DepGraph;
 use rustc::hir;
 use rustc::hir::intravisit;
-use rustc::session::{self, config};
+use rustc::session::{self, CompileIncomplete, config};
 use rustc::session::config::{OutputType, OutputTypes, Externs};
 use rustc::session::search_paths::{SearchPaths, PathKind};
 use rustc_back::dynamic_lib::DynamicLibrary;
@@ -253,35 +253,25 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
         driver::compile_input(&sess, &cstore, &input, &out, &None, None, &control)
     }));
 
-    match res {
-        Ok(r) => {
-            match r {
-                Err(count) => {
-                    if count > 0 && !compile_fail {
-                        sess.fatal("aborting due to previous error(s)")
-                    } else if count == 0 && compile_fail {
-                        panic!("test compiled while it wasn't supposed to")
-                    }
-                    if count > 0 && error_codes.len() > 0 {
-                        let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap();
-                        error_codes.retain(|err| !out.contains(err));
-                    }
-                }
-                Ok(()) if compile_fail => {
-                    panic!("test compiled while it wasn't supposed to")
-                }
-                _ => {}
-            }
+    let compile_result = match res {
+        Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()),
+        Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(())
+    };
+
+    match (compile_result, compile_fail) {
+        (Ok(()), true) => {
+            panic!("test compiled while it wasn't supposed to")
         }
-        Err(_) => {
-            if !compile_fail {
-                panic!("couldn't compile the test");
-            }
+        (Ok(()), false) => {}
+        (Err(()), true) => {
             if error_codes.len() > 0 {
                 let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap();
                 error_codes.retain(|err| !out.contains(err));
             }
         }
+        (Err(()), false) => {
+            panic!("couldn't compile the test")
+        }
     }
 
     if error_codes.len() > 0 {
@@ -467,7 +457,7 @@ impl Collector {
     pub fn add_test(&mut self, test: String,
                     should_panic: bool, no_run: bool, should_ignore: bool,
                     as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
-                    line: usize, filename: String) {
+                    line: usize, filename: String, allow_fail: bool) {
         let name = self.generate_name(line, &filename);
         // to be removed when hoedown is removed
         if self.render_type == RenderType::Pulldown {
@@ -499,6 +489,7 @@ impl Collector {
                 ignore: should_ignore,
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
+                allow_fail: allow_fail,
             },
             testfn: testing::DynTestFn(box move |()| {
                 let panic = io::set_panic(None);
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 1dfae0ce83f..f81adad3ebe 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -949,63 +949,9 @@ mod arch {
 mod tests {
     use super::*;
 
-    use iter::repeat;
-    use rand::{self, Rng};
-    use ffi::{OsString, OsStr};
+    use ffi::OsStr;
     use path::{Path, PathBuf};
 
-    fn make_rand_name() -> OsString {
-        let mut rng = rand::thread_rng();
-        let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
-                                     .collect::<String>());
-        let n = OsString::from(n);
-        assert!(var_os(&n).is_none());
-        n
-    }
-
-    fn eq(a: Option<OsString>, b: Option<&str>) {
-        assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
-    }
-
-    #[test]
-    fn test_set_var() {
-        let n = make_rand_name();
-        set_var(&n, "VALUE");
-        eq(var_os(&n), Some("VALUE"));
-    }
-
-    #[test]
-    fn test_remove_var() {
-        let n = make_rand_name();
-        set_var(&n, "VALUE");
-        remove_var(&n);
-        eq(var_os(&n), None);
-    }
-
-    #[test]
-    fn test_set_var_overwrite() {
-        let n = make_rand_name();
-        set_var(&n, "1");
-        set_var(&n, "2");
-        eq(var_os(&n), Some("2"));
-        set_var(&n, "");
-        eq(var_os(&n), Some(""));
-    }
-
-    #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn test_var_big() {
-        let mut s = "".to_string();
-        let mut i = 0;
-        while i < 100 {
-            s.push_str("aaaaaaaaaa");
-            i += 1;
-        }
-        let n = make_rand_name();
-        set_var(&n, &s);
-        eq(var_os(&n), Some(&s));
-    }
-
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
     fn test_self_exe_path() {
@@ -1018,32 +964,6 @@ mod tests {
     }
 
     #[test]
-    #[cfg_attr(target_os = "emscripten", ignore)]
-    fn test_env_set_get_huge() {
-        let n = make_rand_name();
-        let s = repeat("x").take(10000).collect::<String>();
-        set_var(&n, &s);
-        eq(var_os(&n), Some(&s));
-        remove_var(&n);
-        eq(var_os(&n), None);
-    }
-
-    #[test]
-    fn test_env_set_var() {
-        let n = make_rand_name();
-
-        let mut e = vars_os();
-        set_var(&n, "VALUE");
-        assert!(!e.any(|(k, v)| {
-            &*k == &*n && &*v == "VALUE"
-        }));
-
-        assert!(vars_os().any(|(k, v)| {
-            &*k == &*n && &*v == "VALUE"
-        }));
-    }
-
-    #[test]
     fn test() {
         assert!((!Path::new("test-path").is_absolute()));
 
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 6134b0b882c..a6eb17c8fa4 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -363,39 +363,29 @@ impl f32 {
     #[inline]
     pub fn signum(self) -> f32 { num::Float::signum(self) }
 
-    /// Returns `true` if `self`'s sign bit is positive, including
-    /// `+0.0` and `INFINITY`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     ///
     /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
     /// let f = 7.0_f32;
     /// let g = -7.0_f32;
     ///
     /// assert!(f.is_sign_positive());
     /// assert!(!g.is_sign_positive());
-    /// // Requires both tests to determine if is `NaN`
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_sign_positive(self) -> bool { num::Float::is_sign_positive(self) }
 
-    /// Returns `true` if `self`'s sign is negative, including `-0.0`
-    /// and `NEG_INFINITY`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     ///
     /// ```
-    /// use std::f32;
-    ///
-    /// let nan = f32::NAN;
     /// let f = 7.0f32;
     /// let g = -7.0f32;
     ///
     /// assert!(!f.is_sign_negative());
     /// assert!(g.is_sign_negative());
-    /// // Requires both tests to determine if is `NaN`.
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1141,13 +1131,16 @@ impl f32 {
     #[inline]
     pub fn from_bits(mut v: u32) -> Self {
         const EXP_MASK: u32   = 0x7F800000;
-        const QNAN_MASK: u32  = 0x00400000;
         const FRACT_MASK: u32 = 0x007FFFFF;
         if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 {
-            // If we have a NaN value, we
-            // convert signaling NaN values to quiet NaN
-            // by setting the the highest bit of the fraction
-            v |= QNAN_MASK;
+            // While IEEE 754-2008 specifies encodings for quiet NaNs
+            // and signaling ones, certain MIPS and PA-RISC
+            // CPUs treat signaling NaNs differently.
+            // Therefore to be safe, we pass a known quiet NaN
+            // if v is any kind of NaN.
+            // The check above only assumes IEEE 754-1985 to be
+            // valid.
+            v = unsafe { ::mem::transmute(NAN) };
         }
         unsafe { ::mem::transmute(v) }
     }
@@ -1184,7 +1177,7 @@ mod tests {
         assert!(!nan.is_infinite());
         assert!(!nan.is_finite());
         assert!(!nan.is_normal());
-        assert!(!nan.is_sign_positive());
+        assert!(nan.is_sign_positive());
         assert!(!nan.is_sign_negative());
         assert_eq!(Fp::Nan, nan.classify());
     }
@@ -1428,7 +1421,8 @@ mod tests {
         assert!(!(-1f32).is_sign_positive());
         assert!(!NEG_INFINITY.is_sign_positive());
         assert!(!(1f32/NEG_INFINITY).is_sign_positive());
-        assert!(!NAN.is_sign_positive());
+        assert!(NAN.is_sign_positive());
+        assert!(!(-NAN).is_sign_positive());
     }
 
     #[test]
@@ -1441,6 +1435,7 @@ mod tests {
         assert!(NEG_INFINITY.is_sign_negative());
         assert!((1f32/NEG_INFINITY).is_sign_negative());
         assert!(!NAN.is_sign_negative());
+        assert!((-NAN).is_sign_negative());
     }
 
     #[test]
@@ -1740,8 +1735,15 @@ mod tests {
     }
     #[test]
     fn test_snan_masking() {
+        // NOTE: this test assumes that our current platform
+        // implements IEEE 754-2008 that specifies the difference
+        // in encoding of quiet and signaling NaNs.
+        // If you are porting Rust to a platform that does not
+        // implement IEEE 754-2008 (but e.g. IEEE 754-1985, which
+        // only says that "Signaling NaNs shall be reserved operands"
+        // but doesn't specify the actual setup), feel free to
+        // cfg out this test.
         let snan: u32 = 0x7F801337;
-        const PAYLOAD_MASK: u32 = 0x003FFFFF;
         const QNAN_MASK: u32  = 0x00400000;
         let nan_masked_fl = f32::from_bits(snan);
         let nan_masked = nan_masked_fl.to_bits();
@@ -1750,7 +1752,5 @@ mod tests {
         // Ensure that we have a quiet NaN
         assert_ne!(nan_masked & QNAN_MASK, 0);
         assert!(nan_masked_fl.is_nan());
-        // Ensure the payload wasn't touched during conversion
-        assert_eq!(nan_masked & PAYLOAD_MASK, snan & PAYLOAD_MASK);
     }
 }
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index e8d25cfbf94..4d8d8b4ebe6 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -301,21 +301,15 @@ impl f64 {
     #[inline]
     pub fn signum(self) -> f64 { num::Float::signum(self) }
 
-    /// Returns `true` if `self`'s sign bit is positive, including
-    /// `+0.0` and `INFINITY`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     ///
     /// ```
-    /// use std::f64;
-    ///
-    /// let nan: f64 = f64::NAN;
-    ///
     /// let f = 7.0_f64;
     /// let g = -7.0_f64;
     ///
     /// assert!(f.is_sign_positive());
     /// assert!(!g.is_sign_positive());
-    /// // Requires both tests to determine if is `NaN`
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -326,21 +320,15 @@ impl f64 {
     #[inline]
     pub fn is_positive(self) -> bool { num::Float::is_sign_positive(self) }
 
-    /// Returns `true` if `self`'s sign is negative, including `-0.0`
-    /// and `NEG_INFINITY`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     ///
     /// ```
-    /// use std::f64;
-    ///
-    /// let nan = f64::NAN;
-    ///
     /// let f = 7.0_f64;
     /// let g = -7.0_f64;
     ///
     /// assert!(!f.is_sign_negative());
     /// assert!(g.is_sign_negative());
-    /// // Requires both tests to determine if is `NaN`.
-    /// assert!(!nan.is_sign_positive() && !nan.is_sign_negative());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1058,13 +1046,16 @@ impl f64 {
     #[inline]
     pub fn from_bits(mut v: u64) -> Self {
         const EXP_MASK: u64   = 0x7FF0000000000000;
-        const QNAN_MASK: u64  = 0x0001000000000000;
         const FRACT_MASK: u64 = 0x000FFFFFFFFFFFFF;
         if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 {
-            // If we have a NaN value, we
-            // convert signaling NaN values to quiet NaN
-            // by setting the the highest bit of the fraction
-            v |= QNAN_MASK;
+            // While IEEE 754-2008 specifies encodings for quiet NaNs
+            // and signaling ones, certain MIPS and PA-RISC
+            // CPUs treat signaling NaNs differently.
+            // Therefore to be safe, we pass a known quiet NaN
+            // if v is any kind of NaN.
+            // The check above only assumes IEEE 754-1985 to be
+            // valid.
+            v = unsafe { ::mem::transmute(NAN) };
         }
         unsafe { ::mem::transmute(v) }
     }
@@ -1101,7 +1092,7 @@ mod tests {
         assert!(!nan.is_infinite());
         assert!(!nan.is_finite());
         assert!(!nan.is_normal());
-        assert!(!nan.is_sign_positive());
+        assert!(nan.is_sign_positive());
         assert!(!nan.is_sign_negative());
         assert_eq!(Fp::Nan, nan.classify());
     }
@@ -1347,7 +1338,8 @@ mod tests {
         assert!(!(-1f64).is_sign_positive());
         assert!(!NEG_INFINITY.is_sign_positive());
         assert!(!(1f64/NEG_INFINITY).is_sign_positive());
-        assert!(!NAN.is_sign_positive());
+        assert!(NAN.is_sign_positive());
+        assert!(!(-NAN).is_sign_positive());
     }
 
     #[test]
@@ -1360,6 +1352,7 @@ mod tests {
         assert!(NEG_INFINITY.is_sign_negative());
         assert!((1f64/NEG_INFINITY).is_sign_negative());
         assert!(!NAN.is_sign_negative());
+        assert!((-NAN).is_sign_negative());
     }
 
     #[test]
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 1a91417ca0e..5f0b11a616e 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -585,11 +585,11 @@ impl From<Box<CStr>> for CString {
     }
 }
 
-#[stable(feature = "box_from_c_string", since = "1.18.0")]
-impl Into<Box<CStr>> for CString {
+#[stable(feature = "box_from_c_string", since = "1.20.0")]
+impl From<CString> for Box<CStr> {
     #[inline]
-    fn into(self) -> Box<CStr> {
-        self.into_boxed_c_str()
+    fn from(s: CString) -> Box<CStr> {
+        s.into_boxed_c_str()
     }
 }
 
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index f54d79c201f..02a13ed7a5a 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -29,7 +29,7 @@ use sys_common::{AsInner, IntoInner, FromInner};
 /// * On Windows, strings are often arbitrary sequences of non-zero 16-bit
 ///   values, interpreted as UTF-16 when it is valid to do so.
 ///
-/// * In Rust, strings are always valid UTF-8, but may contain zeros.
+/// * In Rust, strings are always valid UTF-8, which may contain zeros.
 ///
 /// `OsString` and [`OsStr`] bridge this gap by simultaneously representing Rust
 /// and platform-native string values, and in particular allowing a Rust string
@@ -230,8 +230,6 @@ impl OsString {
     /// # Examples
     ///
     /// ```
-    /// #![feature(osstring_shrink_to_fit)]
-    ///
     /// use std::ffi::OsString;
     ///
     /// let mut s = OsString::from("foo");
@@ -242,7 +240,7 @@ impl OsString {
     /// s.shrink_to_fit();
     /// assert_eq!(3, s.capacity());
     /// ```
-    #[unstable(feature = "osstring_shrink_to_fit", issue = "40421")]
+    #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
     pub fn shrink_to_fit(&mut self) {
         self.inner.shrink_to_fit()
     }
@@ -542,10 +540,10 @@ impl From<Box<OsStr>> for OsString {
     }
 }
 
-#[stable(feature = "box_from_os_string", since = "1.18.0")]
-impl Into<Box<OsStr>> for OsString {
-    fn into(self) -> Box<OsStr> {
-        self.into_boxed_os_str()
+#[stable(feature = "box_from_os_string", since = "1.20.0")]
+impl From<OsString> for Box<OsStr> {
+    fn from(s: OsString) -> Box<OsStr> {
+        s.into_boxed_os_str()
     }
 }
 
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 5b8c0c33990..88994b284c9 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -653,15 +653,29 @@ impl OpenOptions {
     /// # Errors
     ///
     /// This function will return an error under a number of different
-    /// circumstances, to include but not limited to:
-    ///
-    /// * Opening a file that does not exist without setting `create` or
-    ///   `create_new`.
-    /// * Attempting to open a file with access that the user lacks
-    ///   permissions for
-    /// * Filesystem-level errors (full disk, etc)
-    /// * Invalid combinations of open options (truncate without write access,
-    ///   no access mode set, etc)
+    /// circumstances. Some of these error conditions are listed here, together
+    /// with their [`ErrorKind`]. The mapping to [`ErrorKind`]s is not part of
+    /// the compatiblity contract of the function, especially the `Other` kind
+    /// might change to more specific kinds in the future.
+    ///
+    /// * [`NotFound`]: The specified file does not exist and neither `create`
+    ///   or `create_new` is set.
+    /// * [`NotFound`]: One of the directory components of the file path does
+    ///   not exist.
+    /// * [`PermissionDenied`]: The user lacks permission to get the specified
+    ///   access rights for the file.
+    /// * [`PermissionDenied`]: The user lacks permission to open one of the
+    ///   directory components of the specified path.
+    /// * [`AlreadyExists`]: `create_new` was specified and the file already
+    ///   exists.
+    /// * [`InvalidInput`]: Invalid combinations of open options (truncate
+    ///   without write access, no access mode set, etc.).
+    /// * [`Other`]: One of the directory components of the specified file path
+    ///   was not, in fact, a directory.
+    /// * [`Other`]: Filesystem-level errors: full disk, write permission
+    ///   requested on a read-only file system, exceeded disk quota, too many
+    ///   open files, too long filename, too many symbolic links in the
+    ///   specified path (Unix-like systems only), etc.
     ///
     /// # Examples
     ///
@@ -670,6 +684,13 @@ impl OpenOptions {
     ///
     /// let file = OpenOptions::new().open("foo.txt");
     /// ```
+    ///
+    /// [`ErrorKind`]: ../io/enum.ErrorKind.html
+    /// [`AlreadyExists`]: ../io/enum.ErrorKind.html#variant.AlreadyExists
+    /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
+    /// [`NotFound`]: ../io/enum.ErrorKind.html#variant.NotFound
+    /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
+    /// [`PermissionDenied`]: ../io/enum.ErrorKind.html#variant.PermissionDenied
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
         self._open(path.as_ref())
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 680a5f32ae2..71c76008244 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1589,8 +1589,6 @@ impl<T, U> Chain<T, U> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(more_io_inner_methods)]
-    ///
     /// # use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
@@ -1604,7 +1602,7 @@ impl<T, U> Chain<T, U> {
     /// # Ok(())
     /// # }
     /// ```
-    #[unstable(feature = "more_io_inner_methods", issue="41519")]
+    #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn into_inner(self) -> (T, U) {
         (self.first, self.second)
     }
@@ -1614,8 +1612,6 @@ impl<T, U> Chain<T, U> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(more_io_inner_methods)]
-    ///
     /// # use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
@@ -1629,7 +1625,7 @@ impl<T, U> Chain<T, U> {
     /// # Ok(())
     /// # }
     /// ```
-    #[unstable(feature = "more_io_inner_methods", issue="41519")]
+    #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_ref(&self) -> (&T, &U) {
         (&self.first, &self.second)
     }
@@ -1643,8 +1639,6 @@ impl<T, U> Chain<T, U> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(more_io_inner_methods)]
-    ///
     /// # use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
@@ -1658,7 +1652,7 @@ impl<T, U> Chain<T, U> {
     /// # Ok(())
     /// # }
     /// ```
-    #[unstable(feature = "more_io_inner_methods", issue="41519")]
+    #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_mut(&mut self) -> (&mut T, &mut U) {
         (&mut self.first, &mut self.second)
     }
@@ -1791,8 +1785,6 @@ impl<T> Take<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(more_io_inner_methods)]
-    ///
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
@@ -1808,7 +1800,7 @@ impl<T> Take<T> {
     /// # Ok(())
     /// # }
     /// ```
-    #[unstable(feature = "more_io_inner_methods", issue="41519")]
+    #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_ref(&self) -> &T {
         &self.inner
     }
@@ -1822,8 +1814,6 @@ impl<T> Take<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(more_io_inner_methods)]
-    ///
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
@@ -1839,7 +1829,7 @@ impl<T> Take<T> {
     /// # Ok(())
     /// # }
     /// ```
-    #[unstable(feature = "more_io_inner_methods", issue="41519")]
+    #[stable(feature = "more_io_inner_methods", since = "1.20.0")]
     pub fn get_mut(&mut self) -> &mut T {
         &mut self.inner
     }
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 9a4c5ec8f6b..6eb9faacf7f 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -41,10 +41,10 @@ macro_rules! panic {
         panic!("explicit panic")
     });
     ($msg:expr) => ({
-        $crate::rt::begin_panic($msg, {
+        $crate::rt::begin_panic_new($msg, {
             // static requires less code at runtime, more constant data
-            static _FILE_LINE: (&'static str, u32) = (file!(), line!());
-            &_FILE_LINE
+            static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!());
+            &_FILE_LINE_COL
         })
     });
     ($fmt:expr, $($arg:tt)+) => ({
@@ -53,8 +53,8 @@ macro_rules! panic {
             // used inside a dead function. Just `#[allow(dead_code)]` is
             // insufficient, since the user may have
             // `#[forbid(dead_code)]` and which cannot be overridden.
-            static _FILE_LINE: (&'static str, u32) = (file!(), line!());
-            &_FILE_LINE
+            static _FILE_LINE_COL: (&'static str, u32, u32) = (file!(), line!(), column!());
+            &_FILE_LINE_COL
         })
     });
 }
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 6f46a73698f..494376b831e 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -262,6 +262,7 @@ impl<'a> PanicInfo<'a> {
 pub struct Location<'a> {
     file: &'a str,
     line: u32,
+    col: u32,
 }
 
 impl<'a> Location<'a> {
@@ -308,6 +309,29 @@ impl<'a> Location<'a> {
     pub fn line(&self) -> u32 {
         self.line
     }
+
+    /// Returns the column from which the panic originated.
+    ///
+    /// # Examples
+    ///
+    /// ```should_panic
+    /// #![feature(panic_col)]
+    /// use std::panic;
+    ///
+    /// panic::set_hook(Box::new(|panic_info| {
+    ///     if let Some(location) = panic_info.location() {
+    ///         println!("panic occured at column {}", location.column());
+    ///     } else {
+    ///         println!("panic occured but can't get location information...");
+    ///     }
+    /// }));
+    ///
+    /// panic!("Normal panic");
+    /// ```
+    #[unstable(feature = "panic_col", reason = "recently added", issue = "42939")]
+    pub fn column(&self) -> u32 {
+        self.col
+    }
 }
 
 fn default_hook(info: &PanicInfo) {
@@ -329,6 +353,7 @@ fn default_hook(info: &PanicInfo) {
 
     let file = info.location.file;
     let line = info.location.line;
+    let col = info.location.col;
 
     let msg = match info.payload.downcast_ref::<&'static str>() {
         Some(s) => *s,
@@ -342,8 +367,8 @@ fn default_hook(info: &PanicInfo) {
     let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
 
     let write = |err: &mut ::io::Write| {
-        let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
-                         name, msg, file, line);
+        let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}:{}",
+                         name, msg, file, line, col);
 
         #[cfg(feature = "backtrace")]
         {
@@ -467,8 +492,9 @@ pub fn panicking() -> bool {
 #[unwind]
 pub extern fn rust_begin_panic(msg: fmt::Arguments,
                                file: &'static str,
-                               line: u32) -> ! {
-    begin_panic_fmt(&msg, &(file, line))
+                               line: u32,
+                               col: u32) -> ! {
+    begin_panic_fmt(&msg, &(file, line, col))
 }
 
 /// The entry point for panicking with a formatted message.
@@ -482,7 +508,7 @@ pub extern fn rust_begin_panic(msg: fmt::Arguments,
            issue = "0")]
 #[inline(never)] #[cold]
 pub fn begin_panic_fmt(msg: &fmt::Arguments,
-                       file_line: &(&'static str, u32)) -> ! {
+                       file_line_col: &(&'static str, u32, u32)) -> ! {
     use fmt::Write;
 
     // We do two allocations here, unfortunately. But (a) they're
@@ -492,7 +518,39 @@ pub fn begin_panic_fmt(msg: &fmt::Arguments,
 
     let mut s = String::new();
     let _ = s.write_fmt(*msg);
-    begin_panic(s, file_line)
+    begin_panic_new(s, file_line_col)
+}
+
+// FIXME: In PR #42938, we have added the column as info passed to the panic
+// handling code. For this, we want to break the ABI of begin_panic.
+// This is not possible to do directly, as the stage0 compiler is hardcoded
+// to emit a call to begin_panic in src/libsyntax/ext/build.rs, only
+// with the file and line number being passed, but not the colum number.
+// By changing the compiler source, we can only affect behaviour of higher
+// stages. We need to perform the switch over two stage0 replacements, using
+// a temporary function begin_panic_new while performing the switch:
+// 0. Right now, we tell stage1 onward to emit a call to begin_panic_new.
+// 1. In the first SNAP, stage0 calls begin_panic_new with the new ABI,
+//    begin_panic stops being used. Now we can change begin_panic to
+//    the new ABI, and start emitting calls to begin_panic in higher
+//    stages again, this time with the new ABI.
+// 2. After the second SNAP, stage0 calls begin_panic with the new ABI,
+//    and we can remove the temporary begin_panic_new function.
+
+/// This is the entry point of panicking for panic!() and assert!().
+#[unstable(feature = "libstd_sys_internals",
+           reason = "used by the panic! macro",
+           issue = "0")]
+#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
+pub fn begin_panic_new<M: Any + Send>(msg: M, file_line_col: &(&'static str, u32, u32)) -> ! {
+    // Note that this should be the only allocation performed in this code path.
+    // Currently this means that panic!() on OOM will invoke this code path,
+    // but then again we're not really ready for panic on OOM anyway. If
+    // we do start doing this, then we should propagate this allocation to
+    // be performed in the parent of this thread instead of the thread that's
+    // panicking.
+
+    rust_panic_with_hook(Box::new(msg), file_line_col)
 }
 
 /// This is the entry point of panicking for panic!() and assert!().
@@ -508,7 +566,10 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> !
     // be performed in the parent of this thread instead of the thread that's
     // panicking.
 
-    rust_panic_with_hook(Box::new(msg), file_line)
+    let (file, line) = *file_line;
+    let file_line_col = (file, line, 0);
+
+    rust_panic_with_hook(Box::new(msg), &file_line_col)
 }
 
 /// Executes the primary logic for a panic, including checking for recursive
@@ -520,8 +581,8 @@ pub fn begin_panic<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> !
 #[inline(never)]
 #[cold]
 fn rust_panic_with_hook(msg: Box<Any + Send>,
-                        file_line: &(&'static str, u32)) -> ! {
-    let (file, line) = *file_line;
+                        file_line_col: &(&'static str, u32, u32)) -> ! {
+    let (file, line, col) = *file_line_col;
 
     let panics = update_panic_count(1);
 
@@ -540,8 +601,9 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
         let info = PanicInfo {
             payload: &*msg,
             location: Location {
-                file: file,
-                line: line,
+                file,
+                line,
+                col,
             },
         };
         HOOK_LOCK.read();
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 42a54ed6d75..e7c7be981d2 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -276,7 +276,7 @@ impl<'a> Prefix<'a> {
 /// ```
 /// use std::path;
 ///
-/// assert!(path::is_separator('/'));
+/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows
 /// assert!(!path::is_separator('❤'));
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1348,10 +1348,10 @@ impl From<Box<Path>> for PathBuf {
     }
 }
 
-#[stable(feature = "box_from_path_buf", since = "1.18.0")]
-impl Into<Box<Path>> for PathBuf {
-    fn into(self) -> Box<Path> {
-        self.into_boxed_path()
+#[stable(feature = "box_from_path_buf", since = "1.20.0")]
+impl From<PathBuf> for Box<Path> {
+    fn from(p: PathBuf) -> Box<Path> {
+        p.into_boxed_path()
     }
 }
 
@@ -1499,9 +1499,9 @@ impl AsRef<OsStr> for PathBuf {
 /// A slice of a path (akin to [`str`]).
 ///
 /// This type supports a number of operations for inspecting a path, including
-/// breaking the path into its components (separated by `/` or `\`, depending on
-/// the platform), extracting the file name, determining whether the path is
-/// absolute, and so on.
+/// breaking the path into its components (separated by `/` on Unix and by either
+/// `/` or `\` on Windows), extracting the file name, determining whether the path
+/// is absolute, and so on.
 ///
 /// This is an *unsized* type, meaning that it must always be used behind a
 /// pointer like `&` or [`Box`]. For an owned version of this type,
@@ -1520,10 +1520,11 @@ impl AsRef<OsStr> for PathBuf {
 /// use std::path::Path;
 /// use std::ffi::OsStr;
 ///
-/// let path = Path::new("/tmp/foo/bar.txt");
+/// // Note: this example does work on Windows
+/// let path = Path::new("./foo/bar.txt");
 ///
 /// let parent = path.parent();
-/// assert_eq!(parent, Some(Path::new("/tmp/foo")));
+/// assert_eq!(parent, Some(Path::new("./foo")));
 ///
 /// let file_stem = path.file_stem();
 /// assert_eq!(file_stem, Some(OsStr::new("bar")));
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index df6a648b7b1..7adfcc44ad0 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -447,8 +447,6 @@ impl Command {
     /// Basic usage:
     ///
     /// ```no_run
-    /// #![feature(command_envs)]
-    ///
     /// use std::process::{Command, Stdio};
     /// use std::env;
     /// use std::collections::HashMap;
@@ -466,7 +464,7 @@ impl Command {
     ///         .spawn()
     ///         .expect("printenv failed to start");
     /// ```
-    #[unstable(feature = "command_envs", issue = "38526")]
+    #[stable(feature = "command_envs", since = "1.19.0")]
     pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
         where I: IntoIterator<Item=(K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>
     {
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index 06fd838ea06..2ee63527c14 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -25,7 +25,7 @@
 
 
 // Reexport some of our utilities which are expected by other crates.
-pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count};
+pub use panicking::{begin_panic_new, begin_panic, begin_panic_fmt, update_panic_count};
 
 #[cfg(not(test))]
 #[lang = "start"]
diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs
index 7dc61ce6654..9f0eee024d5 100644
--- a/src/libstd/sys/redox/fast_thread_local.rs
+++ b/src/libstd/sys/redox/fast_thread_local.rs
@@ -57,7 +57,7 @@ impl<T> Key<T> {
     }
 }
 
-unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
     // The fallback implementation uses a vanilla OS-based TLS key to track
     // the list of destructors that need to be run for this thread. The key
     // then has its own destructor which runs all the other destructors.
@@ -115,3 +115,7 @@ pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
         ptr::drop_in_place((*ptr).inner.get());
     }
 }
+
+pub fn requires_move_before_drop() -> bool {
+    false
+}
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
index 48d9cdcb2c9..c5a19e8debe 100644
--- a/src/libstd/sys/redox/fs.rs
+++ b/src/libstd/sys/redox/fs.rs
@@ -420,12 +420,19 @@ fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
 }
 
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    canonicalize(p)
-}
-
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
-    ::sys_common::util::dumb_print(format_args!("Symlink\n"));
-    unimplemented!();
+    let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_SYMLINK | syscall::O_RDONLY))?;
+    let mut buf: [u8; 4096] = [0; 4096];
+    let count = cvt(syscall::read(fd, &mut buf))?;
+    cvt(syscall::close(fd))?;
+    Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) }))
+}
+
+pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
+    let fd = cvt(syscall::open(dst.to_str().unwrap(),
+                               syscall::O_SYMLINK | syscall::O_CREAT | syscall::O_WRONLY | 0o777))?;
+    cvt(syscall::write(fd, src.to_str().unwrap().as_bytes()))?;
+    cvt(syscall::close(fd))?;
+    Ok(())
 }
 
 pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs
index ac3fd2ad6b9..17673f0bd60 100644
--- a/src/libstd/sys/redox/net/tcp.rs
+++ b/src/libstd/sys/redox/net/tcp.rs
@@ -17,7 +17,6 @@ use sys::fs::{File, OpenOptions};
 use sys::syscall::TimeSpec;
 use sys_common::{AsInner, FromInner, IntoInner};
 use time::Duration;
-use vec::Vec;
 
 use super::{path_to_peer_addr, path_to_local_addr};
 
diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs
index 05863adf108..28645facd93 100644
--- a/src/libstd/sys/redox/pipe.rs
+++ b/src/libstd/sys/redox/pipe.rs
@@ -49,8 +49,8 @@ pub fn read2(p1: AnonPipe,
     //FIXME: Use event based I/O multiplexing
     //unimplemented!()
 
-    p1.read_to_end(v1)?;
-    p2.read_to_end(v2)?;
+    p1.0.read_to_end(v1)?;
+    p2.0.read_to_end(v2)?;
 
     Ok(())
 
diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs
index 9f0d3e6f779..bd603cfe6ef 100644
--- a/src/libstd/sys/redox/syscall/flag.rs
+++ b/src/libstd/sys/redox/syscall/flag.rs
@@ -33,6 +33,7 @@ pub const MAP_WRITE_COMBINE: usize = 2;
 pub const MODE_TYPE: u16 = 0xF000;
 pub const MODE_DIR: u16 = 0x4000;
 pub const MODE_FILE: u16 = 0x8000;
+pub const MODE_SYMLINK: u16 = 0xA000;
 
 pub const MODE_PERM: u16 = 0x0FFF;
 pub const MODE_SETUID: u16 = 0o4000;
@@ -53,6 +54,7 @@ pub const O_TRUNC: usize =      0x0400_0000;
 pub const O_EXCL: usize =       0x0800_0000;
 pub const O_DIRECTORY: usize =  0x1000_0000;
 pub const O_STAT: usize =       0x2000_0000;
+pub const O_SYMLINK: usize =    0x4000_0000;
 pub const O_ACCMODE: usize =    O_RDONLY | O_WRONLY | O_RDWR;
 
 pub const SEEK_SET: usize = 0;
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 743b7c3220a..f4fe52ca3b3 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -825,8 +825,6 @@ pub fn park_timeout(dur: Duration) {
 /// # Examples
 ///
 /// ```
-/// #![feature(thread_id)]
-///
 /// use std::thread;
 ///
 /// let other_thread = thread::spawn(|| {
@@ -836,7 +834,7 @@ pub fn park_timeout(dur: Duration) {
 /// let other_thread_id = other_thread.join().unwrap();
 /// assert!(thread::current().id() != other_thread_id);
 /// ```
-#[unstable(feature = "thread_id", issue = "21507")]
+#[stable(feature = "thread_id", since = "1.19.0")]
 #[derive(Eq, PartialEq, Clone, Copy, Hash, Debug)]
 pub struct ThreadId(u64);
 
@@ -966,8 +964,6 @@ impl Thread {
     /// # Examples
     ///
     /// ```
-    /// #![feature(thread_id)]
-    ///
     /// use std::thread;
     ///
     /// let other_thread = thread::spawn(|| {
@@ -977,7 +973,7 @@ impl Thread {
     /// let other_thread_id = other_thread.join().unwrap();
     /// assert!(thread::current().id() != other_thread_id);
     /// ```
-    #[unstable(feature = "thread_id", issue = "21507")]
+    #[stable(feature = "thread_id", since = "1.19.0")]
     pub fn id(&self) -> ThreadId {
         self.inner.id
     }
@@ -1168,8 +1164,6 @@ impl<T> JoinHandle<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(thread_id)]
-    ///
     /// use std::thread;
     ///
     /// let builder = thread::Builder::new();
diff --git a/src/libstd_unicode/tables.rs b/src/libstd_unicode/tables.rs
index 7173040350e..0938738b52c 100644
--- a/src/libstd_unicode/tables.rs
+++ b/src/libstd_unicode/tables.rs
@@ -14,7 +14,7 @@
 
 /// The version of [Unicode](http://www.unicode.org/)
 /// that the unicode parts of `CharExt` and `UnicodeStrPrelude` traits are based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (9, 0, 0);
+pub const UNICODE_VERSION: (u64, u64, u64) = (10, 0, 0);
 
 
 // BoolTrie is a trie for representing a set of Unicode codepoints. It is
@@ -167,7 +167,7 @@ pub mod general_category {
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 7, 0, 0, 8, 0, 0, 0, 6, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0,
             0, 0, 8, 0, 9, 6, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
+            0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
             11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -236,7 +236,7 @@ pub mod derived_property {
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
             36, 36, 36, 36, 36, 36, 36, 36, 96, 97, 36, 36, 36, 36, 98, 99, 36, 100, 101, 36, 102,
-            103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 117, 36,
+            103, 104, 105, 36, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 36, 95, 36,
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
@@ -244,23 +244,23 @@ pub mod derived_property {
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
             36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 118, 119,
+            36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 117, 118,
             31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
             31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
             31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
             31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
             31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
             31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-            36, 36, 36, 36, 36, 120, 36, 121, 122, 123, 124, 125, 36, 36, 36, 36, 126, 127, 128,
-            129, 31, 130, 36, 131, 132, 133, 113, 134
+            36, 36, 36, 36, 36, 119, 36, 120, 121, 122, 123, 124, 36, 36, 36, 36, 125, 126, 127,
+            128, 31, 129, 36, 130, 131, 132, 113, 133
         ],
         r3: &[
-            0x00001ffffcffffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000,
-            0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x0003000fb080599f,
-            0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x0200000f00011bbf,
+            0x00001ffffcffffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0xffff03f8fff00000,
+            0xefffffffffffffff, 0xfffe000fffe1dfff, 0xe3c5fdfffff99fef, 0x1003000fb080599f,
+            0xc36dfdfffff987ee, 0x003f00005e021987, 0xe3edfdfffffbbfee, 0x1e00000f00011bbf,
             0xe3edfdfffff99fee, 0x0002000fb0c0199f, 0xc3ffc718d63dc7ec, 0x0000000000811dc7,
             0xe3fffdfffffddfef, 0x0000000f07601ddf, 0xe3effdfffffddfef, 0x0006000f40601ddf,
-            0xe7fffffffffddfee, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f,
+            0xe7fffffffffddfef, 0xfc00000f80f05ddf, 0x2ffbfffffc7fffec, 0x000c0000ff5f807f,
             0x07fffffffffffffe, 0x000000000000207f, 0x3bffecaefef02596, 0x00000000f000205f,
             0x0000000000000001, 0xfffe1ffffffffeff, 0x1ffffffffeffff03, 0x0000000000000000,
             0xf97fffffffffffff, 0xffffc1e7ffff0000, 0xffffffff3000407f, 0xf7ffffffffff20bf,
@@ -278,74 +278,76 @@ pub mod derived_property {
             0x000003ffffffffff, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff,
             0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f,
             0x0000800000000000, 0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff,
-            0xfffe3fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff,
+            0xfffe7fffffffffe0, 0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff,
             0x0000000000001fff, 0x3fffffffffff0000, 0x00000c00ffff1fff, 0x8ff07fffffffffff,
             0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000,
             0x000000fffffff7bb, 0x000fffffffffffff, 0x28fc00000000002f, 0xffff07fffffffc00,
             0x1fffffff0007ffff, 0xfff7ffffffffffff, 0x7c00ffdf00008000, 0x007fffffffffffff,
             0xc47fffff00003fff, 0x7fffffffffffffff, 0x003cffff38000005, 0xffff7f7f007e7e7e,
-            0xffff003ff7ffffff, 0x000007ffffffffff, 0xffff000fffffffff, 0x0ffffffffffff87f,
-            0xffff3fffffffffff, 0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb,
-            0x0003ffffffffffff, 0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000,
-            0xfffffffffffcffff, 0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff,
-            0x07fffffe00000000, 0xffffffc007fffffe, 0x000000001cfcfcfc
+            0xffff003ff7ffffff, 0xffff000fffffffff, 0x0ffffffffffff87f, 0xffff3fffffffffff,
+            0x0000000003ffffff, 0x5f7ffdffe0f8007f, 0xffffffffffffffdb, 0x0003ffffffffffff,
+            0xfffffffffff80000, 0x3fffffffffffffff, 0xffffffffffff0000, 0xfffffffffffcffff,
+            0x0fff0000000000ff, 0xffdf000000000000, 0x1fffffffffffffff, 0x07fffffe00000000,
+            0xffffffc007fffffe, 0x000000001cfcfcfc
         ],
         r4: [
             0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 13, 14,
-            15, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+            15, 7, 16, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
         ],
         r5: &[
             0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2,
             2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32,
             32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 33, 34, 35, 32, 36, 2, 37, 38, 4, 39, 40, 41,
             42, 4, 4, 2, 43, 2, 44, 4, 4, 45, 46, 47, 48, 28, 4, 49, 4, 4, 4, 4, 4, 50, 51, 4, 4, 4,
-            4, 4, 4, 4, 52, 4, 4, 4, 4, 53, 54, 55, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 4, 2, 57, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 52, 53, 54, 55, 4, 4, 4, 4, 56, 57, 58, 4, 59, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 61, 4, 2, 62, 2, 2, 2, 63, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 57, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2,
-            2, 2, 2, 2, 52, 20, 4, 60, 16, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 63, 64,
-            65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2,
+            2, 2, 2, 2, 2, 2, 55, 20, 4, 65, 16, 66, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
+            68, 69, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 66, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 71, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 72, 2, 2, 2, 2, 2, 73,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 2, 68, 69, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 2, 70, 71, 72, 73, 74, 2, 2, 2, 2, 75, 76, 77, 78, 79, 80, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 81,
+            4, 4, 4, 4, 4, 4, 4, 2, 74, 75, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 2, 2, 2, 82, 2, 83, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 84, 85,
-            86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 87, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 2, 2, 2, 88, 2, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 90, 91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 72, 93, 94, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 4, 4, 4,
+            96, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 98, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
         ],
         r6: &[
             0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff,
             0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff,
-            0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f,
+            0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f,
             0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff,
             0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff,
             0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff,
@@ -356,17 +358,18 @@ pub mod derived_property {
             0x000001ffffffffff, 0xe3edfdfffff99fef, 0x0000000fe081199f, 0x00000000000007bb,
             0x00000000000000b3, 0x7f3fffffffffffff, 0x000000003f000000, 0x7fffffffffffffff,
             0x0000000000000011, 0x000007ffe3ffffff, 0xffffffff00000000, 0x80000000ffffffff,
-            0x01ffffffffffffff, 0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff,
-            0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f,
-            0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff, 0x7fffffffffff001f,
-            0x00000000fff80000, 0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003,
-            0x1fff07ffffffffff, 0x0000000043ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff,
-            0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff,
-            0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff,
-            0x0000000000000ff7, 0x000007dbf9ffff7f, 0x000000000000001f, 0x000000000000008f,
-            0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0xffff000000000000,
-            0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff, 0x00000003ffffffff,
-            0x000000003fffffff
+            0x7fe7ffffffffffff, 0xffffffffffff0000, 0x0000000000ffffcf, 0x01ffffffffffffff,
+            0x7f7ffffffffffdff, 0xfffc000000000001, 0x007ffefffffcffff, 0xb47ffffffffffb7f,
+            0x00000000000000cb, 0x0000000003ffffff, 0x00007fffffffffff, 0x000000000000000f,
+            0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000000ffff,
+            0x7fffffffffff001f, 0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff,
+            0xffff000000000000, 0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000043ff01ff,
+            0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf,
+            0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff,
+            0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7, 0x000007dbf9ffff7f,
+            0x000000000000001f, 0x000000000000008f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84,
+            0x0ffffbee0ffffbff, 0xffff03ffffff03ff, 0x00000000000003ff, 0x00000000007fffff,
+            0xffff0003ffffffff, 0x00000001ffffffff, 0x000000003fffffff
         ],
     };
 
@@ -426,9 +429,9 @@ pub mod derived_property {
         r3: &[
             0x00003fffffc00000, 0x000000000e000000, 0x0000000000000000, 0xfffffffffff00000,
             0x1400000000000007, 0x0002000c00fe21fe, 0x1000000000000002, 0x0000000c0000201e,
-            0x1000000000000006, 0x0023000000023986, 0x0000000c000021be, 0x9000000000000002,
+            0x1000000000000006, 0x0023000000023986, 0xfc00000c000021be, 0x9000000000000002,
             0x0000000c0040201e, 0x0000000000000004, 0x0000000000002001, 0xc000000000000001,
-            0x0000000c00603dc1, 0x0000000c00003040, 0x0000000000000002, 0x00000000005c0400,
+            0x0000000c00603dc1, 0x0000000c00003040, 0x1800000000000003, 0x00000000005c0400,
             0x07f2000000000000, 0x0000000000007fc0, 0x1bf2000000000000, 0x0000000000003f40,
             0x02a0000003000000, 0x7ffe000000000000, 0x1ffffffffeffe0df, 0x0000000000000040,
             0x66fde00000000000, 0x001e0001c3000000, 0x0000000020002064, 0x1000000000000000,
@@ -437,7 +440,7 @@ pub mod derived_property {
             0x0e04018700000000, 0x0000000009800000, 0x9ff81fe57f400000, 0x7fff008000000000,
             0x17d000000000000f, 0x000ff80000000004, 0x00003b3c00000003, 0x0003a34000000000,
             0x00cff00000000000, 0x3f00000000000000, 0x031021fdfff70000, 0xfffff00000000000,
-            0x010007ffffffffff, 0xfffffffff8000000, 0xf83fffffffffffff, 0xa000000000000000,
+            0x010007ffffffffff, 0xfffffffff8000000, 0xfbffffffffffffff, 0xa000000000000000,
             0x6000e000e000e003, 0x00007c900300f800, 0x8002ffdf00000000, 0x000000001fff0000,
             0x0001ffffffff0000, 0x3000000000000000, 0x0003800000000000, 0x8000800000000000,
             0xffffffff00000000, 0x0000800000000000, 0x083e3c0000000020, 0x000000007e000000,
@@ -465,24 +468,24 @@ pub mod derived_property {
             0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 6, 7, 8, 0, 9, 10, 11, 12, 13, 0, 0, 14, 15, 16, 0, 0, 17, 18, 19, 20,
-            0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 27, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 21, 22, 23, 24, 25, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, 0,
+            0, 0, 30, 0, 31, 0, 32, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
-            2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 39, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 42, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 41, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 48, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 45,
-            0, 0, 45, 45, 45, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0
+            50, 51, 0, 0, 51, 51, 51, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0
         ],
         r6: &[
             0x0000000000000000, 0x2000000000000000, 0x0000000100000000, 0x07c0000000000000,
@@ -491,12 +494,14 @@ pub mod derived_property {
             0x0000000000001c00, 0x40d3800000000000, 0x000007f880000000, 0x1000000000000003,
             0x001f1fc000000001, 0xff00000000000000, 0x000000000000005c, 0x85f8000000000000,
             0x000000000000000d, 0xb03c000000000000, 0x0000000030000001, 0xa7f8000000000000,
-            0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0xbf7f000000000000,
-            0x006dfcfffffc0000, 0x001f000000000000, 0x007f000000000000, 0x000000000000000f,
-            0x00000000ffff8000, 0x0000000f60000000, 0xfff8038000000000, 0x00003c0000000fe7,
-            0x000000000000001c, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010,
-            0x000007dbf9ffff7f, 0x00000000007f0000, 0x00000000000007f0, 0xf800000000000000,
-            0xffffffff00000002, 0xffffffffffffffff, 0x0000ffffffffffff
+            0x0000000000000001, 0x00bf280000000000, 0x00000fbce0000000, 0x79f800000000067e,
+            0x000000000e7e0080, 0x00000000037ffc00, 0xbf7f000000000000, 0x006dfcfffffc0000,
+            0xb47e000000000000, 0x00000000000000bf, 0x001f000000000000, 0x007f000000000000,
+            0x000000000000000f, 0x00000000ffff8000, 0x0000000300000000, 0x0000000f60000000,
+            0xfff8038000000000, 0x00003c0000000fe7, 0x000000000000001c, 0xf87fffffffffffff,
+            0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f0000,
+            0x00000000000007f0, 0xf800000000000000, 0xffffffff00000002, 0xffffffffffffffff,
+            0x0000ffffffffffff
         ],
     };
 
@@ -851,12 +856,12 @@ pub mod derived_property {
             127
         ],
         r3: &[
-            0x00003fffffffffff, 0x000000000fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000,
-            0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x0003ffcfb080799f,
-            0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0x0200ffcf00013bbf,
+            0x00003fffffffffff, 0x000007ff0fffffff, 0x3fdfffff00000000, 0xfffffffbfff00000,
+            0xffffffffffffffff, 0xfffeffcfffffffff, 0xf3c5fdfffff99fef, 0x1003ffcfb080799f,
+            0xd36dfdfffff987ee, 0x003fffc05e023987, 0xf3edfdfffffbbfee, 0xfe00ffcf00013bbf,
             0xf3edfdfffff99fee, 0x0002ffcfb0c0399f, 0xc3ffc718d63dc7ec, 0x0000ffc000813dc7,
             0xe3fffdfffffddfef, 0x0000ffcf07603ddf, 0xf3effdfffffddfef, 0x0006ffcf40603ddf,
-            0xe7fffffffffddfee, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f,
+            0xfffffffffffddfef, 0xfc00ffcf80f07ddf, 0x2ffbfffffc7fffec, 0x000cffc0ff5f847f,
             0x07fffffffffffffe, 0x0000000003ff7fff, 0x3bffecaefef02596, 0x00000000f3ff3f5f,
             0xc2a003ff03000001, 0xfffe1ffffffffeff, 0x1ffffffffeffffdf, 0x0000000000000040,
             0xffffffffffff03ff, 0xffffffff3fffffff, 0xf7ffffffffff20bf, 0xffffffff3d7f3dff,
@@ -867,13 +872,13 @@ pub mod derived_property {
             0x003fffffffffffff, 0x0fff0fff7fffffff, 0x001f3fffffffffc0, 0xffff0fffffffffff,
             0x0000000007ff03ff, 0xffffffff0fffffff, 0x9fffffff7fffffff, 0x3fff008003ff03ff,
             0x0000000000000000, 0x000ff80003ff0fff, 0x000fffffffffffff, 0x3fffffffffffe3ff,
-            0x00000000000001ff, 0x037ffffffff70000, 0xf83fffffffffffff, 0xffffffff3f3fffff,
+            0x00000000000001ff, 0x03fffffffff70000, 0xfbffffffffffffff, 0xffffffff3f3fffff,
             0x3fffffffaaff3f3f, 0x5fdfffffffffffff, 0x1fdc1fff0fcf1fdc, 0x8000000000000000,
             0x8002000000100001, 0x000000001fff0000, 0x0001ffe21fff0000, 0xf3fffd503f2ffc84,
             0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000ff81fffffffff,
             0xffff20bfffffffff, 0x800080ffffffffff, 0x7f7f7f7f007fffff, 0xffffffff7f7f7f7f,
-            0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0,
-            0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff,
+            0x1f3efffe000000e0, 0xfffffffee67fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0,
+            0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff,
             0x3fffffffffff0000, 0x00000fffffff1fff, 0xbff0ffffffffffff, 0x0003ffffffffffff,
             0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000, 0x000000ffffffffff,
             0x28ffffff03ff003f, 0xffff3fffffffffff, 0x1fffffff000fffff, 0x7fffffff03ff8001,
@@ -886,60 +891,62 @@ pub mod derived_property {
         ],
         r4: [
             0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13,
-            14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+            14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+            5, 5, 5, 5, 5, 5, 5, 17, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
         ],
         r5: &[
             0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16, 4, 4, 2, 2, 2,
             2, 17, 18, 4, 4, 19, 20, 21, 22, 23, 4, 24, 4, 25, 26, 27, 28, 29, 30, 31, 4, 2, 32, 33,
             33, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 34, 3, 35, 36, 37, 2, 38, 39, 4, 40, 41, 42,
             43, 4, 4, 2, 44, 2, 45, 4, 4, 46, 47, 2, 48, 49, 50, 51, 4, 4, 4, 4, 4, 52, 53, 4, 4, 4,
-            4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 58, 4, 2, 59, 2, 2, 2, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 63, 4, 2, 64, 2, 2, 2, 65, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 61, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2,
-            2, 2, 2, 2, 54, 62, 4, 63, 17, 64, 65, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 66, 67,
-            68, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2,
+            2, 2, 2, 2, 2, 2, 57, 67, 4, 68, 17, 69, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
+            71, 72, 73, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 70, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 33, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 21, 75, 2, 2, 2, 2, 2, 76,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 2, 71, 72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 73, 74, 4, 4,
-            75, 4, 4, 4, 4, 4, 4, 2, 76, 77, 78, 79, 80, 2, 2, 2, 2, 81, 82, 83, 84, 85, 86, 4, 4,
-            4, 4, 4, 4, 4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 90, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 2, 2, 2, 91, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            92, 93, 94, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            4, 4, 4, 4, 4, 4, 4, 2, 77, 78, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            79, 80, 4, 4, 81, 4, 4, 4, 4, 4, 4, 2, 82, 83, 84, 85, 86, 2, 2, 2, 2, 87, 88, 89, 90,
+            91, 92, 4, 4, 4, 4, 4, 4, 4, 4, 93, 94, 95, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 96, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 97, 2, 44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 98, 99, 100, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 101, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 102, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 96, 4, 4, 4, 4, 4, 4, 4,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 103, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 2, 2, 2, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 98, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 104, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 105, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
         ],
         r6: &[
             0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff,
             0x0000000000000000, 0x001fffffffffffff, 0x2000000000000000, 0xffffffff1fffffff,
-            0x000000010001ffff, 0xffff0000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff,
+            0x000000010001ffff, 0xffffe000ffffffff, 0x07ffffffffff07ff, 0xffffffff3fffffff,
             0x00000000003eff0f, 0xffff03ff3fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff,
             0x0000000fffffffff, 0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f,
             0x007fffff003fffff, 0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff,
@@ -950,18 +957,20 @@ pub mod derived_property {
             0xffff01ffbfffbd7f, 0x03ff07ffffffffff, 0xf3edfdfffff99fef, 0x001f1fcfe081399f,
             0x0000000003ff07ff, 0x0000000003ff00bf, 0xff3fffffffffffff, 0x000000003f000001,
             0x0000000003ff0011, 0x00ffffffffffffff, 0x00000000000003ff, 0x03ff0fffe3ffffff,
-            0xffffffff00000000, 0x800003ffffffffff, 0x01ffffffffffffff, 0xff7ffffffffffdff,
-            0xfffc000003ff0001, 0x007ffefffffcffff, 0x0000000003ffffff, 0x00007fffffffffff,
-            0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff, 0x001f3fffffff0000,
-            0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f, 0x00000000ffff8000,
-            0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff,
-            0x0000000063ff01ff, 0xf807e3e000000000, 0x00003c0000000fe7, 0x000000000000001c,
-            0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf,
-            0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff,
-            0xffff7fffffff7fff, 0xfffffdfffffffdff, 0xffffffffffffcff7, 0xf87fffffffffffff,
-            0x00201fffffffffff, 0x0000fffef8000010, 0x000007dbf9ffff7f, 0x00000000007f001f,
-            0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff,
-            0x00000003ffffffff, 0x000000003fffffff, 0x0000ffffffffffff
+            0xffffffff00000000, 0x800003ffffffffff, 0x7fffffffffffffff, 0xffffffffffff0080,
+            0x0000000003ffffcf, 0x01ffffffffffffff, 0xff7ffffffffffdff, 0xfffc000003ff0001,
+            0x007ffefffffcffff, 0xb47ffffffffffb7f, 0x0000000003ff00ff, 0x0000000003ffffff,
+            0x00007fffffffffff, 0x000000000000000f, 0x000000000000007f, 0x000003ff7fffffff,
+            0x001f3fffffff0000, 0xe0fffff803ff000f, 0x000000000000ffff, 0x7fffffffffff001f,
+            0x00000000ffff8000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000,
+            0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000063ff01ff, 0xf807e3e000000000,
+            0x00003c0000000fe7, 0x000000000000001c, 0xffffffffffdfffff, 0xebffde64dfffffff,
+            0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff,
+            0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff,
+            0xffffffffffffcff7, 0xf87fffffffffffff, 0x00201fffffffffff, 0x0000fffef8000010,
+            0x000007dbf9ffff7f, 0x00000000007f001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84,
+            0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff, 0x00000001ffffffff,
+            0x000000003fffffff, 0x0000ffffffffffff
         ],
     };
 
@@ -1027,8 +1036,8 @@ pub mod derived_property {
             129, 130, 131, 132
         ],
         r3: &[
-            0x00000110043fffff, 0x0000000001ffffff, 0x3fdfffff00000000, 0x0000000000000000,
-            0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x00030003b0004000,
+            0x00000110043fffff, 0x000007ff01ffffff, 0x3fdfffff00000000, 0x0000000000000000,
+            0x23fffffffffffff0, 0xfffe0003ff010000, 0x23c5fdfffff99fe1, 0x10030003b0004000,
             0x036dfdfffff987e0, 0x001c00005e000000, 0x23edfdfffffbbfe0, 0x0200000300010000,
             0x23edfdfffff99fe0, 0x00020003b0000000, 0x03ffc718d63dc7e8, 0x0000000000010000,
             0x23fffdfffffddfe0, 0x0000000307000000, 0x23effdfffffddfe1, 0x0006000340000000,
@@ -1048,8 +1057,8 @@ pub mod derived_property {
             0x1fdc1fff0fcf1fdc, 0x8002000000000000, 0x000000001fff0000, 0xf3fffd503f2ffc84,
             0xffffffff000043e0, 0xffff7fffffffffff, 0xffffffff7fffffff, 0x000c781fffffffff,
             0xffff20bfffffffff, 0x000080ffffffffff, 0x7f7f7f7f007fffff, 0x000000007f7f7f7f,
-            0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe3fffffffffe0,
-            0x07ffffff00007fff, 0xffff000000000000, 0x00000000003fffff, 0x0000000000001fff,
+            0x1f3e03fe000000e0, 0xfffffffee07fffff, 0xf7ffffffffffffff, 0xfffe7fffffffffe0,
+            0x07ffffff00007fff, 0xffff000000000000, 0x000007ffffffffff, 0x0000000000001fff,
             0x3fffffffffff0000, 0x00000c00ffff1fff, 0x80007fffffffffff, 0xffffffff3fffffff,
             0x0000ffffffffffff, 0xfffffffcff800000, 0x00ff7ffffffff9ff, 0xff80000000000000,
             0x00000007fffff7bb, 0x000ffffffffffffc, 0x28fc000000000000, 0xffff003ffffffc00,
@@ -1064,58 +1073,60 @@ pub mod derived_property {
         ],
         r4: [
             0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 5, 9, 5, 10, 11, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 13,
-            14, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+            14, 7, 15, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
             5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
         ],
         r5: &[
             0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15, 4, 4, 2, 2, 2,
             2, 16, 17, 4, 4, 18, 19, 20, 21, 22, 4, 23, 4, 24, 25, 26, 27, 28, 29, 30, 4, 2, 31, 32,
             32, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 33, 4, 34, 35, 36, 37, 38, 39, 40, 4, 41, 20,
             42, 43, 4, 4, 5, 44, 45, 46, 4, 4, 47, 48, 45, 49, 50, 4, 51, 4, 4, 4, 4, 4, 52, 53, 4,
-            4, 4, 4, 4, 4, 4, 54, 4, 4, 4, 4, 55, 56, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 58, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 54, 55, 56, 57, 4, 4, 4, 4, 58, 59, 60, 4, 61, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 51, 4, 2, 47, 2, 2, 2, 63, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 59, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2,
-            2, 2, 2, 2, 2, 2, 54, 20, 4, 60, 45, 61, 57, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2,
-            62, 63, 64, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 66, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 2, 67, 68, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 69, 70, 71, 72, 73, 2, 2, 2, 2, 74, 75, 76, 77, 78, 79, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            2, 2, 2, 2, 2, 2, 2, 2, 57, 20, 4, 65, 45, 66, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 2, 67, 68, 69, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 70, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 32, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 20, 71, 2, 2, 2, 2, 2,
+            72, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 2, 73, 74, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 75, 76, 77, 78, 79, 2, 2, 2, 2, 80, 81, 82, 83, 84,
+            85, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4, 4, 2, 2, 2, 80, 2, 58, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            81, 82, 83, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 84, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 86, 2, 63, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 87, 88, 89, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 91, 2, 2, 2, 2, 2,
             2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 85, 4, 4, 4, 4, 4, 4, 4,
+            2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 92, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
             4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 2, 2, 2, 2, 2, 2, 2, 2, 86, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-            4, 4, 4, 4
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 93, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+            4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
         ],
         r6: &[
             0xb7ffff7fffffefff, 0x000000003fff3fff, 0xffffffffffffffff, 0x07ffffffffffffff,
             0x0000000000000000, 0x001fffffffffffff, 0xffffffff1fffffff, 0x000000000001ffff,
-            0xffff0000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f,
+            0xffffe000ffffffff, 0x003fffffffff07ff, 0xffffffff3fffffff, 0x00000000003eff0f,
             0xffff00003fffffff, 0x0fffffffff0fffff, 0xffff00ffffffffff, 0x0000000fffffffff,
             0x007fffffffffffff, 0x000000ff003fffff, 0x91bffffffffffd3f, 0x007fffff003fffff,
             0x000000007fffffff, 0x0037ffff00000000, 0x03ffffff003fffff, 0xc0ffffffffffffff,
@@ -1126,15 +1137,17 @@ pub mod derived_property {
             0x00000ffffffbffff, 0xffff01ffbfffbd7f, 0x23edfdfffff99fe0, 0x00000003e0010000,
             0x0000000000000780, 0x0000ffffffffffff, 0x00000000000000b0, 0x00007fffffffffff,
             0x000000000f000000, 0x0000000000000010, 0x000007ffffffffff, 0x0000000003ffffff,
-            0xffffffff00000000, 0x80000000ffffffff, 0x01ffffffffffffff, 0x00007ffffffffdff,
-            0xfffc000000000001, 0x000000000000ffff, 0x000000000000000f, 0x000000000000007f,
-            0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f, 0x00000000fff80000,
-            0x0000000100000000, 0x00001fffffffffff, 0x0000000000000003, 0x1fff07ffffffffff,
-            0x0000000003ff01ff, 0xffffffffffdfffff, 0xebffde64dfffffff, 0xffffffffffffffef,
-            0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f, 0xffffff3fffffffff, 0xf7fffffff7fffffd,
-            0xffdfffffffdfffff, 0xffff7fffffff7fff, 0xfffffdfffffffdff, 0x0000000000000ff7,
-            0x000000000000001f, 0x0af7fe96ffffffef, 0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff,
-            0x00000000007fffff, 0x00000003ffffffff, 0x000000003fffffff
+            0xffffffff00000000, 0x80000000ffffffff, 0x0407fffffffff801, 0xfffffffff0010000,
+            0x00000000000003cf, 0x01ffffffffffffff, 0x00007ffffffffdff, 0xfffc000000000001,
+            0x000000000000ffff, 0x0001fffffffffb7f, 0x0000000000000040, 0x000000000000000f,
+            0x000000000000007f, 0x00003fffffff0000, 0xe0fffff80000000f, 0x000000000001001f,
+            0x00000000fff80000, 0x0000000300000000, 0x00001fffffffffff, 0xffff000000000000,
+            0x0fffffffffffffff, 0x1fff07ffffffffff, 0x0000000003ff01ff, 0xffffffffffdfffff,
+            0xebffde64dfffffff, 0xffffffffffffffef, 0x7bffffffdfdfe7bf, 0xfffffffffffdfc5f,
+            0xffffff3fffffffff, 0xf7fffffff7fffffd, 0xffdfffffffdfffff, 0xffff7fffffff7fff,
+            0xfffffdfffffffdff, 0x0000000000000ff7, 0x000000000000001f, 0x0af7fe96ffffffef,
+            0x5ef7f796aa96ea84, 0x0ffffbee0ffffbff, 0x00000000007fffff, 0xffff0003ffffffff,
+            0x00000001ffffffff, 0x000000003fffffff
         ],
     };
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 325a5cdf8fc..d00e29d954f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -97,9 +97,8 @@ impl Path {
     }
 
     pub fn default_to_global(mut self) -> Path {
-        let name = self.segments[0].identifier.name;
-        if !self.is_global() && name != "$crate" &&
-           name != keywords::SelfValue.name() && name != keywords::Super.name() {
+        if !self.is_global() &&
+           !::parse::token::Ident(self.segments[0].identifier).is_path_segment_keyword() {
             self.segments.insert(0, PathSegment::crate_root(self.span));
         }
         self
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 5168943d108..1eb749623d8 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -11,7 +11,7 @@
 use abi::Abi;
 use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind};
 use attr;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{Pos, Span, DUMMY_SP};
 use codemap::{dummy_spanned, respan, Spanned};
 use ext::base::ExtCtxt;
 use ptr::P;
@@ -768,14 +768,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let loc = self.codemap().lookup_char_pos(span.lo);
         let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name));
         let expr_line = self.expr_u32(span, loc.line as u32);
-        let expr_file_line_tuple = self.expr_tuple(span, vec![expr_file, expr_line]);
-        let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple);
+        let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1);
+        let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]);
+        let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple);
         self.expr_call_global(
             span,
-            self.std_path(&["rt", "begin_panic"]),
+            self.std_path(&["rt", "begin_panic_new"]),
             vec![
                 self.expr_str(span, msg),
-                expr_file_line_ptr])
+                expr_loc_ptr])
     }
 
     fn expr_unreachable(&self, span: Span) -> P<ast::Expr> {
diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs
index 18056f60287..4e9e30857b1 100644
--- a/src/libsyntax/ext/tt/quoted.rs
+++ b/src/libsyntax/ext/tt/quoted.rs
@@ -12,7 +12,7 @@ use ast;
 use ext::tt::macro_parser;
 use parse::{ParseSess, token};
 use print::pprust;
-use symbol::{keywords, Symbol};
+use symbol::keywords;
 use syntax_pos::{DUMMY_SP, Span, BytePos};
 use tokenstream;
 
@@ -199,7 +199,7 @@ fn parse_tree<I>(tree: tokenstream::TokenTree,
             Some(tokenstream::TokenTree::Token(ident_span, token::Ident(ident))) => {
                 let span = Span { lo: span.lo, ..ident_span };
                 if ident.name == keywords::Crate.name() {
-                    let ident = ast::Ident { name: Symbol::intern("$crate"), ..ident };
+                    let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident };
                     TokenTree::Token(span, token::Ident(ident))
                 } else {
                     TokenTree::MetaVar(span, ident)
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 3f3c94536a6..4b0ec1a20e3 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -360,6 +360,12 @@ declare_features! (
 
     // rustc internal
     (active, abi_thiscall, "1.19.0", None),
+
+    // Allows a test to fail without failing the whole suite
+    (active, allow_fail, "1.19.0", Some(42219)),
+
+    // Allows unsized tuple coercion.
+    (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
 );
 
 declare_features! (
@@ -818,6 +824,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                              "used internally by rustc",
                                              cfg_fn!(rustc_attrs))),
 
+    ("allow_fail", Normal, Gated(Stability::Unstable,
+                                 "allow_fail",
+                                 "allow_fail attribute is currently unstable",
+                                 cfg_fn!(allow_fail))),
+
     // Crate level attributes
     ("crate_name", CrateLevel, Ungated),
     ("crate_type", CrateLevel, Ungated),
@@ -1039,6 +1050,9 @@ pub const EXPLAIN_VIS_MATCHER: &'static str =
 pub const EXPLAIN_PLACEMENT_IN: &'static str =
     "placement-in expression syntax is experimental and subject to change.";
 
+pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
+    "Unsized tuple coercion is not stable enough for use and is subject to change";
+
 struct PostExpansionVisitor<'a> {
     context: &'a Context<'a>,
 }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 66775d8c43d..09cdf26bf1f 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1285,7 +1285,7 @@ impl<'a> StringReader<'a> {
                     });
                     let keyword_checking_token = &token::Ident(keyword_checking_ident);
                     let last_bpos = self.pos;
-                    if keyword_checking_token.is_any_keyword() &&
+                    if keyword_checking_token.is_reserved_ident() &&
                        !keyword_checking_token.is_keyword(keywords::Static) {
                         self.err_span_(start, last_bpos, "lifetimes cannot use keyword names");
                     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2858d49d63d..c248e20b608 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -511,14 +511,13 @@ impl<'a> Parser<'a> {
     }
 
     pub fn this_token_descr(&self) -> String {
-        let s = self.this_token_to_string();
-        if self.token.is_strict_keyword() {
-            format!("keyword `{}`", s)
-        } else if self.token.is_reserved_keyword() {
-            format!("reserved keyword `{}`", s)
-        } else {
-            format!("`{}`", s)
-        }
+        let prefix = match &self.token {
+            t if t.is_special_ident() => "reserved identifier ",
+            t if t.is_used_keyword() => "keyword ",
+            t if t.is_unused_keyword() => "reserved keyword ",
+            _ => "",
+        };
+        format!("{}`{}`", prefix, self.this_token_to_string())
     }
 
     pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
@@ -637,10 +636,12 @@ impl<'a> Parser<'a> {
     }
 
     pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
-        self.check_strict_keywords();
-        self.check_reserved_keywords();
         match self.token {
             token::Ident(i) => {
+                if self.token.is_reserved_ident() {
+                    self.span_err(self.span, &format!("expected identifier, found {}",
+                                                      self.this_token_descr()));
+                }
                 self.bump();
                 Ok(i)
             }
@@ -713,25 +714,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Signal an error if the given string is a strict keyword
-    pub fn check_strict_keywords(&mut self) {
-        if self.token.is_strict_keyword() {
-            let token_str = self.this_token_to_string();
-            let span = self.span;
-            self.span_err(span,
-                          &format!("expected identifier, found keyword `{}`",
-                                  token_str));
-        }
-    }
-
-    /// Signal an error if the current token is a reserved keyword
-    pub fn check_reserved_keywords(&mut self) {
-        if self.token.is_reserved_keyword() {
-            let token_str = self.this_token_to_string();
-            self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit()
-        }
-    }
-
     fn check_ident(&mut self) -> bool {
         if self.token.is_ident() {
             true
@@ -1659,8 +1641,10 @@ impl<'a> Parser<'a> {
         Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) })
     }
 
-    /// matches '-' lit | lit
+    /// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat)
     pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
+        maybe_whole_expr!(self);
+
         let minus_lo = self.span;
         let minus_present = self.eat(&token::BinOp(token::Minus));
         let lo = self.span;
@@ -2299,7 +2283,7 @@ impl<'a> Parser<'a> {
                     ex = ExprKind::Break(lt, e);
                     hi = self.prev_span;
                 } else if self.token.is_keyword(keywords::Let) {
-                    // Catch this syntax error here, instead of in `check_strict_keywords`, so
+                    // Catch this syntax error here, instead of in `parse_ident`, so
                     // that we can explicitly mention that let is not to be used as an expression
                     let mut db = self.fatal("expected expression, found statement (`let`)");
                     db.note("variable declaration using `let` is a statement");
@@ -3541,7 +3525,7 @@ impl<'a> Parser<'a> {
                 // Parse box pat
                 let subpat = self.parse_pat()?;
                 pat = PatKind::Box(subpat);
-            } else if self.token.is_ident() && !self.token.is_any_keyword() &&
+            } else if self.token.is_ident() && !self.token.is_reserved_ident() &&
                       self.parse_as_ident() {
                 // Parse ident @ pat
                 // This can give false positives and parse nullary enums,
@@ -3816,7 +3800,7 @@ impl<'a> Parser<'a> {
 
     fn is_union_item(&self) -> bool {
         self.token.is_keyword(keywords::Union) &&
-        self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
+        self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
     }
 
     fn is_defaultness(&self) -> bool {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index d4198261d3f..834ac38af98 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -89,7 +89,7 @@ impl Lit {
 fn ident_can_begin_expr(ident: ast::Ident) -> bool {
     let ident_token: Token = Ident(ident);
 
-    !ident_token.is_any_keyword() ||
+    !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
         keywords::Do.name(),
@@ -112,7 +112,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
 fn ident_can_begin_type(ident: ast::Ident) -> bool {
     let ident_token: Token = Ident(ident);
 
-    !ident_token.is_any_keyword() ||
+    !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
         keywords::For.name(),
@@ -319,7 +319,7 @@ impl Token {
 
     pub fn is_path_start(&self) -> bool {
         self == &ModSep || self.is_qpath_start() || self.is_path() ||
-        self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword()
+        self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident()
     }
 
     /// Returns `true` if the token is a given keyword, `kw`.
@@ -331,18 +331,23 @@ impl Token {
         match self.ident() {
             Some(id) => id.name == keywords::Super.name() ||
                         id.name == keywords::SelfValue.name() ||
-                        id.name == keywords::SelfType.name(),
+                        id.name == keywords::SelfType.name() ||
+                        id.name == keywords::DollarCrate.name(),
             None => false,
         }
     }
 
-    /// Returns `true` if the token is either a strict or reserved keyword.
-    pub fn is_any_keyword(&self) -> bool {
-        self.is_strict_keyword() || self.is_reserved_keyword()
+    // Returns true for reserved identifiers used internally for elided lifetimes,
+    // unnamed method parameters, crate root module, error recovery etc.
+    pub fn is_special_ident(&self) -> bool {
+        match self.ident() {
+            Some(id) => id.name <= keywords::DollarCrate.name(),
+            _ => false,
+        }
     }
 
-    /// Returns `true` if the token is a strict keyword.
-    pub fn is_strict_keyword(&self) -> bool {
+    /// Returns `true` if the token is a keyword used in the language.
+    pub fn is_used_keyword(&self) -> bool {
         match self.ident() {
             Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(),
             _ => false,
@@ -350,7 +355,7 @@ impl Token {
     }
 
     /// Returns `true` if the token is a keyword reserved for possible future use.
-    pub fn is_reserved_keyword(&self) -> bool {
+    pub fn is_unused_keyword(&self) -> bool {
         match self.ident() {
             Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(),
             _ => false,
@@ -410,6 +415,11 @@ impl Token {
             Whitespace | Comment | Shebang(..) | Eof => return None,
         })
     }
+
+    /// Returns `true` if the token is either a special identifier or a keyword.
+    pub fn is_reserved_ident(&self) -> bool {
+        self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword()
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index ac5b32c828a..d449e412d6c 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -760,7 +760,7 @@ pub trait PrintState<'a> {
                         word(self.writer(), "::")?
                     }
                     if segment.identifier.name != keywords::CrateRoot.name() &&
-                       segment.identifier.name != "$crate" {
+                       segment.identifier.name != keywords::DollarCrate.name() {
                         word(self.writer(), &segment.identifier.name.as_str())?;
                     }
                 }
@@ -2374,7 +2374,7 @@ impl<'a> State<'a> {
                           -> io::Result<()>
     {
         if segment.identifier.name != keywords::CrateRoot.name() &&
-           segment.identifier.name != "$crate" {
+           segment.identifier.name != keywords::DollarCrate.name() {
             self.print_ident(segment.identifier)?;
             if let Some(ref parameters) = segment.parameters {
                 self.print_path_parameters(parameters, colons_before_params)?;
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index a0d1785c6ff..86f5f42eac7 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -52,7 +52,8 @@ struct Test {
     path: Vec<Ident> ,
     bench: bool,
     ignore: bool,
-    should_panic: ShouldPanic
+    should_panic: ShouldPanic,
+    allow_fail: bool,
 }
 
 struct TestCtxt<'a> {
@@ -133,7 +134,8 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
                         path: self.cx.path.clone(),
                         bench: is_bench_fn(&self.cx, &i),
                         ignore: is_ignored(&i),
-                        should_panic: should_panic(&i, &self.cx)
+                        should_panic: should_panic(&i, &self.cx),
+                        allow_fail: is_allowed_fail(&i),
                     };
                     self.cx.testfns.push(test);
                     self.tests.push(i.ident);
@@ -383,6 +385,10 @@ fn is_ignored(i: &ast::Item) -> bool {
     i.attrs.iter().any(|attr| attr.check_name("ignore"))
 }
 
+fn is_allowed_fail(i: &ast::Item) -> bool {
+    i.attrs.iter().any(|attr| attr.check_name("allow_fail"))
+}
+
 fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic {
     match i.attrs.iter().find(|attr| attr.check_name("should_panic")) {
         Some(attr) => {
@@ -668,6 +674,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
             }
         }
     };
+    let allow_fail_expr = ecx.expr_bool(span, test.allow_fail);
 
     // self::test::TestDesc { ... }
     let desc_expr = ecx.expr_struct(
@@ -675,7 +682,8 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
         test_path("TestDesc"),
         vec![field("name", name_expr),
              field("ignore", ignore_expr),
-             field("should_panic", fail_expr)]);
+             field("should_panic", fail_expr),
+             field("allow_fail", allow_fail_expr)]);
 
 
     let mut visible_path = match cx.toplevel_reexport {
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs
index 1993d6ebe5b..35a2a2513f4 100644
--- a/src/libsyntax_ext/deriving/clone.rs
+++ b/src/libsyntax_ext/deriving/clone.rs
@@ -167,7 +167,7 @@ fn cs_clone(name: &str,
             all_fields = af;
             vdata = vdata_;
         }
-        EnumMatching(_, variant, ref af) => {
+        EnumMatching(.., variant, ref af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
             all_fields = af;
             vdata = &variant.node.data;
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index ec4cb815960..38ed596098b 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -60,7 +60,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<E
     // based on the "shape".
     let (ident, is_struct) = match *substr.fields {
         Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
-        EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
+        EnumMatching(_, _, v, _) => (v.node.name, v.node.data.is_struct()),
         EnumNonMatchingCollapsed(..) |
         StaticStruct(..) |
         StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 33f742282c1..1e19cd99419 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -237,7 +237,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
                                      blk])
         }
 
-        EnumMatching(idx, variant, ref fields) => {
+        EnumMatching(idx, _, variant, ref fields) => {
             // We're not generating an AST that the borrow checker is expecting,
             // so we need to generate a unique local variable to take the
             // mutable loan out on, otherwise we get conflicts which don't
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 3a15b82d19f..4acd65bbf86 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -305,10 +305,10 @@ pub enum StaticFields {
 /// A summary of the possible sets of fields.
 pub enum SubstructureFields<'a> {
     Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
-    /// Matching variants of the enum: variant index, ast::Variant,
+    /// Matching variants of the enum: variant index, variant count, ast::Variant,
     /// fields: the field name is only non-`None` in the case of a struct
     /// variant.
-    EnumMatching(usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
+    EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
 
     /// Non-matching variants of the enum, but with all state hidden from
     /// the consequent code.  The first component holds `Ident`s for all of
@@ -1252,7 +1252,7 @@ impl<'a> MethodDef<'a> {
                 // expressions for referencing every field of every
                 // Self arg, assuming all are instances of VariantK.
                 // Build up code associated with such a case.
-                let substructure = EnumMatching(index, variant, field_tuples);
+                let substructure = EnumMatching(index, variants.len(), variant, field_tuples);
                 let arm_expr = self.call_substructure_method(cx,
                                                              trait_,
                                                              type_ident,
@@ -1269,12 +1269,13 @@ impl<'a> MethodDef<'a> {
                 // We need a default case that handles the fieldless variants.
                 // The index and actual variant aren't meaningful in this case,
                 // so just use whatever
+                let substructure = EnumMatching(0, variants.len(), v, Vec::new());
                 Some(self.call_substructure_method(cx,
                                                    trait_,
                                                    type_ident,
                                                    &self_args[..],
                                                    nonself_args,
-                                                   &EnumMatching(0, v, Vec::new())))
+                                                   &substructure))
             }
             _ if variants.len() > 1 && self_args.len() > 1 => {
                 // Since we know that all the arguments will match if we reach
diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs
index 97d7f2ce800..a341c21d0a1 100644
--- a/src/libsyntax_ext/deriving/hash.rs
+++ b/src/libsyntax_ext/deriving/hash.rs
@@ -81,7 +81,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
     let mut stmts = Vec::new();
 
     let fields = match *substr.fields {
-        Struct(_, ref fs) => fs,
+        Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
         EnumMatching(.., ref fs) => {
             let variant_value = deriving::call_intrinsic(cx,
                                                          trait_span,
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 6b5caff27e8..debac70545a 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -237,76 +237,76 @@ macro_rules! declare_keywords {(
 // NB: leaving holes in the ident table is bad! a different ident will get
 // interned with the id from the hole, but it will be between the min and max
 // of the reserved words, and thus tagged as "reserved".
-// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`,
+// After modifying this list adjust `is_special_ident`, `is_used_keyword`/`is_unused_keyword`,
 // this should be rarely necessary though if the keywords are kept in alphabetic order.
 declare_keywords! {
-    // Invalid identifier
+    // Special reserved identifiers used internally for elided lifetimes,
+    // unnamed method parameters, crate root module, error recovery etc.
     (0,  Invalid,        "")
-
-    // Strict keywords used in the language.
-    (1,  As,             "as")
-    (2,  Box,            "box")
-    (3,  Break,          "break")
-    (4,  Const,          "const")
-    (5,  Continue,       "continue")
-    (6,  Crate,          "crate")
-    (7,  Else,           "else")
-    (8,  Enum,           "enum")
-    (9,  Extern,         "extern")
-    (10, False,          "false")
-    (11, Fn,             "fn")
-    (12, For,            "for")
-    (13, If,             "if")
-    (14, Impl,           "impl")
-    (15, In,             "in")
-    (16, Let,            "let")
-    (17, Loop,           "loop")
-    (18, Match,          "match")
-    (19, Mod,            "mod")
-    (20, Move,           "move")
-    (21, Mut,            "mut")
-    (22, Pub,            "pub")
-    (23, Ref,            "ref")
-    (24, Return,         "return")
-    (25, SelfValue,      "self")
-    (26, SelfType,       "Self")
-    (27, Static,         "static")
-    (28, Struct,         "struct")
-    (29, Super,          "super")
-    (30, Trait,          "trait")
-    (31, True,           "true")
-    (32, Type,           "type")
-    (33, Unsafe,         "unsafe")
-    (34, Use,            "use")
-    (35, Where,          "where")
-    (36, While,          "while")
+    (1,  CrateRoot,      "{{root}}")
+    (2,  DollarCrate,    "$crate")
+
+    // Keywords used in the language.
+    (3,  As,             "as")
+    (4,  Box,            "box")
+    (5,  Break,          "break")
+    (6,  Const,          "const")
+    (7,  Continue,       "continue")
+    (8,  Crate,          "crate")
+    (9,  Else,           "else")
+    (10, Enum,           "enum")
+    (11, Extern,         "extern")
+    (12, False,          "false")
+    (13, Fn,             "fn")
+    (14, For,            "for")
+    (15, If,             "if")
+    (16, Impl,           "impl")
+    (17, In,             "in")
+    (18, Let,            "let")
+    (19, Loop,           "loop")
+    (20, Match,          "match")
+    (21, Mod,            "mod")
+    (22, Move,           "move")
+    (23, Mut,            "mut")
+    (24, Pub,            "pub")
+    (25, Ref,            "ref")
+    (26, Return,         "return")
+    (27, SelfValue,      "self")
+    (28, SelfType,       "Self")
+    (29, Static,         "static")
+    (30, Struct,         "struct")
+    (31, Super,          "super")
+    (32, Trait,          "trait")
+    (33, True,           "true")
+    (34, Type,           "type")
+    (35, Unsafe,         "unsafe")
+    (36, Use,            "use")
+    (37, Where,          "where")
+    (38, While,          "while")
 
     // Keywords reserved for future use.
-    (37, Abstract,       "abstract")
-    (38, Alignof,        "alignof")
-    (39, Become,         "become")
-    (40, Do,             "do")
-    (41, Final,          "final")
-    (42, Macro,          "macro")
-    (43, Offsetof,       "offsetof")
-    (44, Override,       "override")
-    (45, Priv,           "priv")
-    (46, Proc,           "proc")
-    (47, Pure,           "pure")
-    (48, Sizeof,         "sizeof")
-    (49, Typeof,         "typeof")
-    (50, Unsized,        "unsized")
-    (51, Virtual,        "virtual")
-    (52, Yield,          "yield")
+    (39, Abstract,       "abstract")
+    (40, Alignof,        "alignof")
+    (41, Become,         "become")
+    (42, Do,             "do")
+    (43, Final,          "final")
+    (44, Macro,          "macro")
+    (45, Offsetof,       "offsetof")
+    (46, Override,       "override")
+    (47, Priv,           "priv")
+    (48, Proc,           "proc")
+    (49, Pure,           "pure")
+    (50, Sizeof,         "sizeof")
+    (51, Typeof,         "typeof")
+    (52, Unsized,        "unsized")
+    (53, Virtual,        "virtual")
+    (54, Yield,          "yield")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (53, Default,        "default")
-    (54, StaticLifetime, "'static")
-    (55, Union,          "union")
-    (56, Catch,          "catch")
-
-    // A virtual keyword that resolves to the crate root when used in a lexical scope.
-    (57, CrateRoot, "{{root}}")
+    (55, Default,        "default")
+    (56, StaticLifetime, "'static")
+    (57, Union,          "union")
+    (58, Catch,          "catch")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 2094fd8898d..92cfb862b16 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -212,6 +212,7 @@ pub struct TestDesc {
     pub name: TestName,
     pub ignore: bool,
     pub should_panic: ShouldPanic,
+    pub allow_fail: bool,
 }
 
 #[derive(Clone)]
@@ -523,6 +524,7 @@ pub enum TestResult {
     TrFailed,
     TrFailedMsg(String),
     TrIgnored,
+    TrAllowedFail,
     TrMetrics(MetricMap),
     TrBench(BenchSamples),
 }
@@ -543,6 +545,7 @@ struct ConsoleTestState<T> {
     passed: usize,
     failed: usize,
     ignored: usize,
+    allowed_fail: usize,
     filtered_out: usize,
     measured: usize,
     metrics: MetricMap,
@@ -572,6 +575,7 @@ impl<T: Write> ConsoleTestState<T> {
             passed: 0,
             failed: 0,
             ignored: 0,
+            allowed_fail: 0,
             filtered_out: 0,
             measured: 0,
             metrics: MetricMap::new(),
@@ -594,6 +598,10 @@ impl<T: Write> ConsoleTestState<T> {
         self.write_short_result("ignored", "i", term::color::YELLOW)
     }
 
+    pub fn write_allowed_fail(&mut self) -> io::Result<()> {
+        self.write_short_result("FAILED (allowed)", "a", term::color::YELLOW)
+    }
+
     pub fn write_metric(&mut self) -> io::Result<()> {
         self.write_pretty("metric", term::color::CYAN)
     }
@@ -669,6 +677,7 @@ impl<T: Write> ConsoleTestState<T> {
             TrOk => self.write_ok(),
             TrFailed | TrFailedMsg(_) => self.write_failed(),
             TrIgnored => self.write_ignored(),
+            TrAllowedFail => self.write_allowed_fail(),
             TrMetrics(ref mm) => {
                 self.write_metric()?;
                 self.write_plain(&format!(": {}\n", mm.fmt_metrics()))
@@ -702,6 +711,7 @@ impl<T: Write> ConsoleTestState<T> {
                         TrFailed => "failed".to_owned(),
                         TrFailedMsg(ref msg) => format!("failed: {}", msg),
                         TrIgnored => "ignored".to_owned(),
+                        TrAllowedFail => "failed (allowed)".to_owned(),
                         TrMetrics(ref mm) => mm.fmt_metrics(),
                         TrBench(ref bs) => fmt_bench_samples(bs),
                     },
@@ -761,7 +771,8 @@ impl<T: Write> ConsoleTestState<T> {
     }
 
     pub fn write_run_finish(&mut self) -> io::Result<bool> {
-        assert!(self.passed + self.failed + self.ignored + self.measured == self.total);
+        assert!(self.passed + self.failed + self.ignored + self.measured +
+                    self.allowed_fail == self.total);
 
         if self.options.display_output {
             self.write_outputs()?;
@@ -778,12 +789,24 @@ impl<T: Write> ConsoleTestState<T> {
         } else {
             self.write_pretty("FAILED", term::color::RED)?;
         }
-        let s = format!(". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
-                        self.passed,
-                        self.failed,
-                        self.ignored,
-                        self.measured,
-                        self.filtered_out);
+        let s = if self.allowed_fail > 0 {
+            format!(
+                ". {} passed; {} failed ({} allowed); {} ignored; {} measured; {} filtered out\n\n",
+                self.passed,
+                self.failed + self.allowed_fail,
+                self.allowed_fail,
+                self.ignored,
+                self.measured,
+                self.filtered_out)
+        } else {
+            format!(
+                ". {} passed; {} failed; {} ignored; {} measured; {} filtered out\n\n",
+                self.passed,
+                self.failed,
+                self.ignored,
+                self.measured,
+                self.filtered_out)
+        };
         self.write_plain(&s)?;
         return Ok(success);
     }
@@ -891,6 +914,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
                         st.not_failures.push((test, stdout));
                     }
                     TrIgnored => st.ignored += 1,
+                    TrAllowedFail => st.allowed_fail += 1,
                     TrMetrics(mm) => {
                         let tname = test.name;
                         let MetricMap(mm) = mm;
@@ -945,12 +969,14 @@ fn should_sort_failures_before_printing_them() {
         name: StaticTestName("a"),
         ignore: false,
         should_panic: ShouldPanic::No,
+        allow_fail: false,
     };
 
     let test_b = TestDesc {
         name: StaticTestName("b"),
         ignore: false,
         should_panic: ShouldPanic::No,
+        allow_fail: false,
     };
 
     let mut st = ConsoleTestState {
@@ -962,6 +988,7 @@ fn should_sort_failures_before_printing_them() {
         passed: 0,
         failed: 0,
         ignored: 0,
+        allowed_fail: 0,
         filtered_out: 0,
         measured: 0,
         max_name_len: 10,
@@ -1471,8 +1498,13 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any + Send>>) -> Tes
                   .unwrap_or(false) {
                 TrOk
             } else {
-                TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+                if desc.allow_fail {
+                    TrAllowedFail
+                } else {
+                    TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+                }
             },
+        _ if desc.allow_fail => TrAllowedFail,
         _ => TrFailed,
     }
 }
@@ -1706,6 +1738,7 @@ mod tests {
                 name: StaticTestName("whatever"),
                 ignore: true,
                 should_panic: ShouldPanic::No,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1723,6 +1756,7 @@ mod tests {
                 name: StaticTestName("whatever"),
                 ignore: true,
                 should_panic: ShouldPanic::No,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1742,6 +1776,7 @@ mod tests {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::Yes,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1761,6 +1796,7 @@ mod tests {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::YesWithMessage("error message"),
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1782,6 +1818,7 @@ mod tests {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::YesWithMessage(expected),
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1799,6 +1836,7 @@ mod tests {
                 name: StaticTestName("whatever"),
                 ignore: false,
                 should_panic: ShouldPanic::Yes,
+                allow_fail: false,
             },
             testfn: DynTestFn(Box::new(move |()| f())),
         };
@@ -1832,6 +1870,7 @@ mod tests {
                                  name: StaticTestName("1"),
                                  ignore: true,
                                  should_panic: ShouldPanic::No,
+                                 allow_fail: false,
                              },
                              testfn: DynTestFn(Box::new(move |()| {})),
                          },
@@ -1840,6 +1879,7 @@ mod tests {
                                  name: StaticTestName("2"),
                                  ignore: false,
                                  should_panic: ShouldPanic::No,
+                                 allow_fail: false,
                              },
                              testfn: DynTestFn(Box::new(move |()| {})),
                          }];
@@ -1863,6 +1903,7 @@ mod tests {
                     name: StaticTestName(name),
                     ignore: false,
                     should_panic: ShouldPanic::No,
+                    allow_fail: false,
                 },
                 testfn: DynTestFn(Box::new(move |()| {}))
             })
@@ -1944,6 +1985,7 @@ mod tests {
                         name: DynTestName((*name).clone()),
                         ignore: false,
                         should_panic: ShouldPanic::No,
+                        allow_fail: false,
                     },
                     testfn: DynTestFn(Box::new(move |()| testfn())),
                 };
diff --git a/src/llvm b/src/llvm
-Subproject d8c9dfcc4f5289c09bab5736966feee2a0e6959
+Subproject 8e1b4fedfa4542e65f82fe124bd6433f3bd0aec
diff --git a/src/rustllvm/.editorconfig b/src/rustllvm/.editorconfig
new file mode 100644
index 00000000000..865cd45f708
--- /dev/null
+++ b/src/rustllvm/.editorconfig
@@ -0,0 +1,6 @@
+[*.{h,cpp}]
+end_of_line = lf
+insert_final_newline = true
+charset = utf-8
+indent_style = space
+indent_size = 2
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index fdbe4e5f7ad..7fb1eafb30d 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -10,11 +10,14 @@
 
 #include <stdio.h>
 
+#include <vector>
+
 #include "rustllvm.h"
 
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/IR/AutoUpgrade.h"
+#include "llvm/IR/AssemblyAnnotationWriter.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
@@ -503,8 +506,129 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
   return LLVMRustResult::Success;
 }
 
+
+// Callback to demangle function name
+// Parameters:
+// * name to be demangled
+// * name len
+// * output buffer
+// * output buffer len
+// Returns len of demangled string, or 0 if demangle failed.
+typedef size_t (*DemangleFn)(const char*, size_t, char*, size_t);
+
+
+namespace {
+
+class RustAssemblyAnnotationWriter : public AssemblyAnnotationWriter {
+  DemangleFn Demangle;
+  std::vector<char> Buf;
+
+public:
+  RustAssemblyAnnotationWriter(DemangleFn Demangle) : Demangle(Demangle) {}
+
+  // Return empty string if demangle failed
+  // or if name does not need to be demangled
+  StringRef CallDemangle(StringRef name) {
+    if (!Demangle) {
+      return StringRef();
+    }
+
+    if (Buf.size() < name.size() * 2) {
+      // Semangled name usually shorter than mangled,
+      // but allocate twice as much memory just in case
+      Buf.resize(name.size() * 2);
+    }
+
+    auto R = Demangle(name.data(), name.size(), Buf.data(), Buf.size());
+    if (!R) {
+      // Demangle failed.
+      return StringRef();
+    }
+
+    auto Demangled = StringRef(Buf.data(), R);
+    if (Demangled == name) {
+      // Do not print anything if demangled name is equal to mangled.
+      return StringRef();
+    }
+
+    return Demangled;
+  }
+
+  void emitFunctionAnnot(const Function *F,
+                         formatted_raw_ostream &OS) override {
+    StringRef Demangled = CallDemangle(F->getName());
+    if (Demangled.empty()) {
+        return;
+    }
+
+    OS << "; " << Demangled << "\n";
+  }
+
+  void emitInstructionAnnot(const Instruction *I,
+                            formatted_raw_ostream &OS) override {
+    const char *Name;
+    const Value *Value;
+    if (const CallInst *CI = dyn_cast<CallInst>(I)) {
+      Name = "call";
+      Value = CI->getCalledValue();
+    } else if (const InvokeInst* II = dyn_cast<InvokeInst>(I)) {
+      Name = "invoke";
+      Value = II->getCalledValue();
+    } else {
+      // Could demangle more operations, e. g.
+      // `store %place, @function`.
+      return;
+    }
+
+    if (!Value->hasName()) {
+      return;
+    }
+
+    StringRef Demangled = CallDemangle(Value->getName());
+    if (Demangled.empty()) {
+      return;
+    }
+
+    OS << "; " << Name << " " << Demangled << "\n";
+  }
+};
+
+class RustPrintModulePass : public ModulePass {
+  raw_ostream* OS;
+  DemangleFn Demangle;
+public:
+  static char ID;
+  RustPrintModulePass() : ModulePass(ID), OS(nullptr), Demangle(nullptr) {}
+  RustPrintModulePass(raw_ostream &OS, DemangleFn Demangle)
+      : ModulePass(ID), OS(&OS), Demangle(Demangle) {}
+
+  bool runOnModule(Module &M) override {
+    RustAssemblyAnnotationWriter AW(Demangle);
+
+    M.print(*OS, &AW, false);
+
+    return false;
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesAll();
+  }
+
+  static StringRef name() { return "RustPrintModulePass"; }
+};
+
+} // namespace
+
+namespace llvm {
+  void initializeRustPrintModulePassPass(PassRegistry&);
+}
+
+char RustPrintModulePass::ID = 0;
+INITIALIZE_PASS(RustPrintModulePass, "print-rust-module",
+                "Print rust module to stderr", false, false)
+
 extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
-                                    const char *Path) {
+                                    const char *Path, DemangleFn Demangle) {
   llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
   std::string ErrorInfo;
 
@@ -515,7 +639,7 @@ extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
 
   formatted_raw_ostream FOS(OS);
 
-  PM->add(createPrintModulePass(FOS));
+  PM->add(new RustPrintModulePass(FOS, Demangle));
 
   PM->run(*unwrap(M));
 }
diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger
index e547659d19a..37ba3264452 100644
--- a/src/rustllvm/llvm-rebuild-trigger
+++ b/src/rustllvm/llvm-rebuild-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2017-06-19
+2017-06-27
diff --git a/src/test/compile-fail/E0604.rs b/src/test/compile-fail/E0604.rs
new file mode 100644
index 00000000000..c5bf3a77b6c
--- /dev/null
+++ b/src/test/compile-fail/E0604.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() {
+    1u32 as char; //~ ERROR E0604
+}
diff --git a/src/test/compile-fail/E0605.rs b/src/test/compile-fail/E0605.rs
new file mode 100644
index 00000000000..add3fd8fd8a
--- /dev/null
+++ b/src/test/compile-fail/E0605.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.
+
+fn main() {
+    let x = 0u8;
+    x as Vec<u8>; //~ ERROR E0605
+                  //~| NOTE an `as` expression can only be used to convert between primitive types
+
+    let v = 0 as *const u8;
+    v as &u8; //~ ERROR E0605
+              //~| NOTE an `as` expression can only be used to convert between primitive types
+}
diff --git a/src/test/compile-fail/E0606.rs b/src/test/compile-fail/E0606.rs
new file mode 100644
index 00000000000..55071736bfe
--- /dev/null
+++ b/src/test/compile-fail/E0606.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() {
+    &0u8 as u8; //~ ERROR E0606
+}
diff --git a/src/test/compile-fail/E0607.rs b/src/test/compile-fail/E0607.rs
new file mode 100644
index 00000000000..fa761f2c178
--- /dev/null
+++ b/src/test/compile-fail/E0607.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let v = 0 as *const u8;
+    v as *const [u8]; //~ ERROR E0607
+}
diff --git a/src/test/compile-fail/E0619.rs b/src/test/compile-fail/E0619.rs
new file mode 100644
index 00000000000..a5a5ff7218d
--- /dev/null
+++ b/src/test/compile-fail/E0619.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.
+
+fn main() {
+    let x;
+
+    match x {
+        (..) => {} //~ ERROR E0619
+        _ => {}
+    }
+}
+
diff --git a/src/test/compile-fail/E0620.rs b/src/test/compile-fail/E0620.rs
new file mode 100644
index 00000000000..5e945dfa5c8
--- /dev/null
+++ b/src/test/compile-fail/E0620.rs
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let _foo = &[1_usize, 2] as [usize]; //~ ERROR E0620
+}
diff --git a/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs b/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs
new file mode 100644
index 00000000000..980461bedae
--- /dev/null
+++ b/src/test/compile-fail/E0621-does-not-trigger-for-closures.rs
@@ -0,0 +1,28 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we give the generic E0495 when one of the free regions is
+// bound in a closure (rather than suggesting a change to the signature
+// of the closure, which is not specified in `foo` but rather in `invoke`).
+
+// FIXME - This might be better as a UI test, but the finer details
+// of the error seem to vary on different machines.
+fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32
+where F: FnOnce(&'a i32, &i32) -> &'a i32
+{
+    let y = 22;
+    f(x, &y)
+}
+
+fn foo<'a>(x: &'a i32) {
+    invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/invalid-intrinsic.rs b/src/test/compile-fail/E0622.rs
index 2aa2546cb9f..f2bde5b0364 100644
--- a/src/test/compile-fail/invalid-intrinsic.rs
+++ b/src/test/compile-fail/E0622.rs
@@ -11,6 +11,6 @@
 #![feature(intrinsics)]
 extern "rust-intrinsic" {
     pub static breakpoint : unsafe extern "rust-intrinsic" fn();
-    //~^ ERROR intrinsic has wrong type
+    //~^ ERROR intrinsic must be a function [E0622]
 }
-fn main() { unsafe { breakpoint(); } }
\ No newline at end of file
+fn main() { unsafe { breakpoint(); } }
diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs
index cdb7dff692c..d62f6b0f1a3 100644
--- a/src/test/compile-fail/associated-types-path-2.rs
+++ b/src/test/compile-fail/associated-types-path-2.rs
@@ -38,11 +38,13 @@ pub fn f1_int_uint() {
 pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
+    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
diff --git a/src/test/compile-fail/cast-from-nil.rs b/src/test/compile-fail/cast-from-nil.rs
index 4c6dcaccc9a..ab22d352480 100644
--- a/src/test/compile-fail/cast-from-nil.rs
+++ b/src/test/compile-fail/cast-from-nil.rs
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: non-scalar cast: `()` as `u32`
+// error-pattern: non-primitive cast: `()` as `u32`
 fn main() { let u = (assert!(true) as u32); }
diff --git a/src/test/compile-fail/cast-to-bare-fn.rs b/src/test/compile-fail/cast-to-bare-fn.rs
index 7cc5c727bc7..d5a998c6e4b 100644
--- a/src/test/compile-fail/cast-to-bare-fn.rs
+++ b/src/test/compile-fail/cast-to-bare-fn.rs
@@ -13,8 +13,8 @@ fn foo(_x: isize) { }
 fn main() {
     let v: u64 = 5;
     let x = foo as extern "C" fn() -> isize;
-    //~^ ERROR non-scalar cast
+    //~^ ERROR non-primitive cast
     let y = v as extern "Rust" fn(isize) -> (isize, isize);
-    //~^ ERROR non-scalar cast
+    //~^ ERROR non-primitive cast
     y(x());
 }
diff --git a/src/test/compile-fail/cast-to-nil.rs b/src/test/compile-fail/cast-to-nil.rs
index e5fd5bb33eb..27d9e8a42b1 100644
--- a/src/test/compile-fail/cast-to-nil.rs
+++ b/src/test/compile-fail/cast-to-nil.rs
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: non-scalar cast: `u32` as `()`
+// error-pattern: non-primitive cast: `u32` as `()`
 fn main() { let u = 0u32 as (); }
diff --git a/src/test/compile-fail/closure-no-fn-3.rs b/src/test/compile-fail/closure-no-fn-3.rs
index 85dbc899208..6584c16c9de 100644
--- a/src/test/compile-fail/closure-no-fn-3.rs
+++ b/src/test/compile-fail/closure-no-fn-3.rs
@@ -14,5 +14,5 @@
 fn main() {
     let b = 0u8;
     let baz: fn() -> u8 = (|| { b }) as fn() -> u8;
-    //~^ ERROR non-scalar cast
+    //~^ ERROR non-primitive cast
 }
diff --git a/src/test/compile-fail/coerce-to-bang-cast.rs b/src/test/compile-fail/coerce-to-bang-cast.rs
index 57d2192e635..0479f5cce65 100644
--- a/src/test/compile-fail/coerce-to-bang-cast.rs
+++ b/src/test/compile-fail/coerce-to-bang-cast.rs
@@ -17,7 +17,7 @@ fn cast_a() {
 }
 
 fn cast_b() {
-    let y = 22 as !; //~ ERROR non-scalar cast
+    let y = 22 as !; //~ ERROR non-primitive cast
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/dollar-crate-is-keyword-2.rs b/src/test/compile-fail/dollar-crate-is-keyword-2.rs
new file mode 100644
index 00000000000..e221fc6e9e0
--- /dev/null
+++ b/src/test/compile-fail/dollar-crate-is-keyword-2.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod a {}
+
+macro_rules! m {
+    () => {
+        use a::$crate; //~ ERROR unresolved import `a::$crate`
+        use a::$crate::b; //~ ERROR unresolved import `a::$crate::b`
+        type A = a::$crate; //~ ERROR cannot find type `$crate` in module `a`
+    }
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/compile-fail/dollar-crate-is-keyword.rs b/src/test/compile-fail/dollar-crate-is-keyword.rs
new file mode 100644
index 00000000000..70597a230a8
--- /dev/null
+++ b/src/test/compile-fail/dollar-crate-is-keyword.rs
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! m {
+    () => {
+        struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate`
+
+        use $crate; // OK
+                    //~^ WARN `$crate` may not be imported
+        use $crate as $crate; //~ ERROR expected identifier, found reserved identifier `$crate`
+                              //~^ WARN `$crate` may not be imported
+    }
+}
+
+m!();
+
+fn main() {}
diff --git a/src/test/compile-fail/dst-bad-assign-3.rs b/src/test/compile-fail/dst-bad-assign-3.rs
new file mode 100644
index 00000000000..1c3bad5ba56
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-assign-3.rs
@@ -0,0 +1,50 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Forbid assignment into a dynamically sized type.
+
+#![feature(unsized_tuple_coercion)]
+
+type Fat<T: ?Sized> = (isize, &'static str, T);
+//~^ WARNING trait bounds are not (yet) enforced
+
+#[derive(PartialEq,Eq)]
+struct Bar;
+
+#[derive(PartialEq,Eq)]
+struct Bar1 {
+    f: isize
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> isize;
+}
+
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> isize {
+        self.f
+    }
+}
+
+pub fn main() {
+    // Assignment.
+    let f5: &mut Fat<ToBar> = &mut (5, "some str", Bar1 {f :42});
+    let z: Box<ToBar> = Box::new(Bar1 {f: 36});
+    f5.2 = Bar1 {f: 36};
+    //~^ ERROR mismatched types
+    //~| expected type `ToBar`
+    //~| found type `Bar1`
+    //~| expected trait ToBar, found struct `Bar1`
+    //~| ERROR `ToBar: std::marker::Sized` is not satisfied
+}
diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs
index 9a3ea54a3a4..b0de84a5300 100644
--- a/src/test/compile-fail/dst-bad-coerce1.rs
+++ b/src/test/compile-fail/dst-bad-coerce1.rs
@@ -10,6 +10,8 @@
 
 // Attempt to change the type as well as unsizing.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Fat<T: ?Sized> {
     ptr: T
 }
@@ -29,4 +31,16 @@ pub fn main() {
     let f2: &Fat<Foo> = &f1;
     let f3: &Fat<Bar> = f2;
     //~^ ERROR `Foo: Bar` is not satisfied
+
+    // Tuple with a vec of isize.
+    let f1 = ([1, 2, 3],);
+    let f2: &([isize; 3],) = &f1;
+    let f3: &([usize],) = f2;
+    //~^ ERROR mismatched types
+
+    // Tuple with a trait.
+    let f1 = (Foo,);
+    let f2: &(Foo,) = &f1;
+    let f3: &(Bar,) = f2;
+    //~^ ERROR `Foo: Bar` is not satisfied
 }
diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs
index 160197368d6..9e92f649b2d 100644
--- a/src/test/compile-fail/dst-bad-coerce2.rs
+++ b/src/test/compile-fail/dst-bad-coerce2.rs
@@ -28,4 +28,14 @@ pub fn main() {
     let f1 = Fat { ptr: Foo };
     let f2: &Fat<Foo> = &f1;
     let f3: &mut Fat<Bar> = f2; //~ ERROR mismatched types
+
+    // Tuple with a vec of ints.
+    let f1 = ([1, 2, 3],);
+    let f2: &([isize; 3],) = &f1;
+    let f3: &mut ([isize],) = f2; //~ ERROR mismatched types
+
+    // Tuple with a trait.
+    let f1 = (Foo,);
+    let f2: &(Foo,) = &f1;
+    let f3: &mut (Bar,) = f2; //~ ERROR mismatched types
 }
diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs
index 7bad3bd69d3..35a147c15bb 100644
--- a/src/test/compile-fail/dst-bad-coerce3.rs
+++ b/src/test/compile-fail/dst-bad-coerce3.rs
@@ -10,6 +10,8 @@
 
 // Attempt to extend the lifetime as well as unsizing.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Fat<T: ?Sized> {
     ptr: T
 }
@@ -28,6 +30,16 @@ fn baz<'a>() {
     let f1 = Fat { ptr: Foo };
     let f2: &Fat<Foo> = &f1; //~ ERROR `f1` does not live long enough
     let f3: &'a Fat<Bar> = f2;
+
+    // Tuple with a vec of ints.
+    let f1 = ([1, 2, 3],);
+    let f2: &([isize; 3],) = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a ([isize],) = f2;
+
+    // Tuple with a trait.
+    let f1 = (Foo,);
+    let f2: &(Foo,) = &f1; //~ ERROR `f1` does not live long enough
+    let f3: &'a (Bar,) = f2;
 }
 
 pub fn main() {
diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs
index 9d4d56cf791..874b7588ff9 100644
--- a/src/test/compile-fail/dst-bad-coerce4.rs
+++ b/src/test/compile-fail/dst-bad-coerce4.rs
@@ -10,6 +10,8 @@
 
 // Attempt to coerce from unsized to sized.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Fat<T: ?Sized> {
     ptr: T
 }
@@ -22,4 +24,12 @@ pub fn main() {
     //~| expected type `&Fat<[isize; 3]>`
     //~| found type `&Fat<[isize]>`
     //~| expected array of 3 elements, found slice
+
+    // Tuple with a vec of isizes.
+    let f1: &([isize],) = &([1, 2, 3],);
+    let f2: &([isize; 3],) = f1;
+    //~^ ERROR mismatched types
+    //~| expected type `&([isize; 3],)`
+    //~| found type `&([isize],)`
+    //~| expected array of 3 elements, found slice
 }
diff --git a/src/test/compile-fail/dst-bad-deep-2.rs b/src/test/compile-fail/dst-bad-deep-2.rs
new file mode 100644
index 00000000000..0c812b1d815
--- /dev/null
+++ b/src/test/compile-fail/dst-bad-deep-2.rs
@@ -0,0 +1,23 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Try to initialise a DST struct where the lost information is deeply nested.
+// This is an error because it requires an unsized rvalue. This is a problem
+// because it would require stack allocation of an unsized temporary (*g in the
+// test).
+
+#![feature(unsized_tuple_coercion)]
+
+pub fn main() {
+    let f: ([isize; 3],) = ([5, 6, 7],);
+    let g: &([isize],) = &f;
+    let h: &(([isize],),) = &(*g,);
+    //~^ ERROR `[isize]: std::marker::Sized` is not satisfied
+}
diff --git a/src/test/compile-fail/fat-ptr-cast.rs b/src/test/compile-fail/fat-ptr-cast.rs
index c62987a5b90..bc2dc1cc5d4 100644
--- a/src/test/compile-fail/fat-ptr-cast.rs
+++ b/src/test/compile-fail/fat-ptr-cast.rs
@@ -22,7 +22,7 @@ fn main() {
     a as isize; //~ ERROR casting
     a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
     a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
-    b as usize; //~ ERROR non-scalar cast
+    b as usize; //~ ERROR non-primitive cast
     p as usize;
     //~^ ERROR casting
     //~^^ HELP cast through a thin pointer
diff --git a/src/test/compile-fail/feature-gate-allow_fail.rs b/src/test/compile-fail/feature-gate-allow_fail.rs
new file mode 100644
index 00000000000..11247402809
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-allow_fail.rs
@@ -0,0 +1,17 @@
+// 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.
+
+// check that #[allow_fail] is feature-gated
+
+#[allow_fail] //~ ERROR allow_fail attribute is currently unstable
+fn ok_to_fail() {
+    assert!(false);
+}
+
diff --git a/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
new file mode 100644
index 00000000000..4ddde011263
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-unsized_tuple_coercion.rs
@@ -0,0 +1,14 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let _ : &(Send,) = &((),);
+    //~^ ERROR Unsized tuple coercion is not stable enough
+}
diff --git a/src/test/compile-fail/issue-10991.rs b/src/test/compile-fail/issue-10991.rs
index 25060b94dcf..2d00f339f33 100644
--- a/src/test/compile-fail/issue-10991.rs
+++ b/src/test/compile-fail/issue-10991.rs
@@ -10,5 +10,5 @@
 
 fn main() {
     let nil = ();
-    let _t = nil as usize; //~ ERROR: non-scalar cast: `()` as `usize`
+    let _t = nil as usize; //~ ERROR: non-primitive cast: `()` as `usize`
 }
diff --git a/src/test/compile-fail/issue-22289.rs b/src/test/compile-fail/issue-22289.rs
index bcbc414d353..c23fc4f3344 100644
--- a/src/test/compile-fail/issue-22289.rs
+++ b/src/test/compile-fail/issue-22289.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    0 as &std::any::Any; //~ ERROR non-scalar cast
+    0 as &std::any::Any; //~ ERROR non-primitive cast
 }
diff --git a/src/test/compile-fail/issue-22312.rs b/src/test/compile-fail/issue-22312.rs
index 4d6e6eded21..2128c420630 100644
--- a/src/test/compile-fail/issue-22312.rs
+++ b/src/test/compile-fail/issue-22312.rs
@@ -19,7 +19,7 @@ pub trait Array2D: Index<usize> {
         }
         let i = y * self.columns() + x;
         let indexer = &(*self as &Index<usize, Output = <Self as Index<usize>>::Output>);
-        //~^ERROR non-scalar cast
+        //~^ERROR non-primitive cast
         Some(indexer.index(i))
     }
 }
diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs
index 28109747b75..129f7c8b1ea 100644
--- a/src/test/compile-fail/issue-23046.rs
+++ b/src/test/compile-fail/issue-23046.rs
@@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
 }
 
 fn main() {
-    let ex = |x| {
-        let_(add(x,x), |y| { //~ ERROR type annotations needed
+    let ex = |x| { //~ ERROR type annotations needed
+        let_(add(x,x), |y| {
             let_(add(x, x), |x|x)})};
 }
diff --git a/src/test/compile-fail/issue-2995.rs b/src/test/compile-fail/issue-2995.rs
index 8fbf97411cc..d735e184d5c 100644
--- a/src/test/compile-fail/issue-2995.rs
+++ b/src/test/compile-fail/issue-2995.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn bad (p: *const isize) {
-    let _q: &isize = p as &isize; //~ ERROR non-scalar cast
+    let _q: &isize = p as &isize; //~ ERROR non-primitive cast
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-38954.rs b/src/test/compile-fail/issue-38954.rs
index 65b17a3db0b..896728b6da0 100644
--- a/src/test/compile-fail/issue-38954.rs
+++ b/src/test/compile-fail/issue-38954.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs)]
-
 fn _test(ref _p: str) {}
+//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied [E0277]
 
-#[rustc_error]
-fn main() { } //~ ERROR compilation successful
+fn main() { }
diff --git a/src/test/compile-fail/issue-42312.rs b/src/test/compile-fail/issue-42312.rs
new file mode 100644
index 00000000000..06573b42b59
--- /dev/null
+++ b/src/test/compile-fail/issue-42312.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::Deref;
+
+pub trait Foo {
+    fn baz(_: Self::Target) where Self: Deref {}
+    //~^ ERROR `<Self as std::ops::Deref>::Target: std::marker::Sized` is not satisfied
+}
+
+pub fn f(_: ToString) {}
+//~^ ERROR the trait bound `std::string::ToString + 'static: std::marker::Sized` is not satisfied
+
+fn main() { }
diff --git a/src/test/compile-fail/issue-42880.rs b/src/test/compile-fail/issue-42880.rs
new file mode 100644
index 00000000000..ebb1ec425d1
--- /dev/null
+++ b/src/test/compile-fail/issue-42880.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.
+
+type Value = String;
+
+fn main() {
+    let f = |&Value::String(_)| (); //~ ERROR no associated item named
+
+    let vec: Vec<Value> = Vec::new();
+    vec.last().map(f);
+}
diff --git a/src/test/compile-fail/nonscalar-cast.rs b/src/test/compile-fail/nonscalar-cast.rs
index d6f274da967..0abbc05eef0 100644
--- a/src/test/compile-fail/nonscalar-cast.rs
+++ b/src/test/compile-fail/nonscalar-cast.rs
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:non-scalar cast
-
 #[derive(Debug)]
 struct foo {
     x: isize
 }
 
 fn main() {
-    println!("{}", foo{ x: 1 } as isize);
+    println!("{}", foo{ x: 1 } as isize); //~ non-primitive cast: `foo` as `isize` [E0605]
 }
diff --git a/src/test/compile-fail/on-unimplemented/multiple-impls.rs b/src/test/compile-fail/on-unimplemented/multiple-impls.rs
index 0df8c41ffe1..15375936b89 100644
--- a/src/test/compile-fail/on-unimplemented/multiple-impls.rs
+++ b/src/test/compile-fail/on-unimplemented/multiple-impls.rs
@@ -44,12 +44,18 @@ fn main() {
     //~^ ERROR E0277
     //~| NOTE trait message
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE trait message
     Index::index(&[] as &[i32], Foo(2u32));
     //~^ ERROR E0277
     //~| NOTE on impl for Foo
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE on impl for Foo
     Index::index(&[] as &[i32], Bar(2u32));
     //~^ ERROR E0277
     //~| NOTE on impl for Bar
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE on impl for Bar
 }
diff --git a/src/test/compile-fail/on-unimplemented/on-impl.rs b/src/test/compile-fail/on-unimplemented/on-impl.rs
index 79021cd03cc..66d612baab4 100644
--- a/src/test/compile-fail/on-unimplemented/on-impl.rs
+++ b/src/test/compile-fail/on-unimplemented/on-impl.rs
@@ -33,4 +33,6 @@ fn main() {
     //~^ ERROR E0277
     //~| NOTE a usize is required
     //~| NOTE required by
+    //~| ERROR E0277
+    //~| NOTE a usize is required
 }
diff --git a/src/test/compile-fail/patkind-litrange-no-expr.rs b/src/test/compile-fail/patkind-litrange-no-expr.rs
new file mode 100644
index 00000000000..afb2cbb7db3
--- /dev/null
+++ b/src/test/compile-fail/patkind-litrange-no-expr.rs
@@ -0,0 +1,36 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! enum_number {
+    ($name:ident { $($variant:ident = $value:expr, )* }) => {
+        enum $name {
+            $($variant = $value,)*
+        }
+
+        fn foo(value: i32) -> Option<$name> {
+            match value {
+                $( $value => Some($name::$variant), )* // PatKind::Lit
+                $( $value ... 42 => Some($name::$variant), )* // PatKind::Range
+                _ => None
+            }
+        }
+    }
+}
+
+enum_number!(Change {
+    Pos = 1,
+    Neg = -1,
+    Arith = 1 + 1, //~ ERROR arbitrary expressions aren't allowed in patterns
+                   //~^ ERROR arbitrary expressions aren't allowed in patterns
+                   //~^^ ERROR only char and numeric types are allowed in range patterns
+});
+
+fn main() {}
+
diff --git a/src/test/compile-fail/tag-variant-cast-non-nullary.rs b/src/test/compile-fail/tag-variant-cast-non-nullary.rs
index b0106329126..220537633ea 100644
--- a/src/test/compile-fail/tag-variant-cast-non-nullary.rs
+++ b/src/test/compile-fail/tag-variant-cast-non-nullary.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//error-pattern: non-scalar cast
-
 enum non_nullary {
     nullary,
     other(isize),
@@ -17,5 +15,5 @@ enum non_nullary {
 
 fn main() {
     let v = non_nullary::nullary;
-    let val = v as isize;
+    let val = v as isize; //~ ERROR non-primitive cast: `non_nullary` as `isize` [E0605]
 }
diff --git a/src/test/compile-fail/uninhabited-enum-cast.rs b/src/test/compile-fail/uninhabited-enum-cast.rs
index b4df5fb1e2a..2a5d25e6b98 100644
--- a/src/test/compile-fail/uninhabited-enum-cast.rs
+++ b/src/test/compile-fail/uninhabited-enum-cast.rs
@@ -11,7 +11,7 @@
 enum E {}
 
 fn f(e: E) {
-    println!("{}", (e as isize).to_string());   //~ ERROR non-scalar cast
+    println!("{}", (e as isize).to_string());   //~ ERROR non-primitive cast
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs
index 9b6ccf22c8d..e96e0ea3aec 100644
--- a/src/test/compile-fail/unsized3.rs
+++ b/src/test/compile-fail/unsized3.rs
@@ -54,6 +54,7 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
 fn f10<X: ?Sized>(x1: Box<S<X>>) {
     f5(&(32, *x1));
     //~^ ERROR `X: std::marker::Sized` is not satisfied
+    //~| ERROR `X: std::marker::Sized` is not satisfied
 }
 
 pub fn main() {
diff --git a/src/test/compile-fail/use-self-type.rs b/src/test/compile-fail/use-self-type.rs
new file mode 100644
index 00000000000..6b5286bf0a7
--- /dev/null
+++ b/src/test/compile-fail/use-self-type.rs
@@ -0,0 +1,21 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S;
+
+impl S {
+    fn f() {}
+    fn g() {
+        use Self::f; //~ ERROR unresolved import
+        pub(in Self::f) struct Z; //~ ERROR Use of undeclared type or module `Self`
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs
index 58fb785c48c..9b88e38e085 100644
--- a/src/test/compile-fail/variance-trait-bounds.rs
+++ b/src/test/compile-fail/variance-trait-bounds.rs
@@ -14,13 +14,11 @@
 // Check that bounds on type parameters (other than `Self`) do not
 // influence variance.
 
-#[rustc_variance]
-trait Getter<T> { //~ ERROR [o, o]
+trait Getter<T> {
     fn get(&self) -> T;
 }
 
-#[rustc_variance]
-trait Setter<T> { //~ ERROR [o, o]
+trait Setter<T> {
     fn get(&self, T);
 }
 
@@ -35,20 +33,6 @@ enum TestEnum<U,T:Setter<U>> { //~ ERROR [*, +]
 }
 
 #[rustc_variance]
-trait TestTrait<U,T:Setter<U>> { //~ ERROR [o, o, o]
-    fn getter(&self, u: U) -> T;
-}
-
-#[rustc_variance]
-trait TestTrait2<U> : Getter<U> { //~ ERROR [o, o]
-}
-
-#[rustc_variance]
-trait TestTrait3<U> { //~ ERROR [o, o]
-    fn getter<T:Getter<U>>(&self);
-}
-
-#[rustc_variance]
 struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [*, +]
     t: T
 }
diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs
index 2df94cc907a..5075dd2ceed 100644
--- a/src/test/compile-fail/variance-types-bounds.rs
+++ b/src/test/compile-fail/variance-types-bounds.rs
@@ -36,38 +36,15 @@ struct TestIndirect2<A:'static, B:'static> { //~ ERROR [o, o]
     m: TestMut<B, A>
 }
 
-#[rustc_variance]
-trait Getter<A> { //~ ERROR [o, o]
+trait Getter<A> {
     fn get(&self) -> A;
 }
 
-#[rustc_variance]
-trait Setter<A> { //~ ERROR [o, o]
-    fn set(&mut self, a: A);
-}
-
-#[rustc_variance]
-trait GetterSetter<A> { //~ ERROR [o, o]
-    fn get(&self) -> A;
+trait Setter<A> {
     fn set(&mut self, a: A);
 }
 
 #[rustc_variance]
-trait GetterInTypeBound<A> { //~ ERROR [o, o]
-    // Here, the use of `A` in the method bound *does* affect
-    // variance.  Think of it as if the method requested a dictionary
-    // for `T:Getter<A>`.  Since this dictionary is an input, it is
-    // contravariant, and the Getter is covariant w/r/t A, yielding an
-    // overall contravariant result.
-    fn do_it<T:Getter<A>>(&self);
-}
-
-#[rustc_variance]
-trait SetterInTypeBound<A> { //~ ERROR [o, o]
-    fn do_it<T:Setter<A>>(&self);
-}
-
-#[rustc_variance]
 struct TestObject<A, R> { //~ ERROR [o, o]
     n: Box<Setter<A>+Send>,
     m: Box<Getter<R>+Send>,
diff --git a/src/test/parse-fail/macro-keyword.rs b/src/test/parse-fail/macro-keyword.rs
index 6a7ccff1554..c7dcaf4137e 100644
--- a/src/test/parse-fail/macro-keyword.rs
+++ b/src/test/parse-fail/macro-keyword.rs
@@ -10,7 +10,7 @@
 
 // compile-flags: -Z parse-only
 
-fn macro() {  //~ ERROR `macro` is a reserved keyword
+fn macro() {  //~ ERROR expected identifier, found reserved keyword `macro`
 }
 
 pub fn main() {
diff --git a/src/test/run-make/llvm-phase/test.rs b/src/test/run-make/llvm-phase/test.rs
index ca58e007852..a75dc7e57a9 100644
--- a/src/test/run-make/llvm-phase/test.rs
+++ b/src/test/run-make/llvm-phase/test.rs
@@ -85,6 +85,6 @@ fn main() {
     let (result, _) = rustc_driver::run_compiler(
         &args, &mut JitCalls, Some(box JitLoader), None);
     if let Err(n) = result {
-        panic!("Error {}", n);
+        panic!("Error {:?}", n);
     }
 }
diff --git a/src/test/run-pass-valgrind/dst-dtor-3.rs b/src/test/run-pass-valgrind/dst-dtor-3.rs
new file mode 100644
index 00000000000..1ae66a28a84
--- /dev/null
+++ b/src/test/run-pass-valgrind/dst-dtor-3.rs
@@ -0,0 +1,34 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![feature(unsized_tuple_coercion)]
+
+static mut DROP_RAN: bool = false;
+
+struct Foo;
+impl Drop for Foo {
+    fn drop(&mut self) {
+        unsafe { DROP_RAN = true; }
+    }
+}
+
+trait Trait { fn dummy(&self) { } }
+impl Trait for Foo {}
+
+pub fn main() {
+    {
+        let _x: Box<(i32, Trait)> = Box::<(i32, Foo)>::new((42, Foo));
+    }
+    unsafe {
+        assert!(DROP_RAN);
+    }
+}
diff --git a/src/test/run-pass-valgrind/dst-dtor-4.rs b/src/test/run-pass-valgrind/dst-dtor-4.rs
new file mode 100644
index 00000000000..e416f25bc03
--- /dev/null
+++ b/src/test/run-pass-valgrind/dst-dtor-4.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![feature(unsized_tuple_coercion)]
+
+static mut DROP_RAN: isize = 0;
+
+struct Foo;
+impl Drop for Foo {
+    fn drop(&mut self) {
+        unsafe { DROP_RAN += 1; }
+    }
+}
+
+pub fn main() {
+    {
+        let _x: Box<(i32, [Foo])> = Box::<(i32, [Foo; 3])>::new((42, [Foo, Foo, Foo]));
+    }
+    unsafe {
+        assert_eq!(DROP_RAN, 3);
+    }
+}
diff --git a/src/test/run-pass/allocator-alloc-one.rs b/src/test/run-pass/allocator-alloc-one.rs
new file mode 100644
index 00000000000..7cc547dcc04
--- /dev/null
+++ b/src/test/run-pass/allocator-alloc-one.rs
@@ -0,0 +1,27 @@
+// 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(alloc, allocator_api, heap_api, unique)]
+
+extern crate alloc;
+
+use alloc::heap::HeapAlloc;
+use alloc::allocator::Alloc;
+
+fn main() {
+    unsafe {
+        let ptr = HeapAlloc.alloc_one::<i32>().unwrap_or_else(|e| {
+            HeapAlloc.oom(e)
+        });
+        *ptr.as_ptr() = 4;
+        assert_eq!(*ptr.as_ptr(), 4);
+        HeapAlloc.dealloc_one(ptr);
+    }
+}
diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs
index 587fb3f80d6..d8d42f2cba2 100644
--- a/src/test/run-pass/associated-types-sugar-path.rs
+++ b/src/test/run-pass/associated-types-sugar-path.rs
@@ -15,8 +15,6 @@ use std::ops::Deref;
 pub trait Foo {
     type A;
     fn boo(&self) -> Self::A;
-
-    fn baz(_: Self::Target) where Self: Deref {}
 }
 
 impl Foo for isize {
diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs
index 91bfc2f9201..18b2fbe015b 100644
--- a/src/test/run-pass/deriving-hash.rs
+++ b/src/test/run-pass/deriving-hash.rs
@@ -45,8 +45,8 @@ impl<'a> Hasher for FakeHasher<'a> {
     }
 }
 
-fn fake_hash(v: &mut Vec<u8>, e: E) {
-    e.hash(&mut FakeHasher(v));
+fn fake_hash<A: Hash>(v: &mut Vec<u8>, a: A) {
+    a.hash(&mut FakeHasher(v));
 }
 
 fn main() {
@@ -69,4 +69,13 @@ fn main() {
     fake_hash(&mut va, E::A);
     fake_hash(&mut vb, E::B);
     assert!(va != vb);
+
+    // issue #39137: single variant enum hash should not hash discriminant
+    #[derive(Hash)]
+    enum SingleVariantEnum {
+        A(u8),
+    }
+    let mut v = vec![];
+    fake_hash(&mut v, SingleVariantEnum::A(17));
+    assert_eq!(vec![17], v);
 }
diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs
index 9f8067f372a..b1d6c732e7f 100644
--- a/src/test/run-pass/dst-irrefutable-bind.rs
+++ b/src/test/run-pass/dst-irrefutable-bind.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unsized_tuple_coercion)]
+
 struct Test<T: ?Sized>(T);
 
 fn main() {
@@ -21,4 +23,14 @@ fn main() {
     let slice = &[1,2,3];
     let x = Test(&slice);
     let Test(&_slice) = x;
+
+
+    let x = (10, [1,2,3]);
+    let x : &(i32, [i32]) = &x;
+
+    let & ref _y = x;
+
+    let slice = &[1,2,3];
+    let x = (10, &slice);
+    let (_, &_slice) = x;
 }
diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs
index 3a74626b029..9ebfbee8a33 100644
--- a/src/test/run-pass/dst-raw.rs
+++ b/src/test/run-pass/dst-raw.rs
@@ -11,6 +11,8 @@
 // Test DST raw pointers
 
 
+#![feature(unsized_tuple_coercion)]
+
 trait Trait {
     fn foo(&self) -> isize;
 }
@@ -45,6 +47,14 @@ pub fn main() {
     };
     assert_eq!(r, 42);
 
+    // raw DST tuple
+    let p = (A { f: 42 },);
+    let o: *const (Trait,) = &p;
+    let r = unsafe {
+        (&*o).0.foo()
+    };
+    assert_eq!(r, 42);
+
     // raw slice
     let a: *const [_] = &[1, 2, 3];
     unsafe {
@@ -72,6 +82,15 @@ pub fn main() {
         assert_eq!(len, 3);
     }
 
+    // raw DST tuple with slice
+    let c: *const ([_],) = &([1, 2, 3],);
+    unsafe {
+        let b = (&*c).0[0];
+        assert_eq!(b, 1);
+        let len = (&*c).0.len();
+        assert_eq!(len, 3);
+    }
+
     // all of the above with *mut
     let mut x = A { f: 42 };
     let z: *mut Trait = &mut x;
@@ -87,6 +106,13 @@ pub fn main() {
     };
     assert_eq!(r, 42);
 
+    let mut p = (A { f: 42 },);
+    let o: *mut (Trait,) = &mut p;
+    let r = unsafe {
+        (&*o).0.foo()
+    };
+    assert_eq!(r, 42);
+
     let a: *mut [_] = &mut [1, 2, 3];
     unsafe {
         let b = (*a)[2];
@@ -110,4 +136,12 @@ pub fn main() {
         let len = (&*c).f.len();
         assert_eq!(len, 3);
     }
+
+    let c: *mut ([_],) = &mut ([1, 2, 3],);
+    unsafe {
+        let b = (&*c).0[0];
+        assert_eq!(b, 1);
+        let len = (&*c).0.len();
+        assert_eq!(len, 3);
+    }
 }
diff --git a/src/test/run-pass/dst-trait-tuple.rs b/src/test/run-pass/dst-trait-tuple.rs
new file mode 100644
index 00000000000..9803e26f5f8
--- /dev/null
+++ b/src/test/run-pass/dst-trait-tuple.rs
@@ -0,0 +1,111 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![allow(unused_features)]
+#![feature(box_syntax)]
+#![feature(unsized_tuple_coercion)]
+
+type Fat<T: ?Sized> = (isize, &'static str, T);
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+struct Bar;
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+struct Bar1 {
+    f: isize
+}
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+    fn to_val(&self) -> isize;
+}
+
+impl ToBar for Bar {
+    fn to_bar(&self) -> Bar {
+        *self
+    }
+    fn to_val(&self) -> isize {
+        0
+    }
+}
+impl ToBar for Bar1 {
+    fn to_bar(&self) -> Bar {
+        Bar
+    }
+    fn to_val(&self) -> isize {
+        self.f
+    }
+}
+
+// x is a fat pointer
+fn foo(x: &Fat<ToBar>) {
+    assert_eq!(x.0, 5);
+    assert_eq!(x.1, "some str");
+    assert_eq!(x.2.to_bar(), Bar);
+    assert_eq!(x.2.to_val(), 42);
+
+    let y = &x.2;
+    assert_eq!(y.to_bar(), Bar);
+    assert_eq!(y.to_val(), 42);
+}
+
+fn bar(x: &ToBar) {
+    assert_eq!(x.to_bar(), Bar);
+    assert_eq!(x.to_val(), 42);
+}
+
+fn baz(x: &Fat<Fat<ToBar>>) {
+    assert_eq!(x.0, 5);
+    assert_eq!(x.1, "some str");
+    assert_eq!((x.2).0, 8);
+    assert_eq!((x.2).1, "deep str");
+    assert_eq!((x.2).2.to_bar(), Bar);
+    assert_eq!((x.2).2.to_val(), 42);
+
+    let y = &(x.2).2;
+    assert_eq!(y.to_bar(), Bar);
+    assert_eq!(y.to_val(), 42);
+
+}
+
+pub fn main() {
+    let f1 = (5, "some str", Bar1 {f :42});
+    foo(&f1);
+    let f2 = &f1;
+    foo(f2);
+    let f3: &Fat<ToBar> = f2;
+    foo(f3);
+    let f4: &Fat<ToBar> = &f1;
+    foo(f4);
+    let f5: &Fat<ToBar> = &(5, "some str", Bar1 {f :42});
+    foo(f5);
+
+    // Zero size object.
+    let f6: &Fat<ToBar> = &(5, "some str", Bar);
+    assert_eq!(f6.2.to_bar(), Bar);
+
+    // &*
+    //
+    let f7: Box<ToBar> = Box::new(Bar1 {f :42});
+    bar(&*f7);
+
+    // Deep nesting
+    let f1 = (5, "some str", (8, "deep str", Bar1 {f :42}));
+    baz(&f1);
+    let f2 = &f1;
+    baz(f2);
+    let f3: &Fat<Fat<ToBar>> = f2;
+    baz(f3);
+    let f4: &Fat<Fat<ToBar>> = &f1;
+    baz(f4);
+    let f5: &Fat<Fat<ToBar>> = &(5, "some str", (8, "deep str", Bar1 {f :42}));
+    baz(f5);
+}
diff --git a/src/test/run-pass/dst-tuple-sole.rs b/src/test/run-pass/dst-tuple-sole.rs
new file mode 100644
index 00000000000..a788e25218e
--- /dev/null
+++ b/src/test/run-pass/dst-tuple-sole.rs
@@ -0,0 +1,85 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// As dst-tuple.rs, but the unsized field is the only field in the tuple.
+
+
+#![feature(unsized_tuple_coercion)]
+
+type Fat<T: ?Sized> = (T,);
+
+// x is a fat pointer
+fn foo(x: &Fat<[isize]>) {
+    let y = &x.0;
+    assert_eq!(x.0.len(), 3);
+    assert_eq!(y[0], 1);
+    assert_eq!(x.0[1], 2);
+}
+
+fn foo2<T:ToBar>(x: &Fat<[T]>) {
+    let y = &x.0;
+    let bar = Bar;
+    assert_eq!(x.0.len(), 3);
+    assert_eq!(y[0].to_bar(), bar);
+    assert_eq!(x.0[1].to_bar(), bar);
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+struct Bar;
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+}
+
+impl ToBar for Bar {
+    fn to_bar(&self) -> Bar {
+        *self
+    }
+}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = ([1, 2, 3],);
+    foo(&f1);
+    let f2 = &f1;
+    foo(f2);
+    let f3: &Fat<[isize]> = f2;
+    foo(f3);
+    let f4: &Fat<[isize]> = &f1;
+    foo(f4);
+    let f5: &Fat<[isize]> = &([1, 2, 3],);
+    foo(f5);
+
+    // With a vec of Bars.
+    let bar = Bar;
+    let f1 = ([bar, bar, bar],);
+    foo2(&f1);
+    let f2 = &f1;
+    foo2(f2);
+    let f3: &Fat<[Bar]> = f2;
+    foo2(f3);
+    let f4: &Fat<[Bar]> = &f1;
+    foo2(f4);
+    let f5: &Fat<[Bar]> = &([bar, bar, bar],);
+    foo2(f5);
+
+    // Assignment.
+    let f5: &mut Fat<[isize]> = &mut ([1, 2, 3],);
+    f5.0[1] = 34;
+    assert_eq!(f5.0[0], 1);
+    assert_eq!(f5.0[1], 34);
+    assert_eq!(f5.0[2], 3);
+
+    // Zero size vec.
+    let f5: &Fat<[isize]> = &([],);
+    assert!(f5.0.is_empty());
+    let f5: &Fat<[Bar]> = &([],);
+    assert!(f5.0.is_empty());
+}
diff --git a/src/test/run-pass/dst-tuple.rs b/src/test/run-pass/dst-tuple.rs
new file mode 100644
index 00000000000..2f5b28495b8
--- /dev/null
+++ b/src/test/run-pass/dst-tuple.rs
@@ -0,0 +1,129 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![allow(unknown_features)]
+#![feature(box_syntax)]
+#![feature(unsized_tuple_coercion)]
+
+type Fat<T: ?Sized> = (isize, &'static str, T);
+
+// x is a fat pointer
+fn foo(x: &Fat<[isize]>) {
+    let y = &x.2;
+    assert_eq!(x.2.len(), 3);
+    assert_eq!(y[0], 1);
+    assert_eq!(x.2[1], 2);
+    assert_eq!(x.0, 5);
+    assert_eq!(x.1, "some str");
+}
+
+fn foo2<T:ToBar>(x: &Fat<[T]>) {
+    let y = &x.2;
+    let bar = Bar;
+    assert_eq!(x.2.len(), 3);
+    assert_eq!(y[0].to_bar(), bar);
+    assert_eq!(x.2[1].to_bar(), bar);
+    assert_eq!(x.0, 5);
+    assert_eq!(x.1, "some str");
+}
+
+fn foo3(x: &Fat<Fat<[isize]>>) {
+    let y = &(x.2).2;
+    assert_eq!(x.0, 5);
+    assert_eq!(x.1, "some str");
+    assert_eq!((x.2).0, 8);
+    assert_eq!((x.2).1, "deep str");
+    assert_eq!((x.2).2.len(), 3);
+    assert_eq!(y[0], 1);
+    assert_eq!((x.2).2[1], 2);
+}
+
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+struct Bar;
+
+trait ToBar {
+    fn to_bar(&self) -> Bar;
+}
+
+impl ToBar for Bar {
+    fn to_bar(&self) -> Bar {
+        *self
+    }
+}
+
+pub fn main() {
+    // With a vec of ints.
+    let f1 = (5, "some str", [1, 2, 3]);
+    foo(&f1);
+    let f2 = &f1;
+    foo(f2);
+    let f3: &Fat<[isize]> = f2;
+    foo(f3);
+    let f4: &Fat<[isize]> = &f1;
+    foo(f4);
+    let f5: &Fat<[isize]> = &(5, "some str", [1, 2, 3]);
+    foo(f5);
+
+    // With a vec of Bars.
+    let bar = Bar;
+    let f1 = (5, "some str", [bar, bar, bar]);
+    foo2(&f1);
+    let f2 = &f1;
+    foo2(f2);
+    let f3: &Fat<[Bar]> = f2;
+    foo2(f3);
+    let f4: &Fat<[Bar]> = &f1;
+    foo2(f4);
+    let f5: &Fat<[Bar]> = &(5, "some str", [bar, bar, bar]);
+    foo2(f5);
+
+    // Assignment.
+    let f5: &mut Fat<[isize]> = &mut (5, "some str", [1, 2, 3]);
+    f5.2[1] = 34;
+    assert_eq!(f5.2[0], 1);
+    assert_eq!(f5.2[1], 34);
+    assert_eq!(f5.2[2], 3);
+
+    // Zero size vec.
+    let f5: &Fat<[isize]> = &(5, "some str", []);
+    assert!(f5.2.is_empty());
+    let f5: &Fat<[Bar]> = &(5, "some str", []);
+    assert!(f5.2.is_empty());
+
+    // Deeply nested.
+    let f1 = (5, "some str", (8, "deep str", [1, 2, 3]));
+    foo3(&f1);
+    let f2 = &f1;
+    foo3(f2);
+    let f3: &Fat<Fat<[isize]>> = f2;
+    foo3(f3);
+    let f4: &Fat<Fat<[isize]>> = &f1;
+    foo3(f4);
+    let f5: &Fat<Fat<[isize]>> = &(5, "some str", (8, "deep str", [1, 2, 3]));
+    foo3(f5);
+
+    // Box.
+    let f1 = Box::new([1, 2, 3]);
+    assert_eq!((*f1)[1], 2);
+    let f2: Box<[isize]> = f1;
+    assert_eq!((*f2)[1], 2);
+
+    // Nested Box.
+    let f1 : Box<Fat<[isize; 3]>> = box (5, "some str", [1, 2, 3]);
+    foo(&*f1);
+    let f2 : Box<Fat<[isize]>> = f1;
+    foo(&*f2);
+
+    let f3 : Box<Fat<[isize]>> =
+        Box::<Fat<[_; 3]>>::new((5, "some str", [1, 2, 3]));
+    foo(&*f3);
+}
diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs
index 6725a0c547f..bdcd3eecc69 100644
--- a/src/test/run-pass/dynamic-drop.rs
+++ b/src/test/run-pass/dynamic-drop.rs
@@ -106,6 +106,18 @@ fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) {
     }
 }
 
+fn field_assignment(a: &Allocator, c0: bool) {
+    let mut x = (TwoPtrs(a.alloc(), a.alloc()), a.alloc());
+
+    x.1 = a.alloc();
+    x.1 = a.alloc();
+
+    let f = (x.0).0;
+    if c0 {
+        (x.0).0 = f;
+    }
+}
+
 fn assignment2(a: &Allocator, c0: bool, c1: bool) {
     let mut _v = a.alloc();
     let mut _w = a.alloc();
@@ -207,5 +219,8 @@ fn main() {
     run_test(|a| struct_dynamic_drop(a, true, true, false));
     run_test(|a| struct_dynamic_drop(a, true, true, true));
 
+    run_test(|a| field_assignment(a, false));
+    run_test(|a| field_assignment(a, true));
+
     run_test_nopanic(|a| union1(a));
 }
diff --git a/src/test/run-pass/env.rs b/src/test/run-pass/env.rs
new file mode 100644
index 00000000000..e602fb2d7d2
--- /dev/null
+++ b/src/test/run-pass/env.rs
@@ -0,0 +1,98 @@
+// 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: --test
+
+#![feature(rand, std_panic)]
+
+use std::env::*;
+use std::__rand as rand;
+use std::__rand::Rng;
+use std::iter::repeat;
+use std::ffi::{OsString, OsStr};
+
+
+fn make_rand_name() -> OsString {
+    let mut rng = rand::thread_rng();
+    let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
+                                 .collect::<String>());
+    let n = OsString::from(n);
+    assert!(var_os(&n).is_none());
+    n
+}
+
+fn eq(a: Option<OsString>, b: Option<&str>) {
+    assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
+}
+
+#[test]
+fn test_set_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    eq(var_os(&n), Some("VALUE"));
+}
+
+#[test]
+fn test_remove_var() {
+    let n = make_rand_name();
+    set_var(&n, "VALUE");
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_set_var_overwrite() {
+    let n = make_rand_name();
+    set_var(&n, "1");
+    set_var(&n, "2");
+    eq(var_os(&n), Some("2"));
+    set_var(&n, "");
+    eq(var_os(&n), Some(""));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_var_big() {
+    let mut s = "".to_string();
+    let mut i = 0;
+    while i < 100 {
+        s.push_str("aaaaaaaaaa");
+        i += 1;
+    }
+    let n = make_rand_name();
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn test_env_set_get_huge() {
+    let n = make_rand_name();
+    let s = repeat("x").take(10000).collect::<String>();
+    set_var(&n, &s);
+    eq(var_os(&n), Some(&s));
+    remove_var(&n);
+    eq(var_os(&n), None);
+}
+
+#[test]
+fn test_env_set_var() {
+    let n = make_rand_name();
+
+    let mut e = vars_os();
+    set_var(&n, "VALUE");
+    assert!(!e.any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+
+    assert!(vars_os().any(|(k, v)| {
+        &*k == &*n && &*v == "VALUE"
+    }));
+}
diff --git a/src/test/run-pass/issue-31260.rs b/src/test/run-pass/issue-31260.rs
index e771fc7464d..d21ffb96bef 100644
--- a/src/test/run-pass/issue-31260.rs
+++ b/src/test/run-pass/issue-31260.rs
@@ -12,9 +12,12 @@ pub struct Struct<K: 'static> {
     pub field: K,
 }
 
-// Partial fix for #31260, doesn't work without {...}.
 static STRUCT: Struct<&'static [u8]> = Struct {
     field: {&[1]}
 };
 
+static STRUCT2: Struct<&'static [u8]> = Struct {
+    field: &[1]
+};
+
 fn main() {}
diff --git a/src/test/run-pass/issue-37725.rs b/src/test/run-pass/issue-37725.rs
new file mode 100644
index 00000000000..5ed1295c85c
--- /dev/null
+++ b/src/test/run-pass/issue-37725.rs
@@ -0,0 +1,14 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+    s.clone();
+}
+fn main() {}
diff --git a/src/test/run-pass/macro-pat-neg-lit.rs b/src/test/run-pass/macro-pat-neg-lit.rs
new file mode 100644
index 00000000000..43ac697edce
--- /dev/null
+++ b/src/test/run-pass/macro-pat-neg-lit.rs
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! enum_number {
+    ($name:ident { $($variant:ident = $value:expr, )* }) => {
+        enum $name {
+            $($variant = $value,)*
+        }
+
+        fn foo(value: i32) -> Option<$name> {
+            match value {
+                $( $value => Some($name::$variant), )*
+                _ => None
+            }
+        }
+    }
+}
+
+enum_number!(Change {
+    Down = -1,
+    None = 0,
+    Up = 1,
+});
+
+fn main() {
+    if let Some(Change::Down) = foo(-1) {} else { panic!() }
+}
+
diff --git a/src/test/run-pass/process-envs.rs b/src/test/run-pass/process-envs.rs
index a131dcbe4dd..b3785d898ba 100644
--- a/src/test/run-pass/process-envs.rs
+++ b/src/test/run-pass/process-envs.rs
@@ -10,8 +10,6 @@
 
 // ignore-emscripten
 
-#![feature(command_envs)]
-
 use std::process::Command;
 use std::env;
 use std::collections::HashMap;
diff --git a/src/test/run-pass/range_inclusive.rs b/src/test/run-pass/range_inclusive.rs
index 372d4a8b732..f6119e70999 100644
--- a/src/test/run-pass/range_inclusive.rs
+++ b/src/test/run-pass/range_inclusive.rs
@@ -10,7 +10,7 @@
 
 // Test inclusive range syntax.
 
-#![feature(inclusive_range_syntax, inclusive_range, step_by)]
+#![feature(inclusive_range_syntax, inclusive_range, iterator_step_by)]
 
 use std::ops::{RangeInclusive, RangeToInclusive};
 
diff --git a/src/test/run-pass/sync-send-iterators-in-libcore.rs b/src/test/run-pass/sync-send-iterators-in-libcore.rs
index d12bdf182fa..c11a0d391a4 100644
--- a/src/test/run-pass/sync-send-iterators-in-libcore.rs
+++ b/src/test/run-pass/sync-send-iterators-in-libcore.rs
@@ -14,7 +14,7 @@
 #![feature(iter_empty)]
 #![feature(iter_once)]
 #![feature(iter_unfold)]
-#![feature(step_by)]
+#![feature(iterator_step_by)]
 #![feature(str_escape)]
 
 use std::iter::{empty, once, repeat};
diff --git a/src/test/run-pass/test-allow-fail-attr.rs b/src/test/run-pass/test-allow-fail-attr.rs
new file mode 100644
index 00000000000..aa9cf76617f
--- /dev/null
+++ b/src/test/run-pass/test-allow-fail-attr.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.
+
+// compile-flags: --test
+#![feature(allow_fail)]
+
+#[test]
+#[allow_fail]
+fn test1() {
+    panic!();
+}
+
+#[test]
+#[allow_fail]
+fn test2() {
+    assert!(true);
+}
diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs
index 8ad6ca0abb0..4387a43f03b 100644
--- a/src/test/run-pass/vector-sort-panic-safe.rs
+++ b/src/test/run-pass/vector-sort-panic-safe.rs
@@ -10,14 +10,17 @@
 
 // ignore-emscripten no threads support
 
-#![feature(rand)]
 #![feature(const_fn)]
+#![feature(rand)]
+#![feature(sort_unstable)]
 
 use std::__rand::{thread_rng, Rng};
+use std::cell::Cell;
+use std::cmp::Ordering;
 use std::panic;
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize};
+use std::sync::atomic::Ordering::Relaxed;
 use std::thread;
-use std::cell::Cell;
 
 const MAX_LEN: usize = 80;
 
@@ -45,54 +48,85 @@ static DROP_COUNTS: [AtomicUsize; MAX_LEN] = [
     AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0),
 ];
 
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
+static VERSIONS: AtomicUsize = ATOMIC_USIZE_INIT;
+
+#[derive(Clone, Eq)]
 struct DropCounter {
     x: u32,
     id: usize,
+    version: Cell<usize>,
+}
+
+impl PartialEq for DropCounter {
+    fn eq(&self, other: &Self) -> bool {
+        self.partial_cmp(other) == Some(Ordering::Equal)
+    }
+}
+
+impl PartialOrd for DropCounter {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.version.set(self.version.get() + 1);
+        other.version.set(other.version.get() + 1);
+        VERSIONS.fetch_add(2, Relaxed);
+        self.x.partial_cmp(&other.x)
+    }
+}
+
+impl Ord for DropCounter {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.partial_cmp(other).unwrap()
+    }
 }
 
 impl Drop for DropCounter {
     fn drop(&mut self) {
-        DROP_COUNTS[self.id].fetch_add(1, Ordering::Relaxed);
+        DROP_COUNTS[self.id].fetch_add(1, Relaxed);
+        VERSIONS.fetch_sub(self.version.get(), Relaxed);
     }
 }
 
-fn test(input: &[DropCounter]) {
-    let len = input.len();
-
-    // Work out the total number of comparisons required to sort
-    // this array...
-    let mut count = 0usize;
-    input.to_owned().sort_by(|a, b| { count += 1; a.cmp(b) });
+macro_rules! test {
+    ($input:ident, $func:ident) => {
+        let len = $input.len();
+
+        // Work out the total number of comparisons required to sort
+        // this array...
+        let mut count = 0usize;
+        $input.to_owned().$func(|a, b| { count += 1; a.cmp(b) });
+
+        // ... and then panic on each and every single one.
+        for panic_countdown in 0..count {
+            // Refresh the counters.
+            VERSIONS.store(0, Relaxed);
+            for i in 0..len {
+                DROP_COUNTS[i].store(0, Relaxed);
+            }
 
-    // ... and then panic on each and every single one.
-    for panic_countdown in 0..count {
-        // Refresh the counters.
-        for i in 0..len {
-            DROP_COUNTS[i].store(0, Ordering::Relaxed);
-        }
+            let v = $input.to_owned();
+            let _ = thread::spawn(move || {
+                let mut v = v;
+                let mut panic_countdown = panic_countdown;
+                v.$func(|a, b| {
+                    if panic_countdown == 0 {
+                        SILENCE_PANIC.with(|s| s.set(true));
+                        panic!();
+                    }
+                    panic_countdown -= 1;
+                    a.cmp(b)
+                })
+            }).join();
+
+            // Check that the number of things dropped is exactly
+            // what we expect (i.e. the contents of `v`).
+            for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
+                let count = c.load(Relaxed);
+                assert!(count == 1,
+                        "found drop count == {} for i == {}, len == {}",
+                        count, i, len);
+            }
 
-        let v = input.to_owned();
-        let _ = thread::spawn(move || {
-            let mut v = v;
-            let mut panic_countdown = panic_countdown;
-            v.sort_by(|a, b| {
-                if panic_countdown == 0 {
-                    SILENCE_PANIC.with(|s| s.set(true));
-                    panic!();
-                }
-                panic_countdown -= 1;
-                a.cmp(b)
-            })
-        }).join();
-
-        // Check that the number of things dropped is exactly
-        // what we expect (i.e. the contents of `v`).
-        for (i, c) in DROP_COUNTS.iter().enumerate().take(len) {
-            let count = c.load(Ordering::Relaxed);
-            assert!(count == 1,
-                    "found drop count == {} for i == {}, len == {}",
-                    count, i, len);
+            // Check that the most recent versions of values were dropped.
+            assert_eq!(VERSIONS.load(Relaxed), 0);
         }
     }
 }
@@ -106,33 +140,41 @@ fn main() {
             prev(info);
         }
     }));
+
+    let mut rng = thread_rng();
+
     for len in (1..20).chain(70..MAX_LEN) {
-        // Test on a random array.
-        let mut rng = thread_rng();
-        let input = (0..len).map(|id| {
-            DropCounter {
-                x: rng.next_u32(),
-                id: id,
-            }
-        }).collect::<Vec<_>>();
-        test(&input);
-
-        // Test on a sorted array with two elements randomly swapped, creating several natural
-        // runs of random lengths. Such arrays have very high chances of hitting all code paths in
-        // the merge procedure.
-        for _ in 0..5 {
-            let mut input = (0..len).map(|i|
-                DropCounter {
-                    x: i as u32,
-                    id: i,
+        for &modulus in &[5, 20, 50] {
+            for &has_runs in &[false, true] {
+                let mut input = (0..len)
+                    .map(|id| {
+                        DropCounter {
+                            x: rng.next_u32() % modulus,
+                            id: id,
+                            version: Cell::new(0),
+                        }
+                    })
+                    .collect::<Vec<_>>();
+
+                if has_runs {
+                    for c in &mut input {
+                        c.x = c.id as u32;
+                    }
+
+                    for _ in 0..5 {
+                        let a = rng.gen::<usize>() % len;
+                        let b = rng.gen::<usize>() % len;
+                        if a < b {
+                            input[a..b].reverse();
+                        } else {
+                            input.swap(a, b);
+                        }
+                    }
                 }
-            ).collect::<Vec<_>>();
-
-            let a = rng.gen::<usize>() % len;
-            let b = rng.gen::<usize>() % len;
-            input.swap(a, b);
 
-            test(&input);
+                test!(input, sort_by);
+                test!(input, sort_unstable_by);
+            }
         }
     }
 }
diff --git a/src/test/rustdoc/issue-42875.rs b/src/test/rustdoc/issue-42875.rs
new file mode 100644
index 00000000000..ebf7056755e
--- /dev/null
+++ b/src/test/rustdoc/issue-42875.rs
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --no-defaults
+
+#![crate_name = "foo"]
+
+// @has foo/a/index.html '//code' 'use *;'
+mod a {
+    use *;
+}
+
+// @has foo/b/index.html '//code' 'pub use *;'
+pub mod b {
+    pub use *;
+}
diff --git a/src/test/compile-fail/block-must-not-have-result-do.rs b/src/test/ui/block-result/block-must-not-have-result-do.rs
index 2a6c71dbe39..2a6c71dbe39 100644
--- a/src/test/compile-fail/block-must-not-have-result-do.rs
+++ b/src/test/ui/block-result/block-must-not-have-result-do.rs
diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr
new file mode 100644
index 00000000000..d4024f41c26
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-do.rs:13:9
+   |
+13 |         true //~  ERROR mismatched types
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/block-must-not-have-result-res.rs b/src/test/ui/block-result/block-must-not-have-result-res.rs
index 8728685fc8b..8728685fc8b 100644
--- a/src/test/compile-fail/block-must-not-have-result-res.rs
+++ b/src/test/ui/block-result/block-must-not-have-result-res.rs
diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr
new file mode 100644
index 00000000000..f60a0c2e5f6
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-res.rs:15:9
+   |
+15 |         true //~  ERROR mismatched types
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs
index a0fb470e1e4..a0fb470e1e4 100644
--- a/src/test/compile-fail/block-must-not-have-result-while.rs
+++ b/src/test/ui/block-result/block-must-not-have-result-while.rs
diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr
new file mode 100644
index 00000000000..888a64c1bb1
--- /dev/null
+++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/block-must-not-have-result-while.rs:13:9
+   |
+13 |         true //~  ERROR mismatched types
+   |         ^^^^ expected (), found bool
+   |
+   = note: expected type `()`
+              found type `bool`
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs
index 530a0e41562..530a0e41562 100644
--- a/src/test/compile-fail/consider-removing-last-semi.rs
+++ b/src/test/ui/block-result/consider-removing-last-semi.rs
diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr
new file mode 100644
index 00000000000..5905cfa9322
--- /dev/null
+++ b/src/test/ui/block-result/consider-removing-last-semi.stderr
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+  --> $DIR/consider-removing-last-semi.rs:11:18
+   |
+11 |   fn f() -> String {  //~ ERROR mismatched types
+   |  __________________^
+12 | |     0u8;
+13 | |     "bla".to_string();  //~ HELP consider removing this semicolon
+   | |                      - help: consider removing this semicolon
+14 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/consider-removing-last-semi.rs:16:18
+   |
+16 |   fn g() -> String {  //~ ERROR mismatched types
+   |  __________________^
+17 | |     "this won't work".to_string();
+18 | |     "removeme".to_string(); //~ HELP consider removing this semicolon
+   | |                           - help: consider removing this semicolon
+19 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/issue-11714.rs b/src/test/ui/block-result/issue-11714.rs
index 192f78e41cb..192f78e41cb 100644
--- a/src/test/compile-fail/issue-11714.rs
+++ b/src/test/ui/block-result/issue-11714.rs
diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr
new file mode 100644
index 00000000000..376834beab0
--- /dev/null
+++ b/src/test/ui/block-result/issue-11714.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-11714.rs:11:18
+   |
+11 |   fn blah() -> i32 { //~ ERROR mismatched types
+   |  __________________^
+12 | |     1
+13 | |
+14 | |     ; //~ HELP consider removing this semicolon:
+   | |     - help: consider removing this semicolon
+15 | | }
+   | |_^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/issue-13428.rs b/src/test/ui/block-result/issue-13428.rs
index 9406199afc2..9406199afc2 100644
--- a/src/test/compile-fail/issue-13428.rs
+++ b/src/test/ui/block-result/issue-13428.rs
diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr
new file mode 100644
index 00000000000..7bd4529c463
--- /dev/null
+++ b/src/test/ui/block-result/issue-13428.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13428.rs:13:20
+   |
+13 |   fn foo() -> String {  //~ ERROR mismatched types
+   |  ____________________^
+14 | |     format!("Hello {}",
+15 | |             "world")
+16 | |     // Put the trailing semicolon on its own line to test that the
+17 | |     // note message gets the offending semicolon exactly
+18 | |     ;   //~ HELP consider removing this semicolon
+   | |     - help: consider removing this semicolon
+19 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13428.rs:21:20
+   |
+21 |   fn bar() -> String {  //~ ERROR mismatched types
+   |  ____________________^
+22 | |     "foobar".to_string()
+23 | |     ;   //~ HELP consider removing this semicolon
+   | |     - help: consider removing this semicolon
+24 | | }
+   | |_^ expected struct `std::string::String`, found ()
+   |
+   = note: expected type `std::string::String`
+              found type `()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/ui/block-result/issue-13624.rs
index e4ed87c3cb0..e4ed87c3cb0 100644
--- a/src/test/compile-fail/issue-13624.rs
+++ b/src/test/ui/block-result/issue-13624.rs
diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr
new file mode 100644
index 00000000000..41113eb7a57
--- /dev/null
+++ b/src/test/ui/block-result/issue-13624.stderr
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-13624.rs:17:5
+   |
+17 |     Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+   |
+   = note: expected type `()`
+              found type `a::Enum`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13624.rs:32:9
+   |
+32 |         a::Enum::EnumStructVariant { x, y, z } => {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum`
+   |
+   = note: expected type `()`
+              found type `a::Enum`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/issue-20862.rs b/src/test/ui/block-result/issue-20862.rs
index 9df63583998..9df63583998 100644
--- a/src/test/compile-fail/issue-20862.rs
+++ b/src/test/ui/block-result/issue-20862.rs
diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr
new file mode 100644
index 00000000000..7c88d789fd3
--- /dev/null
+++ b/src/test/ui/block-result/issue-20862.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-20862.rs:12:5
+   |
+11 | fn foo(x: i32) {
+   |                - possibly return type missing here?
+12 |     |y| x + y
+   |     ^^^^^^^^^ expected (), found closure
+   |
+   = note: expected type `()`
+              found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]`
+
+error[E0618]: expected function, found `()`
+  --> $DIR/issue-20862.rs:17:13
+   |
+17 |     let x = foo(5)(2);
+   |             ^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/ui/block-result/issue-22645.rs
index 81f66e3e2cf..81f66e3e2cf 100644
--- a/src/test/compile-fail/issue-22645.rs
+++ b/src/test/ui/block-result/issue-22645.rs
diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr
new file mode 100644
index 00000000000..a9bcc8bea94
--- /dev/null
+++ b/src/test/ui/block-result/issue-22645.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `{integer}: Scalar` is not satisfied
+  --> $DIR/issue-22645.rs:25:5
+   |
+25 |   b + 3 //~ ERROR E0277
+   |     ^ the trait `Scalar` is not implemented for `{integer}`
+   |
+   = help: the following implementations were found:
+             <f64 as Scalar>
+   = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-22645.rs:25:3
+   |
+25 |   b + 3 //~ ERROR E0277
+   |   ^^^^^ expected (), found struct `Bob`
+   |
+   = note: expected type `()`
+              found type `Bob`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs
index 7928c04b9df..7928c04b9df 100644
--- a/src/test/compile-fail/issue-3563.rs
+++ b/src/test/ui/block-result/issue-3563.rs
diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr
new file mode 100644
index 00000000000..4b1f8b032b7
--- /dev/null
+++ b/src/test/ui/block-result/issue-3563.stderr
@@ -0,0 +1,19 @@
+error[E0599]: no method named `b` found for type `&Self` in the current scope
+  --> $DIR/issue-3563.rs:13:17
+   |
+13 |         || self.b()
+   |                 ^
+
+error[E0308]: mismatched types
+  --> $DIR/issue-3563.rs:13:9
+   |
+12 |     fn a(&self) {
+   |                 - possibly return type missing here?
+13 |         || self.b()
+   |         ^^^^^^^^^^^ expected (), found closure
+   |
+   = note: expected type `()`
+              found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs
index 1cbb7588e17..1cbb7588e17 100644
--- a/src/test/compile-fail/issue-5500.rs
+++ b/src/test/ui/block-result/issue-5500.rs
diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr
new file mode 100644
index 00000000000..bd670a14f24
--- /dev/null
+++ b/src/test/ui/block-result/issue-5500.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-5500.rs:12:5
+   |
+12 |     &panic!()
+   |     ^^^^^^^^^ expected (), found reference
+   |
+   = note: expected type `()`
+              found type `&_`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs
new file mode 100644
index 00000000000..291b7a16f14
--- /dev/null
+++ b/src/test/ui/block-result/unexpected-return-on-unit.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.
+
+// Test that we do some basic error correcton in the tokeniser (and don't spew
+// too many bogus errors).
+
+fn foo() -> usize {
+    3
+}
+
+fn bar() {
+    foo()
+}
+
+fn main() {
+    bar()
+}
diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr
new file mode 100644
index 00000000000..68afd2084f1
--- /dev/null
+++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/unexpected-return-on-unit.rs:19:5
+   |
+19 |     foo()
+   |     ^^^^^ expected (), found usize
+   |
+   = note: expected type `()`
+              found type `usize`
+help: did you mean to add a semicolon here?
+   |     foo();
+help: possibly return type missing here?
+   | fn bar() -> usize {
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/borrowck/borrowck-in-static.stderr b/src/test/ui/borrowck/borrowck-in-static.stderr
index a30d4cbd64c..6083a82b1b6 100644
--- a/src/test/ui/borrowck/borrowck-in-static.stderr
+++ b/src/test/ui/borrowck/borrowck-in-static.stderr
@@ -6,5 +6,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure
 15 |     Box::new(|| x) //~ ERROR cannot move out of captured outer variable
    |                 ^ cannot move out of captured outer variable in an `Fn` closure
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
index a13971d32de..dbfcb2e0c2f 100644
--- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
+++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
@@ -7,5 +7,5 @@ error[E0507]: cannot move out of captured outer variable in an `Fn` closure
 21 |         y.into_iter();
    |         ^ cannot move out of captured outer variable in an `Fn` closure
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/check_match/issue-35609.stderr b/src/test/ui/check_match/issue-35609.stderr
index 0cb264ff35e..0aafe3f17b3 100644
--- a/src/test/ui/check_match/issue-35609.stderr
+++ b/src/test/ui/check_match/issue-35609.stderr
@@ -46,5 +46,5 @@ error[E0004]: non-exhaustive patterns: `Some(B)`, `Some(C)`, `Some(D)` and 2 mor
 49 |     match Some(A) {
    |           ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
 
-error: aborting due to previous error(s)
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr
index dbf702e4503..42fc2909dfb 100644
--- a/src/test/ui/closure_context/issue-26046-fn-mut.stderr
+++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr
@@ -16,5 +16,5 @@ note: closure is `FnMut` because it mutates the variable `num` here
 15 |         num += 1;
    |         ^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr
index 3ec3f0cc9aa..7bfe72d3d6c 100644
--- a/src/test/ui/closure_context/issue-26046-fn-once.stderr
+++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr
@@ -16,5 +16,5 @@ note: closure is `FnOnce` because it moves the variable `vec` out of its environ
 15 |         vec
    |         ^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/closure_context/issue-42065.stderr b/src/test/ui/closure_context/issue-42065.stderr
index 5bbd372adb6..c195940ade6 100644
--- a/src/test/ui/closure_context/issue-42065.stderr
+++ b/src/test/ui/closure_context/issue-42065.stderr
@@ -12,5 +12,5 @@ note: closure cannot be invoked more than once because it moves the variable `di
 16 |         for (key, value) in dict {
    |                             ^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr
index cddc7df85ae..87255dfe774 100644
--- a/src/test/ui/codemap_tests/bad-format-args.stderr
+++ b/src/test/ui/codemap_tests/bad-format-args.stderr
@@ -22,5 +22,5 @@ error: expected token: `,`
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr
index 1c32ce44109..7f1ab929c6f 100644
--- a/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr
+++ b/src/test/ui/codemap_tests/coherence-overlapping-inherent-impl-trait.stderr
@@ -6,5 +6,5 @@ error[E0592]: duplicate definitions with name `f`
 15 | impl C { fn f() {} }
    |          --------- other definition for `f`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr
index 84e6e336b93..b33dee6b4a4 100644
--- a/src/test/ui/codemap_tests/empty_span.stderr
+++ b/src/test/ui/codemap_tests/empty_span.stderr
@@ -4,5 +4,5 @@ error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`,
 17 |     unsafe impl Send for &'static Foo { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr
index 46b3db18e8a..914db98c784 100644
--- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr
@@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
 100 |     let y = &mut x;
     |                  ^ cannot borrow mutably
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr
index dcc21672c56..4947cbedd20 100644
--- a/src/test/ui/codemap_tests/issue-11715.stderr
+++ b/src/test/ui/codemap_tests/issue-11715.stderr
@@ -8,5 +8,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
 101 | }
     | - first borrow ends here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/issue-28308.stderr b/src/test/ui/codemap_tests/issue-28308.stderr
index 43743b796d5..7a1478104fd 100644
--- a/src/test/ui/codemap_tests/issue-28308.stderr
+++ b/src/test/ui/codemap_tests/issue-28308.stderr
@@ -6,5 +6,5 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr
index e2e0537226a..a73575a8d57 100644
--- a/src/test/ui/codemap_tests/one_line.stderr
+++ b/src/test/ui/codemap_tests/one_line.stderr
@@ -7,5 +7,5 @@ error[E0499]: cannot borrow `v` as mutable more than once at a time
    |     |      second mutable borrow occurs here
    |     first mutable borrow occurs here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
index 0af8c06cfda..de8a24cf33f 100644
--- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
+++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
@@ -25,5 +25,5 @@ error[E0592]: duplicate definitions with name `baz`
 43 |     fn baz(&self) {}
    |     ---------------- other definition for `baz`
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/codemap_tests/overlapping_spans.stderr b/src/test/ui/codemap_tests/overlapping_spans.stderr
index 9778015766c..d32b18d6703 100644
--- a/src/test/ui/codemap_tests/overlapping_spans.stderr
+++ b/src/test/ui/codemap_tests/overlapping_spans.stderr
@@ -7,5 +7,5 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
    |         |    hint: to prevent move, use `ref _s` or `ref mut _s`
    |         cannot move out of here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr
index a3b76159b46..657deca4e6d 100644
--- a/src/test/ui/codemap_tests/tab.stderr
+++ b/src/test/ui/codemap_tests/tab.stderr
@@ -4,5 +4,5 @@ error[E0425]: cannot find value `bar` in this scope
 14 | \tbar;
    | \t^^^ not found in this scope
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
index 0f1e008d589..0828fd28b58 100644
--- a/src/test/ui/codemap_tests/unicode.stderr
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -4,5 +4,5 @@ error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thisc
 11 | extern "路濫狼á́́" fn foo() {}
    |        ^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr
index e96bc425e0b..0de0a25e68e 100644
--- a/src/test/ui/coercion-missing-tail-expected-type.stderr
+++ b/src/test/ui/coercion-missing-tail-expected-type.stderr
@@ -4,16 +4,12 @@ error[E0308]: mismatched types
 13 |   fn plus_one(x: i32) -> i32 {
    |  ____________________________^
 14 | |     x + 1;
+   | |          - help: consider removing this semicolon
 15 | | }
    | |_^ expected i32, found ()
    |
    = note: expected type `i32`
               found type `()`
-help: consider removing this semicolon:
-  --> $DIR/coercion-missing-tail-expected-type.rs:14:10
-   |
-14 |     x + 1;
-   |          ^
 
 error[E0308]: mismatched types
   --> $DIR/coercion-missing-tail-expected-type.rs:17:29
@@ -21,16 +17,12 @@ error[E0308]: mismatched types
 17 |   fn foo() -> Result<u8, u64> {
    |  _____________________________^
 18 | |     Ok(1);
+   | |          - help: consider removing this semicolon
 19 | | }
    | |_^ expected enum `std::result::Result`, found ()
    |
    = note: expected type `std::result::Result<u8, u64>`
               found type `()`
-help: consider removing this semicolon:
-  --> $DIR/coercion-missing-tail-expected-type.rs:18:10
-   |
-18 |     Ok(1);
-   |          ^
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/compare-method/proj-outlives-region.stderr b/src/test/ui/compare-method/proj-outlives-region.stderr
index 63c48ffe26b..2a707c6eb8b 100644
--- a/src/test/ui/compare-method/proj-outlives-region.stderr
+++ b/src/test/ui/compare-method/proj-outlives-region.stderr
@@ -11,5 +11,5 @@ error[E0276]: impl has stricter requirements than trait
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr
index 7adcc66d75c..af974d50183 100644
--- a/src/test/ui/compare-method/region-extra-2.stderr
+++ b/src/test/ui/compare-method/region-extra-2.stderr
@@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait
 22 | |     }
    | |_____^ impl has extra requirement `'a: 'b`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr
index a29a292ac65..e657813221a 100644
--- a/src/test/ui/compare-method/region-extra.stderr
+++ b/src/test/ui/compare-method/region-extra.stderr
@@ -7,5 +7,5 @@ error[E0276]: impl has stricter requirements than trait
 22 |     fn foo() where 'a: 'b { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/compare-method/region-unrelated.stderr b/src/test/ui/compare-method/region-unrelated.stderr
index 04de54cd05d..9e822bd8b07 100644
--- a/src/test/ui/compare-method/region-unrelated.stderr
+++ b/src/test/ui/compare-method/region-unrelated.stderr
@@ -11,5 +11,5 @@ error[E0276]: impl has stricter requirements than trait
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr
index b5e9c89f2f5..4620248e2ef 100644
--- a/src/test/ui/compare-method/reordered-type-param.stderr
+++ b/src/test/ui/compare-method/reordered-type-param.stderr
@@ -10,5 +10,5 @@ error[E0053]: method `b` has an incompatible type for trait
    = note: expected type `fn(&E, F) -> F`
               found type `fn(&E, G) -> G`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr
index c4a4921289b..7112a00c7b7 100644
--- a/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr
+++ b/src/test/ui/compare-method/trait-bound-on-type-parameter.stderr
@@ -7,5 +7,5 @@ error[E0276]: impl has stricter requirements than trait
 25 |     fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } //~ ERROR E0276
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr
index 6374b83e794..f221ebe3302 100644
--- a/src/test/ui/compare-method/traits-misc-mismatch-1.stderr
+++ b/src/test/ui/compare-method/traits-misc-mismatch-1.stderr
@@ -61,5 +61,5 @@ error[E0276]: impl has stricter requirements than trait
 76 |     fn method<G: Getter<usize>>(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter<usize>`
 
-error: aborting due to previous error(s)
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
index 7ff2d93d820..622e144c53a 100644
--- a/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
+++ b/src/test/ui/compare-method/traits-misc-mismatch-2.stderr
@@ -10,5 +10,5 @@ error[E0276]: impl has stricter requirements than trait
 26 | |     }
    | |_____^ impl has extra requirement `U: Iterator<B>`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/cross-crate-macro-backtrace/main.stderr b/src/test/ui/cross-crate-macro-backtrace/main.stderr
index 3642a702a82..84db85ac092 100644
--- a/src/test/ui/cross-crate-macro-backtrace/main.stderr
+++ b/src/test/ui/cross-crate-macro-backtrace/main.stderr
@@ -6,5 +6,5 @@ error: invalid reference to argument `0` (no arguments given)
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/E0178.stderr b/src/test/ui/did_you_mean/E0178.stderr
index bcf00df9832..15e7131cfd3 100644
--- a/src/test/ui/did_you_mean/E0178.stderr
+++ b/src/test/ui/did_you_mean/E0178.stderr
@@ -22,5 +22,5 @@ error[E0178]: expected a path on the left-hand side of `+`, not `fn() -> Foo`
 17 |     z: fn() -> Foo + 'a,
    |        ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses?
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
index 73b8e06183b..9010de081da 100644
--- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
@@ -8,5 +8,5 @@ error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
              <Bar as Foo<i32>>
              <Bar as Foo<u8>>
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
index e1e4e14b215..e9591a64784 100644
--- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -11,5 +11,5 @@ error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
              <Bar as Foo<u8>>
            and 2 others
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-31424.stderr b/src/test/ui/did_you_mean/issue-31424.stderr
index eecb164a83f..c7d43a0fc0b 100644
--- a/src/test/ui/did_you_mean/issue-31424.stderr
+++ b/src/test/ui/did_you_mean/issue-31424.stderr
@@ -15,5 +15,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable
 23 |         (&mut self).bar();
    |               ^^^^ cannot borrow mutably
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-34126.stderr b/src/test/ui/did_you_mean/issue-34126.stderr
index d5d6ee133b8..63d59a59238 100644
--- a/src/test/ui/did_you_mean/issue-34126.stderr
+++ b/src/test/ui/did_you_mean/issue-34126.stderr
@@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable argument `self` as mutable
    |                       try removing `&mut` here
    |                       cannot reborrow mutably
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-34337.stderr b/src/test/ui/did_you_mean/issue-34337.stderr
index 2769c74be5e..9eb88cdeddb 100644
--- a/src/test/ui/did_you_mean/issue-34337.stderr
+++ b/src/test/ui/did_you_mean/issue-34337.stderr
@@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `key` as mutable
    |              try removing `&mut` here
    |              cannot reborrow mutably
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr
index 4760d28566f..1cd1fb76aa3 100644
--- a/src/test/ui/did_you_mean/issue-35937.stderr
+++ b/src/test/ui/did_you_mean/issue-35937.stderr
@@ -22,5 +22,5 @@ error[E0594]: cannot assign to immutable field `s.x`
 30 |     s.x += 1;
    |     ^^^^^^^^ cannot mutably borrow immutable field
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-36798.stderr b/src/test/ui/did_you_mean/issue-36798.stderr
index a8d978d5514..72fd09c0357 100644
--- a/src/test/ui/did_you_mean/issue-36798.stderr
+++ b/src/test/ui/did_you_mean/issue-36798.stderr
@@ -4,5 +4,5 @@ error[E0609]: no field `baz` on type `Foo`
 17 |     f.baz;
    |       ^^^ did you mean `bar`?
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
index 8228f9f3fac..82e3eab0836 100644
--- a/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
+++ b/src/test/ui/did_you_mean/issue-36798_unknown_field.stderr
@@ -4,5 +4,5 @@ error[E0609]: no field `zz` on type `Foo`
 17 |     f.zz;
    |       ^^ unknown field
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-37139.stderr b/src/test/ui/did_you_mean/issue-37139.stderr
index 6debbaadb1a..4348b6fca63 100644
--- a/src/test/ui/did_you_mean/issue-37139.stderr
+++ b/src/test/ui/did_you_mean/issue-37139.stderr
@@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable local variable `x` as mutable
    |                       try removing `&mut` here
    |                       cannot reborrow mutably
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr
index 10f5972e369..325f55e686c 100644
--- a/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr
+++ b/src/test/ui/did_you_mean/issue-38054-do-not-show-unresolved-names.stderr
@@ -10,5 +10,5 @@ error[E0432]: unresolved import `Foo1`
 13 | use Foo1;
    |     ^^^^ no `Foo1` in the root
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr
index 85eecd037dd..e9f2b1dad80 100644
--- a/src/test/ui/did_you_mean/issue-38147-1.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-1.stderr
@@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference
 27 |         self.s.push('x');
    |         ^^^^^^ assignment into an immutable reference
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-38147-2.stderr b/src/test/ui/did_you_mean/issue-38147-2.stderr
index 2834fc6262f..e81bc722fa0 100644
--- a/src/test/ui/did_you_mean/issue-38147-2.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-2.stderr
@@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable
 17 |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-38147-3.stderr b/src/test/ui/did_you_mean/issue-38147-3.stderr
index d950e82003c..749795f4d8f 100644
--- a/src/test/ui/did_you_mean/issue-38147-3.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-3.stderr
@@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*self.s` as mutable
 17 |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr
index 6fa152c970b..9a8853f4fbb 100644
--- a/src/test/ui/did_you_mean/issue-38147-4.stderr
+++ b/src/test/ui/did_you_mean/issue-38147-4.stderr
@@ -6,5 +6,5 @@ error[E0389]: cannot borrow data mutably in a `&` reference
 16 |     f.s.push('x');
    |     ^^^ assignment into an immutable reference
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr
index 94afe896d5e..28aaab97bda 100644
--- a/src/test/ui/did_you_mean/issue-39544.stderr
+++ b/src/test/ui/did_you_mean/issue-39544.stderr
@@ -96,5 +96,5 @@ error[E0594]: cannot assign to immutable borrowed content `*x.0`
 58 |     *x.0 = 1;
    |     ^^^^^^^^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index 6a0e94bf138..4ea4adfcfe0 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -39,5 +39,5 @@ error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
            and 2 others
    = note: required by `Foo::bar`
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr
index b1dab01d81f..3b7f32cf890 100644
--- a/src/test/ui/did_you_mean/issue-40006.stderr
+++ b/src/test/ui/did_you_mean/issue-40006.stderr
@@ -64,5 +64,5 @@ error[E0038]: the trait `X` cannot be made into an object
    |
    = note: method `xxx` has no receiver
 
-error: aborting due to previous error(s)
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr
index daee8df7ed8..1a0c74dc01a 100644
--- a/src/test/ui/did_you_mean/issue-40396.stderr
+++ b/src/test/ui/did_you_mean/issue-40396.stderr
@@ -30,5 +30,5 @@ error: chained comparison operators require parentheses
    |
    = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr
index a034ea80969..7daab09c09e 100644
--- a/src/test/ui/did_you_mean/issue-40823.stderr
+++ b/src/test/ui/did_you_mean/issue-40823.stderr
@@ -4,5 +4,5 @@ error[E0596]: cannot borrow immutable borrowed content `*buf` as mutable
 13 |     buf.iter_mut();
    |     ^^^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/issue-41679.stderr b/src/test/ui/did_you_mean/issue-41679.stderr
index 4f210bb0b11..2abbbf65ba9 100644
--- a/src/test/ui/did_you_mean/issue-41679.stderr
+++ b/src/test/ui/did_you_mean/issue-41679.stderr
@@ -6,5 +6,5 @@ error: `~` can not be used as a unary operator
    |
    = help: use `!` instead of `~` if you meant to perform bitwise negation
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
index 32f9d90ec2d..d157c5de6c7 100644
--- a/src/test/ui/did_you_mean/recursion_limit.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -17,5 +17,5 @@ error[E0275]: overflow evaluating the requirement `K: std::marker::Send`
    = note: required because it appears within the type `A`
    = note: required by `is_send`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
index ba8d3815181..57b28d03736 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -19,5 +19,5 @@ error[E0308]: mismatched types
    = note: expected type `&Bottom`
               found type `&Top`
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
index 50e296a1bc5..498255cb9ea 100644
--- a/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
+++ b/src/test/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr
@@ -18,5 +18,5 @@ error[E0038]: the trait `std::marker::Copy` cannot be made into an object
    |
    = note: the trait cannot require that `Self : Sized`
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr
index a5a3c48ab97..62ce3209c91 100644
--- a/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch-extern-crate.stderr
@@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
index e1bfb4d8c1e..2c788e952ed 100644
--- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
@@ -20,5 +20,5 @@ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attri
 43 | | }
    | |_^
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr
index de04a1c4283..d94808bbcb6 100644
--- a/src/test/ui/dropck/dropck-eyepatch-reorder.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch-reorder.stderr
@@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/dropck/dropck-eyepatch.stderr b/src/test/ui/dropck/dropck-eyepatch.stderr
index 26fee852fb2..811eee0e85f 100644
--- a/src/test/ui/dropck/dropck-eyepatch.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch.stderr
@@ -42,5 +42,5 @@ error[E0597]: `c` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/fmt/format-string-error.stderr b/src/test/ui/fmt/format-string-error.stderr
index 2466d2b43b6..58b392f0b8d 100644
--- a/src/test/ui/fmt/format-string-error.stderr
+++ b/src/test/ui/fmt/format-string-error.stderr
@@ -16,5 +16,5 @@ error: invalid format string: unmatched `}` found
    = note: if you intended to print `}`, you can escape it using `}}`
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 2206234b777..3fc08a0900f 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -51,5 +51,5 @@ error[E0308]: mismatched types
    = note: expected type `impl Foo` (i32)
               found type `impl Foo` (u32)
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr
index 1b1e0eaf203..3bc281726ef 100644
--- a/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr
+++ b/src/test/ui/impl-trait/issue-21659-show-relevant-trait-impls-3.stderr
@@ -8,5 +8,5 @@ error[E0599]: no method named `foo` found for type `Bar` in the current scope
    = note: the following trait defines an item `foo`, perhaps you need to implement it:
            candidate #1: `Foo`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
index fa08c3bee9c..d3dbb77490b 100644
--- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
+++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr
@@ -10,5 +10,5 @@ error[E0599]: no method named `is_empty` found for type `Foo` in the current sco
            candidate #2: `core::slice::SliceExt`
            candidate #3: `core::str::StrExt`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
index 95d3007a4fb..fc441f94842 100644
--- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr
@@ -226,5 +226,5 @@ error[E0599]: no method named `method3` found for type `std::rc::Rc<&mut std::bo
 131 |     std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method3();
     |                                                                          ^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr
index cc7a7153a38..9216c6e2907 100644
--- a/src/test/ui/impl-trait/trait_type.stderr
+++ b/src/test/ui/impl-trait/trait_type.stderr
@@ -31,5 +31,5 @@ error[E0046]: not all trait items implemented, missing: `fmt`
    |
    = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr
index a9535f1c830..76362f1f494 100644
--- a/src/test/ui/interior-mutability/interior-mutability.stderr
+++ b/src/test/ui/interior-mutability/interior-mutability.stderr
@@ -10,5 +10,5 @@ error[E0277]: the trait bound `std::cell::UnsafeCell<i32>: std::panic::RefUnwind
    = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:15:18: 15:35 x:&std::cell::Cell<i32>]`
    = note: required by `std::panic::catch_unwind`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
index a444d5f5a40..3e9b21cdb74 100644
--- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
+++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr
@@ -10,5 +10,5 @@ note: maybe move this module `$DIR/auxiliary/foo/bar.rs` to its own directory vi
 11 | pub mod baz;
    |         ^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr
index a22496357d9..22c16ada05d 100644
--- a/src/test/ui/issue-22644.stderr
+++ b/src/test/ui/issue-22644.stderr
@@ -20,5 +20,5 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com
 help: if you want to compare the casted value then write:
    |     println!("{}", (a as usize) < 4);
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-26548.stderr b/src/test/ui/issue-26548.stderr
index c27ad7680a5..8bfe4ac733b 100644
--- a/src/test/ui/issue-26548.stderr
+++ b/src/test/ui/issue-26548.stderr
@@ -5,5 +5,5 @@ note: ...which then requires computing layout of `std::option::Option<<S as Mirr
 note: ...which then requires computing layout of `<S as Mirror>::It`...
   = note: ...which then again requires computing layout of `S`, completing the cycle.
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-33525.rs b/src/test/ui/issue-33525.rs
new file mode 100644
index 00000000000..0e777fe8a94
--- /dev/null
+++ b/src/test/ui/issue-33525.rs
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    a;
+    "".lorem;
+    "".ipsum;
+}
diff --git a/src/test/ui/issue-33525.stderr b/src/test/ui/issue-33525.stderr
new file mode 100644
index 00000000000..5de2d98f86a
--- /dev/null
+++ b/src/test/ui/issue-33525.stderr
@@ -0,0 +1,20 @@
+error[E0425]: cannot find value `a` in this scope
+  --> $DIR/issue-33525.rs:12:5
+   |
+12 |     a;
+   |     ^ not found in this scope
+
+error[E0609]: no field `lorem` on type `&'static str`
+  --> $DIR/issue-33525.rs:13:8
+   |
+13 |     "".lorem;
+   |        ^^^^^
+
+error[E0609]: no field `ipsum` on type `&'static str`
+  --> $DIR/issue-33525.rs:14:8
+   |
+14 |     "".ipsum;
+   |        ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr
index 62223c553e3..b51b683a1ac 100644
--- a/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr
+++ b/src/test/ui/issue-37311-type-length-limit/issue-37311.stderr
@@ -8,5 +8,5 @@ error: reached the type-length limit while instantiating `<T as Foo><(&(&(&(&(&(
    |
    = note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-38875/issue_38875.stderr b/src/test/ui/issue-38875/issue_38875.stderr
index ceed83d9313..10bb61ee22a 100644
--- a/src/test/ui/issue-38875/issue_38875.stderr
+++ b/src/test/ui/issue-38875/issue_38875.stderr
@@ -10,5 +10,5 @@ note: for repeat count here
 16 |     let test_x = [0; issue_38875_b::FOO];
    |                      ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr
index 80f608c1d37..de110ac12b7 100644
--- a/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr
+++ b/src/test/ui/issue-40402-ref-hints/issue-40402-1.stderr
@@ -7,5 +7,5 @@ error[E0507]: cannot move out of indexed content
    |             help: consider using a reference instead `&f.v[0]`
    |             cannot move out of indexed content
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr
index d35800ac1e7..0060b683bba 100644
--- a/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr
+++ b/src/test/ui/issue-40402-ref-hints/issue-40402-2.stderr
@@ -7,5 +7,5 @@ error[E0507]: cannot move out of indexed content
    |          |  ...and here (use `ref b` or `ref mut b`)
    |          hint: to prevent move, use `ref a` or `ref mut a`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr
index b7b1ddb7b88..8a55c9989e1 100644
--- a/src/test/ui/issue-41652/issue_41652.stderr
+++ b/src/test/ui/issue-41652/issue_41652.stderr
@@ -13,5 +13,5 @@ note: candidate #1 is defined in the trait `issue_41652_b::Tr`
    | |__________________________^
    = help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs
new file mode 100644
index 00000000000..a1716c4e797
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.rs
@@ -0,0 +1,15 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+    if x > y { x } else { y }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr
new file mode 100644
index 00000000000..83716b7791d
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-2.stderr
@@ -0,0 +1,10 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-2.rs:12:16
+   |
+11 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |            - consider changing the type of `x` to `&'a i32`
+12 |     if x > y { x } else { y }
+   |                ^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs
new file mode 100644
index 00000000000..7bd32d87617
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.rs
@@ -0,0 +1,15 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
+    if x > y { x } else { y }
+}
+
+fn main () { }
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr
new file mode 100644
index 00000000000..6d5e94a5e78
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-3.stderr
@@ -0,0 +1,10 @@
+error[E0621]: explicit lifetime required in parameter type
+  --> $DIR/ex1-return-one-existing-name-if-else-3.rs:12:27
+   |
+11 | fn foo<'a>((x, y): (&'a i32, &i32)) -> &'a i32 {
+   |            ------ consider changing type to `(&'a i32, &'a i32)`
+12 |     if x > y { x } else { y }
+   |                           ^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs
new file mode 100644
index 00000000000..8849f7084b3
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.rs
@@ -0,0 +1,18 @@
+// 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.
+
+trait Foo {
+
+fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   if x > y { x } else { y }
+   }
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr
new file mode 100644
index 00000000000..4288fdf89a4
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-2.stderr
@@ -0,0 +1,10 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-2.rs:14:15
+   |
+13 | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+   |            - consider changing the type of `x` to `&'a i32`
+14 |    if x > y { x } else { y }
+   |               ^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/variance-region-bounds.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs
index 41d204a541b..362290ff3fa 100644
--- a/src/test/compile-fail/variance-region-bounds.rs
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,18 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that `T:'a` is contravariant in T.
+struct Foo {
+  field: i32
+}
 
-#![feature(rustc_attrs)]
+impl Foo {
+  fn foo<'a>(&'a self, x: &i32) -> &i32 {
 
-#[rustc_variance]
-trait Foo: 'static { //~ ERROR [o]
-}
+    if true { &self.field } else { x }
+
+  }
 
-#[rustc_variance]
-trait Bar<T> { //~ ERROR [o, o]
-    fn do_it(&self)
-        where T: 'static;
 }
 
 fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr
new file mode 100644
index 00000000000..95076bfbdc7
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.stderr
@@ -0,0 +1,11 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:18:36
+   |
+16 |   fn foo<'a>(&'a self, x: &i32) -> &i32 {
+   |                        - consider changing the type of `x` to `&'a i32`
+17 | 
+18 |     if true { &self.field } else { x }
+   |                                    ^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.rs
new file mode 100644
index 00000000000..36d956a3996
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.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.
+
+trait Foo {
+
+    fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
+
+}
+
+impl Foo for () {
+
+    fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+
+        if x > y { x } else { y }
+
+    }
+
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr
new file mode 100644
index 00000000000..9e4f6c42179
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.stderr
@@ -0,0 +1,27 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:21:20
+   |
+21 |         if x > y { x } else { y }
+   |                    ^
+   |
+note: ...the reference is valid for the lifetime 'a as defined on the method body at 19:5...
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5
+   |
+19 | /     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+20 | |
+21 | |         if x > y { x } else { y }
+22 | |
+23 | |     }
+   | |_____^
+note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 19:5
+  --> $DIR/ex1-return-one-existing-name-if-else-using-impl.rs:19:5
+   |
+19 | /     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 {
+20 | |
+21 | |         if x > y { x } else { y }
+22 | |
+23 | |     }
+   | |_____^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
index 0ab24b0b3e6..5d1336c7c3a 100644
--- a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-if-else.stderr
@@ -1,23 +1,10 @@
-error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+error[E0621]: explicit lifetime required in the type of `y`
   --> $DIR/ex1-return-one-existing-name-if-else.rs:12:27
    |
+11 | fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
+   |                        - consider changing the type of `y` to `&'a i32`
 12 |     if x > y { x } else { y }
-   |                           ^
-   |
-note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:1...
-  --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
-   |
-11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
-12 | |     if x > y { x } else { y }
-13 | | }
-   | |_^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:1
-  --> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
-   |
-11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
-12 | |     if x > y { x } else { y }
-13 | | }
-   | |_^
+   |                           ^ lifetime `'a` required
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.rs
new file mode 100644
index 00000000000..96b733be9b4
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.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.
+
+struct Foo {
+  field: i32
+}
+
+impl Foo {
+  fn foo<'a>(&self, x: &'a i32) -> &i32 {
+
+    x
+
+  }
+
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
new file mode 100644
index 00000000000..e3fd0192053
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.stderr
@@ -0,0 +1,27 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:18:5
+   |
+18 |     x
+   |     ^
+   |
+note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
+  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
+   |
+16 | /   fn foo<'a>(&self, x: &'a i32) -> &i32 {
+17 | |
+18 | |     x
+19 | |
+20 | |   }
+   | |___^
+note: ...but the borrowed content is only valid for the lifetime 'a as defined on the method body at 16:3
+  --> $DIR/ex1-return-one-existing-name-return-type-is-anon.rs:16:3
+   |
+16 | /   fn foo<'a>(&self, x: &'a i32) -> &i32 {
+17 | |
+18 | |     x
+19 | |
+20 | |   }
+   | |___^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs
new file mode 100644
index 00000000000..a8ce60c47b6
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.rs
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+    field: i32,
+}
+
+impl Foo {
+    fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
+
+        if true { x } else { self }
+
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
new file mode 100644
index 00000000000..8551f015db5
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex1-return-one-existing-name-self-is-anon.stderr
@@ -0,0 +1,27 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:18:30
+   |
+18 |         if true { x } else { self }
+   |                              ^^^^
+   |
+note: ...the reference is valid for the lifetime 'a as defined on the method body at 16:5...
+  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5
+   |
+16 | /     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
+17 | |
+18 | |         if true { x } else { self }
+19 | |
+20 | |     }
+   | |_____^
+note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the method body at 16:5
+  --> $DIR/ex1-return-one-existing-name-self-is-anon.rs:16:5
+   |
+16 | /     fn foo<'a>(&self, x: &'a Foo) -> &'a Foo {
+17 | |
+18 | |         if true { x } else { self }
+19 | |
+20 | |     }
+   | |_____^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr
index d005eeb4045..fccc44caac8 100644
--- a/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr
+++ b/src/test/ui/lifetime-errors/ex1b-return-no-names-if-else.stderr
@@ -6,5 +6,5 @@ error[E0106]: missing lifetime specifier
    |
    = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs
new file mode 100644
index 00000000000..dd34e1aa6d9
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.rs
@@ -0,0 +1,19 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Ref<'a, T: 'a> {
+    data: &'a T
+}
+
+fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
+    y.push(x);
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr
new file mode 100644
index 00000000000..8dba0c33f20
--- /dev/null
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name-2.stderr
@@ -0,0 +1,10 @@
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/ex2a-push-one-existing-name-2.rs:16:12
+   |
+15 | fn foo<'a>(x: Ref<i32>, y: &mut Vec<Ref<'a, i32>>) {
+   |            - consider changing the type of `x` to `Ref<'a, i32>`
+16 |     y.push(x);
+   |            ^ lifetime `'a` required
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
index 7d0947b364e..e529d6ffe46 100644
--- a/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
+++ b/src/test/ui/lifetime-errors/ex2a-push-one-existing-name.stderr
@@ -1,25 +1,10 @@
-error[E0308]: mismatched types
+error[E0621]: explicit lifetime required in the type of `y`
   --> $DIR/ex2a-push-one-existing-name.rs:16:12
    |
+15 | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
+   |                                       - consider changing the type of `y` to `Ref<'a, i32>`
 16 |     x.push(y);
-   |            ^ lifetime mismatch
-   |
-   = note: expected type `Ref<'a, _>`
-              found type `Ref<'_, _>`
-note: the anonymous lifetime #2 defined on the function body at 15:1...
-  --> $DIR/ex2a-push-one-existing-name.rs:15:1
-   |
-15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
-16 | |     x.push(y);
-17 | | }
-   | |_^
-note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1
-  --> $DIR/ex2a-push-one-existing-name.rs:15:1
-   |
-15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
-16 | |     x.push(y);
-17 | | }
-   | |_^
+   |            ^ lifetime `'a` required
 
-error: aborting due to previous error(s)
+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 6380a885f44..6764c58f4bb 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
@@ -21,5 +21,5 @@ note: ...does not necessarily outlive the anonymous lifetime #2 defined on the f
 17 | | }
    | |_^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
index b28a3c0c135..7356fc11862 100644
--- a/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
+++ b/src/test/ui/lifetime-errors/ex2c-push-inference-variable.stderr
@@ -31,5 +31,5 @@ note: ...so that expression is assignable (expected Ref<'b, _>, found Ref<'_, _>
 17 |     x.push(z);
    |            ^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
index dd716bac513..38b0acf9339 100644
--- a/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
+++ b/src/test/ui/lifetime-errors/ex2d-push-inference-variable-2.stderr
@@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i
 16 |     let a: &mut Vec<Ref<i32>> = x;
    |                                 ^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
index 141f5a7c452..035e516e862 100644
--- a/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
+++ b/src/test/ui/lifetime-errors/ex2e-push-inference-variable-3.stderr
@@ -33,5 +33,5 @@ note: ...so that expression is assignable (expected &mut std::vec::Vec<Ref<'_, i
 16 |     let a: &mut Vec<Ref<i32>> = x;
    |                                 ^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
index 2bc0acd626c..d1ba9246588 100644
--- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
+++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr
@@ -10,5 +10,5 @@ error[E0597]: borrowed value does not live long enough
    |
    = note: consider using a `let` binding to increase its lifetime
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lint/command-line-lint-group-deny.stderr b/src/test/ui/lint/command-line-lint-group-deny.stderr
index d441702374b..23fac66cc6c 100644
--- a/src/test/ui/lint/command-line-lint-group-deny.stderr
+++ b/src/test/ui/lint/command-line-lint-group-deny.stderr
@@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a
    |
    = note: `-D non-snake-case` implied by `-D bad-style`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lint/command-line-lint-group-forbid.stderr b/src/test/ui/lint/command-line-lint-group-forbid.stderr
index 9d4d0b12b18..0babd7f6fe4 100644
--- a/src/test/ui/lint/command-line-lint-group-forbid.stderr
+++ b/src/test/ui/lint/command-line-lint-group-forbid.stderr
@@ -6,5 +6,5 @@ error: variable `_InappropriateCamelCasing` should have a snake case name such a
    |
    = note: `-F non-snake-case` implied by `-F bad-style`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/lint/lint-group-style.stderr b/src/test/ui/lint/lint-group-style.stderr
index dec44c317e4..862e94b873a 100644
--- a/src/test/ui/lint/lint-group-style.stderr
+++ b/src/test/ui/lint/lint-group-style.stderr
@@ -4,12 +4,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case`
 14 | fn CamelCase() {}
    | ^^^^^^^^^^^^^^^^^
    |
-   = note: #[deny(non_snake_case)] implied by #[deny(bad_style)]
 note: lint level defined here
   --> $DIR/lint-group-style.rs:11:9
    |
 11 | #![deny(bad_style)]
    |         ^^^^^^^^^
+   = note: #[deny(non_snake_case)] implied by #[deny(bad_style)]
 
 error: function `CamelCase` should have a snake case name such as `camel_case`
   --> $DIR/lint-group-style.rs:22:9
@@ -17,12 +17,12 @@ error: function `CamelCase` should have a snake case name such as `camel_case`
 22 |         fn CamelCase() {}
    |         ^^^^^^^^^^^^^^^^^
    |
-   = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)]
 note: lint level defined here
   --> $DIR/lint-group-style.rs:20:14
    |
 20 |     #[forbid(bad_style)]
    |              ^^^^^^^^^
+   = note: #[forbid(non_snake_case)] implied by #[forbid(bad_style)]
 
 error: static variable `bad` should have an upper case name such as `BAD`
   --> $DIR/lint-group-style.rs:24:9
@@ -30,12 +30,12 @@ error: static variable `bad` should have an upper case name such as `BAD`
 24 |         static bad: isize = 1;
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)]
 note: lint level defined here
   --> $DIR/lint-group-style.rs:20:14
    |
 20 |     #[forbid(bad_style)]
    |              ^^^^^^^^^
+   = note: #[forbid(non_upper_case_globals)] implied by #[forbid(bad_style)]
 
 warning: function `CamelCase` should have a snake case name such as `camel_case`
   --> $DIR/lint-group-style.rs:30:9
@@ -43,12 +43,12 @@ warning: function `CamelCase` should have a snake case name such as `camel_case`
 30 |         fn CamelCase() {}
    |         ^^^^^^^^^^^^^^^^^
    |
-   = note: #[warn(non_snake_case)] implied by #[warn(bad_style)]
 note: lint level defined here
   --> $DIR/lint-group-style.rs:28:17
    |
 28 |         #![warn(bad_style)]
    |                 ^^^^^^^^^
+   = note: #[warn(non_snake_case)] implied by #[warn(bad_style)]
 
 warning: type `snake_case` should have a camel case name such as `SnakeCase`
   --> $DIR/lint-group-style.rs:32:9
@@ -56,12 +56,12 @@ warning: type `snake_case` should have a camel case name such as `SnakeCase`
 32 |         struct snake_case;
    |         ^^^^^^^^^^^^^^^^^^
    |
-   = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)]
 note: lint level defined here
   --> $DIR/lint-group-style.rs:28:17
    |
 28 |         #![warn(bad_style)]
    |                 ^^^^^^^^^
+   = note: #[warn(non_camel_case_types)] implied by #[warn(bad_style)]
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/lint/outer-forbid.rs b/src/test/ui/lint/outer-forbid.rs
new file mode 100644
index 00000000000..d71da58829a
--- /dev/null
+++ b/src/test/ui/lint/outer-forbid.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.
+
+// Forbidding a group (here, `unused`) overrules subsequent allowance of both
+// the group, and an individual lint in the group (here, `unused_variables`);
+// and, forbidding an individual lint (here, `non_snake_case`) overrules
+// subsequent allowance of a lint group containing it (here, `bad_style`). See
+// Issue #42873.
+
+#![forbid(unused, non_snake_case)]
+
+#[allow(unused, unused_variables, bad_style)]
+fn main() {
+    println!("hello forbidden world")
+}
diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr
new file mode 100644
index 00000000000..df62f5acc00
--- /dev/null
+++ b/src/test/ui/lint/outer-forbid.stderr
@@ -0,0 +1,29 @@
+error[E0453]: allow(unused) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:19:9
+   |
+17 | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+18 | 
+19 | #[allow(unused, unused_variables, bad_style)]
+   |         ^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(unused_variables) overruled by outer forbid(unused)
+  --> $DIR/outer-forbid.rs:19:17
+   |
+17 | #![forbid(unused, non_snake_case)]
+   |           ------ `forbid` level set here
+18 | 
+19 | #[allow(unused, unused_variables, bad_style)]
+   |                 ^^^^^^^^^^^^^^^^ overruled by previous forbid
+
+error[E0453]: allow(bad_style) overruled by outer forbid(non_snake_case)
+  --> $DIR/outer-forbid.rs:19:35
+   |
+17 | #![forbid(unused, non_snake_case)]
+   |                   -------------- `forbid` level set here
+18 | 
+19 | #[allow(unused, unused_variables, bad_style)]
+   |                                   ^^^^^^^^^ overruled by previous forbid
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/loop-break-value-no-repeat.stderr b/src/test/ui/loop-break-value-no-repeat.stderr
index 7a4a9c3f012..c154ea6f8c2 100644
--- a/src/test/ui/loop-break-value-no-repeat.stderr
+++ b/src/test/ui/loop-break-value-no-repeat.stderr
@@ -4,5 +4,5 @@ error[E0571]: `break` with value from a `for` loop
 22 |         break 22
    |         ^^^^^^^^ can only break with a value inside `loop`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/macros/bad_hello.stderr b/src/test/ui/macros/bad_hello.stderr
index b8337c81834..bffb33f468f 100644
--- a/src/test/ui/macros/bad_hello.stderr
+++ b/src/test/ui/macros/bad_hello.stderr
@@ -4,5 +4,5 @@ error: expected a literal
 12 |     println!(3 + 4);
    |              ^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr
index a964b92712d..0283052a89f 100644
--- a/src/test/ui/macros/format-foreign.stderr
+++ b/src/test/ui/macros/format-foreign.stderr
@@ -48,5 +48,5 @@ error: named argument never used
    = help: `$NAME` should be written as `{NAME}`
    = note: shell formatting not supported; see the documentation for `std::fmt`
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
index 5ed4ab4552a..0f0d6d8ded3 100644
--- a/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
+++ b/src/test/ui/macros/macro-backtrace-invalid-internals.stderr
@@ -52,5 +52,5 @@ error[E0613]: attempted to access tuple index `0` on type `{integer}`, but the t
 56 |     let _ = fake_anon_field_expr!();
    |             ----------------------- in this macro invocation
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/macros/macro-backtrace-nested.stderr b/src/test/ui/macros/macro-backtrace-nested.stderr
index 7835b85eafc..8b69d112d4d 100644
--- a/src/test/ui/macros/macro-backtrace-nested.stderr
+++ b/src/test/ui/macros/macro-backtrace-nested.stderr
@@ -16,5 +16,5 @@ error[E0425]: cannot find value `fake` in this scope
 28 |     call_nested_expr_sum!();
    |     ------------------------ in this macro invocation
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/macros/macro-backtrace-println.stderr b/src/test/ui/macros/macro-backtrace-println.stderr
index 4177240d976..f21253bb67f 100644
--- a/src/test/ui/macros/macro-backtrace-println.stderr
+++ b/src/test/ui/macros/macro-backtrace-println.stderr
@@ -7,5 +7,5 @@ error: invalid reference to argument `0` (no arguments given)
 28 |     myprintln!("{}");
    |     ----------------- in this macro invocation
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr
index 2ba2069677e..d9871b8970c 100644
--- a/src/test/ui/mismatched_types/E0053.stderr
+++ b/src/test/ui/mismatched_types/E0053.stderr
@@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait
    = note: expected type `fn(&Bar)`
               found type `fn(&mut Bar)`
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/E0281.stderr b/src/test/ui/mismatched_types/E0281.stderr
index 3eb5c125789..887412d1be7 100644
--- a/src/test/ui/mismatched_types/E0281.stderr
+++ b/src/test/ui/mismatched_types/E0281.stderr
@@ -9,5 +9,5 @@ error[E0281]: type mismatch: `[closure@$DIR/E0281.rs:14:9: 14:24]` implements th
    |
    = note: required by `foo`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr
index a5f63aca13e..cc7c0179070 100644
--- a/src/test/ui/mismatched_types/E0409.stderr
+++ b/src/test/ui/mismatched_types/E0409.stderr
@@ -15,5 +15,5 @@ error[E0308]: mismatched types
    = note: expected type `&{integer}`
               found type `{integer}`
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/abridged.rs b/src/test/ui/mismatched_types/abridged.rs
index c448ad955fa..03f889224be 100644
--- a/src/test/ui/mismatched_types/abridged.rs
+++ b/src/test/ui/mismatched_types/abridged.rs
@@ -39,23 +39,25 @@ fn c() -> Result<Foo, Bar> {
 }
 
 fn d() -> X<X<String, String>, String> {
-    X {
+    let x = X {
         x: X {
             x: "".to_string(),
             y: 2,
         },
         y: 3,
-    }
+    };
+    x
 }
 
 fn e() -> X<X<String, String>, String> {
-    X {
+    let x = X {
         x: X {
             x: "".to_string(),
             y: 2,
         },
         y: "".to_string(),
-    }
+    };
+    x
 }
 
 fn main() {}
diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr
index 78b5dcda1d9..d40bc3b3339 100644
--- a/src/test/ui/mismatched_types/abridged.stderr
+++ b/src/test/ui/mismatched_types/abridged.stderr
@@ -35,34 +35,22 @@ error[E0308]: mismatched types
               found type `Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/abridged.rs:42:5
+  --> $DIR/abridged.rs:49:5
    |
-42 | /     X {
-43 | |         x: X {
-44 | |             x: "".to_string(),
-45 | |             y: 2,
-46 | |         },
-47 | |         y: 3,
-48 | |     }
-   | |_____^ expected struct `std::string::String`, found integral variable
+49 |     x
+   |     ^ expected struct `std::string::String`, found integral variable
    |
    = note: expected type `X<X<_, std::string::String>, std::string::String>`
               found type `X<X<_, {integer}>, {integer}>`
 
 error[E0308]: mismatched types
-  --> $DIR/abridged.rs:52:5
+  --> $DIR/abridged.rs:60:5
    |
-52 | /     X {
-53 | |         x: X {
-54 | |             x: "".to_string(),
-55 | |             y: 2,
-56 | |         },
-57 | |         y: "".to_string(),
-58 | |     }
-   | |_____^ expected struct `std::string::String`, found integral variable
+60 |     x
+   |     ^ expected struct `std::string::String`, found integral variable
    |
    = note: expected type `X<X<_, std::string::String>, _>`
               found type `X<X<_, {integer}>, _>`
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/mismatched_types/binops.stderr b/src/test/ui/mismatched_types/binops.stderr
index cebdc12f568..6d1a39e0d93 100644
--- a/src/test/ui/mismatched_types/binops.stderr
+++ b/src/test/ui/mismatched_types/binops.stderr
@@ -46,5 +46,5 @@ error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::result::Resul
    |
    = help: the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr
index 58cd130dcc2..fb363c388b6 100644
--- a/src/test/ui/mismatched_types/cast-rfc0401.stderr
+++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr
@@ -1,4 +1,4 @@
-error: casting `*const U` as `*const V` is invalid
+error[E0606]: casting `*const U` as `*const V` is invalid
   --> $DIR/cast-rfc0401.rs:13:5
    |
 13 |     u as *const V
@@ -6,7 +6,7 @@ error: casting `*const U` as `*const V` is invalid
    |
    = note: vtable kinds may not match
 
-error: casting `*const U` as `*const str` is invalid
+error[E0606]: casting `*const U` as `*const str` is invalid
   --> $DIR/cast-rfc0401.rs:18:5
    |
 18 |     u as *const str
@@ -20,49 +20,59 @@ error[E0609]: no field `f` on type `fn() {main}`
 75 |     let _ = main.f as *const u32;
    |                  ^
 
-error: non-scalar cast: `*const u8` as `&u8`
+error[E0605]: non-primitive cast: `*const u8` as `&u8`
   --> $DIR/cast-rfc0401.rs:39:13
    |
 39 |     let _ = v as &u8;
    |             ^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `*const u8` as `E`
+error[E0605]: non-primitive cast: `*const u8` as `E`
   --> $DIR/cast-rfc0401.rs:40:13
    |
 40 |     let _ = v as E;
    |             ^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `*const u8` as `fn()`
+error[E0605]: non-primitive cast: `*const u8` as `fn()`
   --> $DIR/cast-rfc0401.rs:41:13
    |
 41 |     let _ = v as fn();
    |             ^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `*const u8` as `(u32,)`
+error[E0605]: non-primitive cast: `*const u8` as `(u32,)`
   --> $DIR/cast-rfc0401.rs:42:13
    |
 42 |     let _ = v as (u32,);
    |             ^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: non-scalar cast: `std::option::Option<&*const u8>` as `*const u8`
+error[E0605]: non-primitive cast: `std::option::Option<&*const u8>` as `*const u8`
   --> $DIR/cast-rfc0401.rs:43:13
    |
 43 |     let _ = Some(&v) as *const u8;
    |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: casting `*const u8` as `f32` is invalid
+error[E0606]: casting `*const u8` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:45:13
    |
 45 |     let _ = v as f32;
    |             ^^^^^^^^
 
-error: casting `fn() {main}` as `f64` is invalid
+error[E0606]: casting `fn() {main}` as `f64` is invalid
   --> $DIR/cast-rfc0401.rs:46:13
    |
 46 |     let _ = main as f64;
    |             ^^^^^^^^^^^
 
-error: casting `&*const u8` as `usize` is invalid
+error[E0606]: casting `&*const u8` as `usize` is invalid
   --> $DIR/cast-rfc0401.rs:47:13
    |
 47 |     let _ = &v as usize;
@@ -70,7 +80,7 @@ error: casting `&*const u8` as `usize` is invalid
    |
    = help: cast through a raw pointer first
 
-error: casting `f32` as `*const u8` is invalid
+error[E0606]: casting `f32` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:48:13
    |
 48 |     let _ = f as *const u8;
@@ -92,13 +102,13 @@ error[E0054]: cannot cast as `bool`
    |
    = help: compare with zero instead
 
-error: only `u8` can be cast as `char`, not `u32`
+error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/cast-rfc0401.rs:51:13
    |
 51 |     let _ = 0x61u32 as char;
    |             ^^^^^^^^^^^^^^^
 
-error: casting `bool` as `f32` is invalid
+error[E0606]: casting `bool` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:53:13
    |
 53 |     let _ = false as f32;
@@ -106,7 +116,7 @@ error: casting `bool` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `E` as `f32` is invalid
+error[E0606]: casting `E` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:54:13
    |
 54 |     let _ = E::A as f32;
@@ -114,7 +124,7 @@ error: casting `E` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `char` as `f32` is invalid
+error[E0606]: casting `char` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:55:13
    |
 55 |     let _ = 'a' as f32;
@@ -122,67 +132,67 @@ error: casting `char` as `f32` is invalid
    |
    = help: cast through an integer first
 
-error: casting `bool` as `*const u8` is invalid
+error[E0606]: casting `bool` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:57:13
    |
 57 |     let _ = false as *const u8;
    |             ^^^^^^^^^^^^^^^^^^
 
-error: casting `E` as `*const u8` is invalid
+error[E0606]: casting `E` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:58:13
    |
 58 |     let _ = E::A as *const u8;
    |             ^^^^^^^^^^^^^^^^^
 
-error: casting `char` as `*const u8` is invalid
+error[E0606]: casting `char` as `*const u8` is invalid
   --> $DIR/cast-rfc0401.rs:59:13
    |
 59 |     let _ = 'a' as *const u8;
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `usize` as `*const [u8]` is invalid
+error[E0606]: casting `usize` as `*const [u8]` is invalid
   --> $DIR/cast-rfc0401.rs:61:13
    |
 61 |     let _ = 42usize as *const [u8];
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
-error: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
+error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
   --> $DIR/cast-rfc0401.rs:62:13
    |
 62 |     let _ = v as *const [u8];
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `&Foo` as `*const str` is invalid
+error[E0606]: casting `&Foo` as `*const str` is invalid
   --> $DIR/cast-rfc0401.rs:64:13
    |
 64 |     let _ = foo as *const str;
    |             ^^^^^^^^^^^^^^^^^
 
-error: casting `&Foo` as `*mut str` is invalid
+error[E0606]: casting `&Foo` as `*mut str` is invalid
   --> $DIR/cast-rfc0401.rs:65:13
    |
 65 |     let _ = foo as *mut str;
    |             ^^^^^^^^^^^^^^^
 
-error: casting `fn() {main}` as `*mut str` is invalid
+error[E0606]: casting `fn() {main}` as `*mut str` is invalid
   --> $DIR/cast-rfc0401.rs:66:13
    |
 66 |     let _ = main as *mut str;
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `&f32` as `*mut f32` is invalid
+error[E0606]: casting `&f32` as `*mut f32` is invalid
   --> $DIR/cast-rfc0401.rs:67:13
    |
 67 |     let _ = &f as *mut f32;
    |             ^^^^^^^^^^^^^^
 
-error: casting `&f32` as `*const f64` is invalid
+error[E0606]: casting `&f32` as `*const f64` is invalid
   --> $DIR/cast-rfc0401.rs:68:13
    |
 68 |     let _ = &f as *const f64;
    |             ^^^^^^^^^^^^^^^^
 
-error: casting `*const [i8]` as `usize` is invalid
+error[E0606]: casting `*const [i8]` as `usize` is invalid
   --> $DIR/cast-rfc0401.rs:69:13
    |
 69 |     let _ = fat_sv as usize;
@@ -190,7 +200,7 @@ error: casting `*const [i8]` as `usize` is invalid
    |
    = help: cast through a thin pointer first
 
-error: casting `*const Foo` as `*const [u16]` is invalid
+error[E0606]: casting `*const Foo` as `*const [u16]` is invalid
   --> $DIR/cast-rfc0401.rs:78:13
    |
 78 |     let _ = cf as *const [u16];
@@ -198,7 +208,7 @@ error: casting `*const Foo` as `*const [u16]` is invalid
    |
    = note: vtable kinds may not match
 
-error: casting `*const Foo` as `*const Bar` is invalid
+error[E0606]: casting `*const Foo` as `*const Bar` is invalid
   --> $DIR/cast-rfc0401.rs:79:13
    |
 79 |     let _ = cf as *const Bar;
@@ -224,7 +234,7 @@ error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
    = help: the trait `std::marker::Sized` is not implemented for `str`
    = note: required for the cast to the object type `Foo`
 
-error: casting `&{float}` as `f32` is invalid
+error[E0606]: casting `&{float}` as `f32` is invalid
   --> $DIR/cast-rfc0401.rs:81:30
    |
 81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
@@ -236,5 +246,5 @@ help: did you mean `*s`?
 81 |     vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
    |                              ^
 
-error: aborting due to previous error(s)
+error: aborting due to 34 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index 85734dfac70..ca71154e872 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -31,5 +31,5 @@ error[E0593]: closure takes 1 argument but 2 arguments are required
    |               |
    |               expected closure that takes 2 arguments
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index 2c9c918168d..5b3eb593189 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -20,5 +20,5 @@ error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` im
    = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
    = note: required by `baz`
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/const-fn-in-trait.stderr b/src/test/ui/mismatched_types/const-fn-in-trait.stderr
index 5f67a66eb32..f7b7635e41a 100644
--- a/src/test/ui/mismatched_types/const-fn-in-trait.stderr
+++ b/src/test/ui/mismatched_types/const-fn-in-trait.stderr
@@ -10,5 +10,5 @@ error[E0379]: trait fns cannot be declared const
 21 |     const fn f() -> u32 { 22 }
    |     ^^^^^ trait fns cannot be const
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index 2030ad6c13b..120fb87cdc8 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -14,5 +14,5 @@ error[E0281]: type mismatch: `fn(&isize) {takes_imm}` implements the trait `for<
    |
    = note: required by `apply`
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/compile-fail/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs
index 8c61fc602e0..8c61fc602e0 100644
--- a/src/test/compile-fail/for-loop-has-unit-body.rs
+++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs
diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr
new file mode 100644
index 00000000000..4a619804a6c
--- /dev/null
+++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/for-loop-has-unit-body.rs:13:9
+   |
+13 |         x //~ ERROR mismatched types
+   |         ^ expected (), found integral variable
+   |
+   = note: expected type `()`
+              found type `{integer}`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr
index cbce4f810c5..2b4b8242af6 100644
--- a/src/test/ui/mismatched_types/issue-19109.stderr
+++ b/src/test/ui/mismatched_types/issue-19109.stderr
@@ -1,11 +1,13 @@
 error[E0308]: mismatched types
   --> $DIR/issue-19109.rs:14:5
    |
+13 | fn function(t: &mut Trait) {
+   |                            - help: possibly return type missing here? `-> *mut Trait `
 14 |     t as *mut Trait
    |     ^^^^^^^^^^^^^^^ expected (), found *-ptr
    |
    = note: expected type `()`
               found type `*mut Trait`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
index dc3764a376c..fae831ffb86 100644
--- a/src/test/ui/mismatched_types/issue-26480.stderr
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -7,7 +7,7 @@ error[E0308]: mismatched types
 37 |     write!(hello);
    |     -------------- in this macro invocation
 
-error: non-scalar cast: `{integer}` as `()`
+error[E0605]: non-primitive cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:32:19
    |
 32 |     ($x:expr) => ($x as ())
@@ -15,6 +15,8 @@ error: non-scalar cast: `{integer}` as `()`
 ...
 38 |     cast!(2);
    |     --------- in this macro invocation
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/issue-35030.stderr b/src/test/ui/mismatched_types/issue-35030.stderr
index 463d9fdf171..46d690c5f03 100644
--- a/src/test/ui/mismatched_types/issue-35030.stderr
+++ b/src/test/ui/mismatched_types/issue-35030.stderr
@@ -7,5 +7,5 @@ error[E0308]: mismatched types
    = note: expected type `bool` (type parameter)
               found type `bool` (bool)
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index f818bd8bcb1..51acdb719b6 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -17,5 +17,5 @@ error[E0281]: type mismatch: `[closure@$DIR/issue-36053-2.rs:17:39: 17:53]` impl
    |                                requires `for<'r> std::ops::FnMut<(&'r &str,)>`
    |                                expected &str, found str
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/issue-38371.stderr b/src/test/ui/mismatched_types/issue-38371.stderr
index 76ffa6e50e1..9efee4cc559 100644
--- a/src/test/ui/mismatched_types/issue-38371.stderr
+++ b/src/test/ui/mismatched_types/issue-38371.stderr
@@ -32,5 +32,5 @@ error[E0529]: expected an array or slice, found `u32`
 34 | fn ugh(&[bar]: &u32) {
    |         ^^^^^ pattern cannot match with input type `u32`
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr
index b4e688e025e..c8941fbf950 100644
--- a/src/test/ui/mismatched_types/main.stderr
+++ b/src/test/ui/mismatched_types/main.stderr
@@ -9,5 +9,5 @@ error[E0308]: mismatched types
    = note: expected type `u32`
               found type `()`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index 80f95da0bbe..ab5b3e17915 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -7,5 +7,5 @@ error[E0599]: no method named `unwrap` found for type `std::result::Result<(), F
    = note: the method `unwrap` exists but the following trait bounds were not satisfied:
            `Foo : std::fmt::Debug`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
index 7c644e3a72d..cd05684f15d 100644
--- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
+++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr
@@ -19,5 +19,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied
 45 |     let ans = s("burma", "shave");
    |                 ^^^^^^^^^^^^^^^^ expected 1 parameter
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr
index 9e7f79df35a..ccc9fb56772 100644
--- a/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr
+++ b/src/test/ui/mismatched_types/trait-bounds-cant-coerce.stderr
@@ -7,5 +7,5 @@ error[E0308]: mismatched types
    = note: expected type `std::boxed::Box<Foo + std::marker::Send + 'static>`
               found type `std::boxed::Box<Foo + 'static>`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
index 8741589f846..349432f64bb 100644
--- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
+++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr
@@ -22,5 +22,5 @@ error[E0053]: method `bar` has an incompatible type for trait
    = note: expected type `fn(&mut Bar, &mut Bar)`
               found type `fn(&mut Bar, &Bar)`
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index 643c9b36dbd..995a1258454 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -12,5 +12,5 @@ error[E0281]: type mismatch: `[closure@$DIR/unboxed-closures-vtable-mismatch.rs:
    |
    = note: required by `call_it`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/missing-items/issue-40221.stderr b/src/test/ui/missing-items/issue-40221.stderr
index 87854493790..fc90c8a2b20 100644
--- a/src/test/ui/missing-items/issue-40221.stderr
+++ b/src/test/ui/missing-items/issue-40221.stderr
@@ -4,5 +4,5 @@ error[E0004]: non-exhaustive patterns: `C(QA)` not covered
 21 |     match proto {
    |           ^^^^^ pattern `C(QA)` not covered
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/missing-items/m2.stderr b/src/test/ui/missing-items/m2.stderr
index 2d699c66359..51afb95b896 100644
--- a/src/test/ui/missing-items/m2.stderr
+++ b/src/test/ui/missing-items/m2.stderr
@@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `met
    = note: `Type` from trait: `type Type;`
    = note: `method` from trait: `fn(&Self, std::string::String) -> <Self as m1::X>::Type`
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/missing-items/missing-type-parameter.stderr b/src/test/ui/missing-items/missing-type-parameter.stderr
index ce38178bf87..a16ae5538bf 100644
--- a/src/test/ui/missing-items/missing-type-parameter.stderr
+++ b/src/test/ui/missing-items/missing-type-parameter.stderr
@@ -4,5 +4,5 @@ error[E0282]: type annotations needed
 14 |     foo();
    |     ^^^ cannot infer type for `X`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr
index 1e19977e84a..8fd1b8de687 100644
--- a/src/test/ui/path-lookahead.stderr
+++ b/src/test/ui/path-lookahead.stderr
@@ -23,6 +23,4 @@ warning: function is never used: `no_parens`
 20 | |   return <T as ToString>::to_string(&arg);
 21 | | }
    | |_^
-   |
-   = note: #[warn(dead_code)] on by default
 
diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr
index 94fc8f15c2b..470e8331247 100644
--- a/src/test/ui/pub/pub-restricted-error-fn.stderr
+++ b/src/test/ui/pub/pub-restricted-error-fn.stderr
@@ -4,5 +4,5 @@ error: unmatched visibility `pub`
 13 | pub(crate) () fn foo() {}
    |          ^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr
index eebb2428ba3..b8b4c80778d 100644
--- a/src/test/ui/pub/pub-restricted-error.stderr
+++ b/src/test/ui/pub/pub-restricted-error.stderr
@@ -4,5 +4,5 @@ error: expected identifier, found `(`
 16 |     pub(crate) () foo: usize,
    |                ^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/pub/pub-restricted-non-path.stderr b/src/test/ui/pub/pub-restricted-non-path.stderr
index 865b1d409e1..ebfccc4d720 100644
--- a/src/test/ui/pub/pub-restricted-non-path.stderr
+++ b/src/test/ui/pub/pub-restricted-non-path.stderr
@@ -4,5 +4,5 @@ error: expected identifier, found `.`
 13 | pub (.) fn afn() {}
    |      ^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr
index 34cc80fcc75..ae283f1fb63 100644
--- a/src/test/ui/pub/pub-restricted.stderr
+++ b/src/test/ui/pub/pub-restricted.stderr
@@ -48,5 +48,5 @@ error: visibilities can only be restricted to ancestor modules
 33 |         pub (in x) non_parent_invalid: usize,
    |                 ^
 
-error: aborting due to previous error(s)
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr
index cbcbf88d86e..1a2cc252051 100644
--- a/src/test/ui/reachable/expr_add.stderr
+++ b/src/test/ui/reachable/expr_add.stderr
@@ -10,5 +10,5 @@ note: lint level defined here
 13 | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr
index 20640c0a897..bf4e4dc4711 100644
--- a/src/test/ui/reachable/expr_again.stderr
+++ b/src/test/ui/reachable/expr_again.stderr
@@ -11,5 +11,5 @@ note: lint level defined here
    |         ^^^^^^^^^^^^^^^^
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr
index c778aec0810..f8dbdb5f8bb 100644
--- a/src/test/ui/reachable/expr_array.stderr
+++ b/src/test/ui/reachable/expr_array.stderr
@@ -16,5 +16,5 @@ error: unreachable expression
 25 |     let x: [usize; 2] = [22, return];
    |                         ^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr
index 9310c000192..807f6a1c1d5 100644
--- a/src/test/ui/reachable/expr_assign.stderr
+++ b/src/test/ui/reachable/expr_assign.stderr
@@ -22,5 +22,5 @@ error: unreachable expression
 36 |     *{return; &mut i} = 22;
    |               ^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr
index ea7b962e190..542ce1c3fd9 100644
--- a/src/test/ui/reachable/expr_block.stderr
+++ b/src/test/ui/reachable/expr_block.stderr
@@ -18,5 +18,5 @@ error: unreachable statement
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reachable/expr_box.stderr b/src/test/ui/reachable/expr_box.stderr
index ee89104df9e..78ba231cef9 100644
--- a/src/test/ui/reachable/expr_box.stderr
+++ b/src/test/ui/reachable/expr_box.stderr
@@ -10,5 +10,5 @@ note: lint level defined here
 13 | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr
index 5e072ed1dc7..5526827f59f 100644
--- a/src/test/ui/reachable/expr_call.stderr
+++ b/src/test/ui/reachable/expr_call.stderr
@@ -16,5 +16,5 @@ error: unreachable expression
 28 |     bar(return);
    |     ^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr
index a8668dc7355..a22300dcc13 100644
--- a/src/test/ui/reachable/expr_cast.stderr
+++ b/src/test/ui/reachable/expr_cast.stderr
@@ -10,5 +10,5 @@ note: lint level defined here
 14 | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr
index 7f901511f72..2cf17474f6e 100644
--- a/src/test/ui/reachable/expr_if.stderr
+++ b/src/test/ui/reachable/expr_if.stderr
@@ -11,5 +11,5 @@ note: lint level defined here
    |         ^^^^^^^^^^^^^^^^
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr
index 4fb6392f405..6e98e754c54 100644
--- a/src/test/ui/reachable/expr_loop.stderr
+++ b/src/test/ui/reachable/expr_loop.stderr
@@ -27,5 +27,5 @@ error: unreachable statement
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr
index 387f7900f49..f5857a5b345 100644
--- a/src/test/ui/reachable/expr_match.stderr
+++ b/src/test/ui/reachable/expr_match.stderr
@@ -26,5 +26,5 @@ error: unreachable statement
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr
index 68fd4973414..177d4352a37 100644
--- a/src/test/ui/reachable/expr_method.stderr
+++ b/src/test/ui/reachable/expr_method.stderr
@@ -16,5 +16,5 @@ error: unreachable expression
 31 |     Foo.bar(return);
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr
index 01b2e1009ee..19afc5dd7b5 100644
--- a/src/test/ui/reachable/expr_repeat.stderr
+++ b/src/test/ui/reachable/expr_repeat.stderr
@@ -10,5 +10,5 @@ note: lint level defined here
 14 | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr
index ee958aa9089..3eb70a4dd7c 100644
--- a/src/test/ui/reachable/expr_return.stderr
+++ b/src/test/ui/reachable/expr_return.stderr
@@ -10,5 +10,5 @@ note: lint level defined here
 14 | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr
index 08866bf32b8..4b7ac660413 100644
--- a/src/test/ui/reachable/expr_struct.stderr
+++ b/src/test/ui/reachable/expr_struct.stderr
@@ -28,5 +28,5 @@ error: unreachable expression
 40 |     let x = Foo { a: 22, b: return };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr
index 780fb02f790..63f477fd0c3 100644
--- a/src/test/ui/reachable/expr_tup.stderr
+++ b/src/test/ui/reachable/expr_tup.stderr
@@ -16,5 +16,5 @@ error: unreachable expression
 25 |     let x: (usize, usize) = (2, return);
    |                             ^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr
index 1216ec2676e..6ed79974ccb 100644
--- a/src/test/ui/reachable/expr_type.stderr
+++ b/src/test/ui/reachable/expr_type.stderr
@@ -10,5 +10,5 @@ note: lint level defined here
 14 | #![deny(unreachable_code)]
    |         ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr
index f47791455af..328b75fd236 100644
--- a/src/test/ui/reachable/expr_unary.stderr
+++ b/src/test/ui/reachable/expr_unary.stderr
@@ -4,5 +4,5 @@ error[E0600]: cannot apply unary operator `!` to type `!`
 18 |     let x: ! = ! { return; 22 };
    |                ^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr
index 3da057f4bbd..066cfc86c64 100644
--- a/src/test/ui/reachable/expr_while.stderr
+++ b/src/test/ui/reachable/expr_while.stderr
@@ -27,5 +27,5 @@ error: unreachable statement
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/regions-fn-subtyping-return-static.stderr b/src/test/ui/regions-fn-subtyping-return-static.stderr
index 121a50d0eda..0c7b44af949 100644
--- a/src/test/ui/regions-fn-subtyping-return-static.stderr
+++ b/src/test/ui/regions-fn-subtyping-return-static.stderr
@@ -9,5 +9,5 @@ error[E0308]: mismatched types
    = note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types
    = note: this error is the result of a recent bug fix; for more information, see issue #33685 <https://github.com/rust-lang/rust/issues/33685>
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
index 03e80046f67..17c5d5d15d4 100644
--- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr
+++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr
@@ -25,5 +25,5 @@ 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
    | use namespaced_enums::Foo::C;
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr
index 009d969fc28..11268e593c4 100644
--- a/src/test/ui/resolve/issue-14254.stderr
+++ b/src/test/ui/resolve/issue-14254.stderr
@@ -144,5 +144,5 @@ error[E0425]: cannot find value `bah` in this scope
 
 error[E0601]: main function not found
 
-error: aborting due to previous error(s)
+error: aborting due to 25 previous errors
 
diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr
index 2fbf7d7185d..63d2ce10914 100644
--- a/src/test/ui/resolve/issue-16058.stderr
+++ b/src/test/ui/resolve/issue-16058.stderr
@@ -9,5 +9,5 @@ help: possible better candidates are found in other modules, you can import them
    | use std::io::Result;
    | use std::thread::Result;
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-17518.stderr b/src/test/ui/resolve/issue-17518.stderr
index 69eeb178dff..c0438abfe43 100644
--- a/src/test/ui/resolve/issue-17518.stderr
+++ b/src/test/ui/resolve/issue-17518.stderr
@@ -7,5 +7,5 @@ error[E0422]: cannot find struct, variant or union type `E` in this scope
 help: possible candidate is found in another module, you can import it into scope
    | use SomeEnum::E;
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr
index 225e31010da..edc7196d846 100644
--- a/src/test/ui/resolve/issue-18252.stderr
+++ b/src/test/ui/resolve/issue-18252.stderr
@@ -4,5 +4,5 @@ error[E0423]: expected function, found struct variant `Foo::Variant`
 16 |     let f = Foo::Variant(42);
    |             ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`?
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr
index 25ee3a02146..7b14d49af51 100644
--- a/src/test/ui/resolve/issue-19452.stderr
+++ b/src/test/ui/resolve/issue-19452.stderr
@@ -10,5 +10,5 @@ error[E0423]: expected value, found struct variant `issue_19452_aux::Homura::Mad
 22 |     let homura = issue_19452_aux::Homura::Madoka;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`?
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr
index 2ca541c161b..fda87de9b9c 100644
--- a/src/test/ui/resolve/issue-23305.stderr
+++ b/src/test/ui/resolve/issue-23305.stderr
@@ -11,5 +11,5 @@ note: the cycle begins when processing `<impl at $DIR/issue-23305.rs:15:1: 15:20
    | ^^^^^^^^^^^^^^^^^^^
    = note: ...which then again requires processing `<impl at $DIR/issue-23305.rs:15:1: 15:20>`, completing the cycle.
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr
index 559598dd38a..039887d8da6 100644
--- a/src/test/ui/resolve/issue-2356.stderr
+++ b/src/test/ui/resolve/issue-2356.stderr
@@ -106,5 +106,5 @@ error[E0424]: expected value, found module `self`
 122 |     self += 1;
     |     ^^^^ `self` value is only available in methods with `self` parameter
 
-error: aborting due to previous error(s)
+error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/resolve/issue-24968.stderr b/src/test/ui/resolve/issue-24968.stderr
index 14a2413feee..111710d515a 100644
--- a/src/test/ui/resolve/issue-24968.stderr
+++ b/src/test/ui/resolve/issue-24968.stderr
@@ -4,5 +4,5 @@ error[E0411]: cannot find type `Self` in this scope
 11 | fn foo(_: Self) {
    |           ^^^^ `Self` is only available in traits and impls
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-33876.stderr b/src/test/ui/resolve/issue-33876.stderr
index a950075715a..5dbecc4f0c5 100644
--- a/src/test/ui/resolve/issue-33876.stderr
+++ b/src/test/ui/resolve/issue-33876.stderr
@@ -4,5 +4,5 @@ error[E0423]: expected value, found trait `Bar`
 20 |     let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar`
    |                      ^^^ not a value
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-3907-2.stderr b/src/test/ui/resolve/issue-3907-2.stderr
index 4e1ef25f803..2ef8c830eb2 100644
--- a/src/test/ui/resolve/issue-3907-2.stderr
+++ b/src/test/ui/resolve/issue-3907-2.stderr
@@ -6,5 +6,5 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
    |
    = note: method `bar` has no receiver
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr
index 134a4540a8d..f6ee0b025bb 100644
--- a/src/test/ui/resolve/issue-39226.stderr
+++ b/src/test/ui/resolve/issue-39226.stderr
@@ -7,5 +7,5 @@ error[E0423]: expected value, found struct `Handle`
    |                 did you mean `handle`?
    |                 did you mean `Handle { /* fields */ }`?
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
index 9bdd7ee4fd4..791b20725f3 100644
--- a/src/test/ui/resolve/issue-5035-2.stderr
+++ b/src/test/ui/resolve/issue-5035-2.stderr
@@ -7,5 +7,5 @@ error[E0277]: the trait bound `I + 'static: std::marker::Sized` is not satisfied
    = help: the trait `std::marker::Sized` is not implemented for `I + 'static`
    = note: all local variables must have a statically known size
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr
index 620958190ca..b50295752f2 100644
--- a/src/test/ui/resolve/issue-6702.stderr
+++ b/src/test/ui/resolve/issue-6702.stderr
@@ -4,5 +4,5 @@ error[E0423]: expected function, found struct `Monster`
 17 |     let _m = Monster(); //~ ERROR expected function, found struct `Monster`
    |              ^^^^^^^ did you mean `Monster { /* fields */ }`?
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
index d25c52eeab3..4dff2620319 100644
--- a/src/test/ui/resolve/levenshtein.stderr
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -46,5 +46,5 @@ error[E0425]: cannot find value `second` in module `m`
 32 |     let b: m::first = m::second; // Misspelled item in module.
    |                          ^^^^^^ did you mean `Second`?
 
-error: aborting due to previous error(s)
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr
index a1ec5f0b713..18efb17dd46 100644
--- a/src/test/ui/resolve/privacy-struct-ctor.stderr
+++ b/src/test/ui/resolve/privacy-struct-ctor.stderr
@@ -65,5 +65,5 @@ error[E0603]: tuple struct `Z` is private
 45 |     xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
    |     ^^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr
index c346612a68b..7975c168de7 100644
--- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr
+++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr
@@ -52,5 +52,5 @@ error[E0425]: cannot find value `method` in this scope
 52 |         method;
    |         ^^^^^^ did you mean `self.method(...)`?
 
-error: aborting due to previous error(s)
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr
index 92f13f705b0..ffb3f848430 100644
--- a/src/test/ui/resolve/resolve-hint-macro.stderr
+++ b/src/test/ui/resolve/resolve-hint-macro.stderr
@@ -4,5 +4,5 @@ error[E0423]: expected function, found macro `assert`
 12 |     assert(true);
    |     ^^^^^^ did you mean `assert!(...)`?
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr
index 04c8087ace9..e7df8140bc5 100644
--- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr
+++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr
@@ -22,5 +22,5 @@ error[E0425]: cannot find function `method` in this scope
 38 |         method();
    |         ^^^^^^ did you mean `self.method(...)`?
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
index a34c27a47da..d1794d19f6a 100644
--- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
@@ -74,5 +74,5 @@ error[E0423]: expected function, found module `a::b`
 
 error[E0601]: main function not found
 
-error: aborting due to previous error(s)
+error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/resolve/token-error-correct-2.stderr b/src/test/ui/resolve/token-error-correct-2.stderr
index 7307f19c74d..feb12612e66 100644
--- a/src/test/ui/resolve/token-error-correct-2.stderr
+++ b/src/test/ui/resolve/token-error-correct-2.stderr
@@ -16,5 +16,5 @@ error[E0425]: cannot find value `foo` in this scope
 14 |     if foo {
    |        ^^^ not found in this scope
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr
index d234c8538fe..bd3bdf35da6 100644
--- a/src/test/ui/resolve/token-error-correct-3.stderr
+++ b/src/test/ui/resolve/token-error-correct-3.stderr
@@ -35,10 +35,12 @@ error[E0308]: mismatched types
   --> $DIR/token-error-correct-3.rs:25:13
    |
 25 |             fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;`
+   |             |
+   |             expected (), found enum `std::result::Result`
    |
    = note: expected type `()`
               found type `std::result::Result<bool, std::io::Error>`
 
-error: aborting due to previous error(s)
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr
index 1dd263affd4..226fa6469bc 100644
--- a/src/test/ui/resolve/token-error-correct.stderr
+++ b/src/test/ui/resolve/token-error-correct.stderr
@@ -52,5 +52,5 @@ error[E0425]: cannot find function `bar` in this scope
 14 |     foo(bar(;
    |         ^^^ not found in this scope
 
-error: aborting due to previous error(s)
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr
index 2fc5979a606..e2ef8f0e568 100644
--- a/src/test/ui/resolve/tuple-struct-alias.stderr
+++ b/src/test/ui/resolve/tuple-struct-alias.stderr
@@ -28,5 +28,5 @@ error[E0532]: expected tuple struct/variant, found type alias `A`
    |         did you mean `S`?
    |         did you mean `A { /* fields */ }`?
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/resolve/unresolved_static_type_field.stderr b/src/test/ui/resolve/unresolved_static_type_field.stderr
index ff6bcf2a532..5fbaf66e014 100644
--- a/src/test/ui/resolve/unresolved_static_type_field.stderr
+++ b/src/test/ui/resolve/unresolved_static_type_field.stderr
@@ -7,5 +7,5 @@ error[E0425]: cannot find value `cx` in this scope
    |           did you mean `self.cx`?
    |           `self` value is only available in methods with `self` parameter
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/compile-fail/shadowed-type-parameter.rs b/src/test/ui/shadowed-type-parameter.rs
index 1f72db1e894..1f72db1e894 100644
--- a/src/test/compile-fail/shadowed-type-parameter.rs
+++ b/src/test/ui/shadowed-type-parameter.rs
diff --git a/src/test/ui/shadowed-type-parameter.stderr b/src/test/ui/shadowed-type-parameter.stderr
new file mode 100644
index 00000000000..a16a9c0244f
--- /dev/null
+++ b/src/test/ui/shadowed-type-parameter.stderr
@@ -0,0 +1,28 @@
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+  --> $DIR/shadowed-type-parameter.rs:30:27
+   |
+27 | trait Bar<T> {
+   |           - first `T` declared here
+...
+30 |     fn shadow_in_required<T>(&self);
+   |                           ^ shadows another type parameter
+
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+  --> $DIR/shadowed-type-parameter.rs:33:27
+   |
+27 | trait Bar<T> {
+   |           - first `T` declared here
+...
+33 |     fn shadow_in_provided<T>(&self) {}
+   |                           ^ shadows another type parameter
+
+error[E0194]: type parameter `T` shadows another type parameter of the same name
+  --> $DIR/shadowed-type-parameter.rs:18:25
+   |
+17 | impl<T> Foo<T> {
+   |      - first `T` declared here
+18 |     fn shadow_in_method<T>(&self) {}
+   |                         ^ shadows another type parameter
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/span/E0046.stderr b/src/test/ui/span/E0046.stderr
index f722908ec10..729a5156124 100644
--- a/src/test/ui/span/E0046.stderr
+++ b/src/test/ui/span/E0046.stderr
@@ -7,5 +7,5 @@ error[E0046]: not all trait items implemented, missing: `foo`
 18 | impl Foo for Bar {}
    | ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr
index bc3a3908dca..0d6b0a552e4 100644
--- a/src/test/ui/span/E0057.stderr
+++ b/src/test/ui/span/E0057.stderr
@@ -10,5 +10,5 @@ error[E0057]: this function takes 1 parameter but 2 parameters were supplied
 15 |     let c = f(2, 3); //~ ERROR E0057
    |               ^^^^ expected 1 parameter
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr
index 14e6bcb73b0..1f6dd6b1d16 100644
--- a/src/test/ui/span/E0072.stderr
+++ b/src/test/ui/span/E0072.stderr
@@ -9,5 +9,5 @@ error[E0072]: recursive type `ListNode` has infinite size
    |
    = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr
index fab2436922d..4fe6afaca8e 100644
--- a/src/test/ui/span/E0204.stderr
+++ b/src/test/ui/span/E0204.stderr
@@ -34,5 +34,5 @@ error[E0204]: the trait `Copy` may not be implemented for this type
 31 |     Bar(&'a mut bool),
    |         ------------- this field does not implement `Copy`
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr
index 5f8b57294d5..afcc9a240eb 100644
--- a/src/test/ui/span/E0493.stderr
+++ b/src/test/ui/span/E0493.stderr
@@ -7,5 +7,5 @@ error[E0493]: constants are not allowed to have destructors
 27 | const F : Foo = Foo { a : 0 };
    |                 ^^^^^^^^^^^^^ constants cannot have destructors
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr
index 64c0016085f..23070e1555b 100644
--- a/src/test/ui/span/E0535.stderr
+++ b/src/test/ui/span/E0535.stderr
@@ -4,5 +4,5 @@ error[E0535]: invalid argument
 11 | #[inline(unknown)] //~ ERROR E0535
    |          ^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr
index 8a4cf34e565..b2da0c6a296 100644
--- a/src/test/ui/span/E0536.stderr
+++ b/src/test/ui/span/E0536.stderr
@@ -4,5 +4,5 @@ error[E0536]: expected 1 cfg-pattern
 11 | #[cfg(not())] //~ ERROR E0536
    |       ^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr
index 1bd54a6a007..29873943f44 100644
--- a/src/test/ui/span/E0537.stderr
+++ b/src/test/ui/span/E0537.stderr
@@ -4,5 +4,5 @@ error[E0537]: invalid predicate `unknown`
 11 | #[cfg(unknown())] //~ ERROR E0537
    |       ^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
index 4b01f5bea7c..2d580e7c20e 100644
--- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
+++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
@@ -82,5 +82,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
 143 |     *x.y_mut() = 3; //~ ERROR cannot borrow
     |      ^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
index 886cc142039..3d380a9a2e8 100644
--- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
+++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
@@ -30,5 +30,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
 63 |     **x = 3; //~ ERROR cannot borrow
    |      ^^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
index a26ca490dd5..6e7d0c17f1d 100644
--- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
+++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
@@ -47,5 +47,5 @@ error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
 72 |         foo(f);
    |             ^ cannot move out of captured outer variable in an `FnMut` closure
 
-error: aborting due to previous error(s)
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr
index dea95d6bf6d..a57cc94b9ba 100644
--- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr
+++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr
@@ -7,5 +7,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
 27 |     x.h(); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr
index 3bf56881c54..45712d1a710 100644
--- a/src/test/ui/span/borrowck-fn-in-const-b.stderr
+++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr
@@ -6,5 +6,5 @@ error[E0596]: cannot borrow immutable borrowed content `*x` as mutable
 17 |         x.push(format!("this is broken"));
    |         ^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
index 04dbcd2ef49..6ed1b7c2622 100644
--- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
+++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr
@@ -48,5 +48,5 @@ error[E0597]: borrowed value does not live long enough
    |
    = note: consider using a `let` binding to increase its lifetime
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr
index 877b17dc27d..530993f399a 100644
--- a/src/test/ui/span/borrowck-object-mutability.stderr
+++ b/src/test/ui/span/borrowck-object-mutability.stderr
@@ -16,5 +16,5 @@ error[E0596]: cannot borrow immutable `Box` content `*x` as mutable
 29 |     x.borrowed_mut(); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/borrowck-ref-into-rvalue.stderr b/src/test/ui/span/borrowck-ref-into-rvalue.stderr
index e0a484bcb37..ced1f762af4 100644
--- a/src/test/ui/span/borrowck-ref-into-rvalue.stderr
+++ b/src/test/ui/span/borrowck-ref-into-rvalue.stderr
@@ -12,5 +12,5 @@ error[E0597]: borrowed value does not live long enough
    |
    = note: consider using a `let` binding to increase its lifetime
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr
index e3bc64a2cfd..b703632bf90 100644
--- a/src/test/ui/span/coerce-suggestions.stderr
+++ b/src/test/ui/span/coerce-suggestions.stderr
@@ -58,5 +58,5 @@ error[E0308]: mismatched types
    = help: try with `&mut format!("foo")`
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/destructor-restrictions.stderr b/src/test/ui/span/destructor-restrictions.stderr
index 1472a364863..ee885454169 100644
--- a/src/test/ui/span/destructor-restrictions.stderr
+++ b/src/test/ui/span/destructor-restrictions.stderr
@@ -8,5 +8,5 @@ error[E0597]: `*a` does not live long enough
    |     |
    |     `*a` dropped here while still borrowed
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/dropck-object-cycle.stderr b/src/test/ui/span/dropck-object-cycle.stderr
index d0fceb2a03e..49115b244e6 100644
--- a/src/test/ui/span/dropck-object-cycle.stderr
+++ b/src/test/ui/span/dropck-object-cycle.stderr
@@ -9,5 +9,5 @@ error[E0597]: `*m` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.stderr b/src/test/ui/span/dropck_arr_cycle_checked.stderr
index 2a9c2c8413f..4179ac1a946 100644
--- a/src/test/ui/span/dropck_arr_cycle_checked.stderr
+++ b/src/test/ui/span/dropck_arr_cycle_checked.stderr
@@ -63,5 +63,5 @@ error[E0597]: `b2` does not live long enough
     |
     = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr
index e6421cd4785..597d42aabd2 100644
--- a/src/test/ui/span/dropck_direct_cycle_with_drop.stderr
+++ b/src/test/ui/span/dropck_direct_cycle_with_drop.stderr
@@ -19,5 +19,5 @@ error[E0597]: `d1` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/dropck_misc_variants.stderr b/src/test/ui/span/dropck_misc_variants.stderr
index 7fbdcba7eb6..958f229f659 100644
--- a/src/test/ui/span/dropck_misc_variants.stderr
+++ b/src/test/ui/span/dropck_misc_variants.stderr
@@ -19,5 +19,5 @@ error[E0597]: `v` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/dropck_vec_cycle_checked.stderr b/src/test/ui/span/dropck_vec_cycle_checked.stderr
index 3861b145c1b..d7d0fe5323b 100644
--- a/src/test/ui/span/dropck_vec_cycle_checked.stderr
+++ b/src/test/ui/span/dropck_vec_cycle_checked.stderr
@@ -63,5 +63,5 @@ error[E0597]: `c2` does not live long enough
     |
     = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/impl-wrong-item-for-trait.stderr b/src/test/ui/span/impl-wrong-item-for-trait.stderr
index ca7286f5027..2c4c6a148d7 100644
--- a/src/test/ui/span/impl-wrong-item-for-trait.stderr
+++ b/src/test/ui/span/impl-wrong-item-for-trait.stderr
@@ -85,5 +85,5 @@ error[E0046]: not all trait items implemented, missing: `fmt`
    |
    = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
 
-error: aborting due to previous error(s)
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/span/issue-11925.stderr b/src/test/ui/span/issue-11925.stderr
index 67d60fe085a..6b2942bc7a8 100644
--- a/src/test/ui/span/issue-11925.stderr
+++ b/src/test/ui/span/issue-11925.stderr
@@ -10,5 +10,5 @@ error[E0597]: `x` does not live long enough
 23 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr
index f5f987c823f..ce1c6e81b96 100644
--- a/src/test/ui/span/issue-15480.stderr
+++ b/src/test/ui/span/issue-15480.stderr
@@ -11,5 +11,5 @@ error[E0597]: borrowed value does not live long enough
    |
    = note: consider using a `let` binding to increase its lifetime
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
index e564b7ccef2..02c03315372 100644
--- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
+++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.stderr
@@ -18,5 +18,5 @@ error[E0597]: `y` does not live long enough
    |     |
    |     `y` dropped here while still borrowed
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-23729.stderr b/src/test/ui/span/issue-23729.stderr
index d6aed36c8f6..d9f4bacce35 100644
--- a/src/test/ui/span/issue-23729.stderr
+++ b/src/test/ui/span/issue-23729.stderr
@@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Item`
    |
    = note: `Item` from trait: `type Item;`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-23827.stderr b/src/test/ui/span/issue-23827.stderr
index a1d3f5c11df..3127af157a6 100644
--- a/src/test/ui/span/issue-23827.stderr
+++ b/src/test/ui/span/issue-23827.stderr
@@ -12,5 +12,5 @@ error[E0046]: not all trait items implemented, missing: `Output`
    |
    = note: `Output` from trait: `type Output;`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-24356.stderr b/src/test/ui/span/issue-24356.stderr
index 771ea787304..71ab82d98b8 100644
--- a/src/test/ui/span/issue-24356.stderr
+++ b/src/test/ui/span/issue-24356.stderr
@@ -11,5 +11,5 @@ error[E0046]: not all trait items implemented, missing: `Target`
    |
    = note: `Target` from trait: `type Target;`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr
index 598f9f51307..8332ba50a73 100644
--- a/src/test/ui/span/issue-24690.stderr
+++ b/src/test/ui/span/issue-24690.stderr
@@ -4,20 +4,18 @@ error: variable `theTwo` should have a snake case name such as `the_two`
 19 |     let theTwo = 2;
    |         ^^^^^^
    |
-   = note: #[deny(non_snake_case)] implied by #[deny(warnings)]
 note: lint level defined here
   --> $DIR/issue-24690.rs:16:9
    |
 16 | #![deny(warnings)]
    |         ^^^^^^^^
+   = note: #[deny(non_snake_case)] implied by #[deny(warnings)]
 
 error: variable `theOtherTwo` should have a snake case name such as `the_other_two`
   --> $DIR/issue-24690.rs:20:9
    |
 20 |     let theOtherTwo = 2;
    |         ^^^^^^^^^^^
-   |
-   = note: #[deny(non_snake_case)] implied by #[deny(warnings)]
 
 error: unused variable: `theOtherTwo`
   --> $DIR/issue-24690.rs:20:9
@@ -25,12 +23,12 @@ error: unused variable: `theOtherTwo`
 20 |     let theOtherTwo = 2;
    |         ^^^^^^^^^^^
    |
-   = note: #[deny(unused_variables)] implied by #[deny(warnings)]
 note: lint level defined here
   --> $DIR/issue-24690.rs:16:9
    |
 16 | #![deny(warnings)]
    |         ^^^^^^^^
+   = note: #[deny(unused_variables)] implied by #[deny(warnings)]
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
index 314ef0ecbbc..29587b7fbde 100644
--- a/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
+++ b/src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.stderr
@@ -9,5 +9,5 @@ error[E0597]: `d1` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr
index 66f22d14578..c88d4a0202f 100644
--- a/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr
+++ b/src/test/ui/span/issue-24805-dropck-trait-has-items.stderr
@@ -28,5 +28,5 @@ error[E0597]: `d1` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr
index cfa8359088a..7f80e6e115a 100644
--- a/src/test/ui/span/issue-24895-copy-clone-dropck.stderr
+++ b/src/test/ui/span/issue-24895-copy-clone-dropck.stderr
@@ -8,5 +8,5 @@ error[E0597]: `d1` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-25199.stderr b/src/test/ui/span/issue-25199.stderr
index 999871db093..4f403b38f5a 100644
--- a/src/test/ui/span/issue-25199.stderr
+++ b/src/test/ui/span/issue-25199.stderr
@@ -19,5 +19,5 @@ error[E0597]: `container` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-26656.stderr b/src/test/ui/span/issue-26656.stderr
index b4f0195f6a8..748fcae48fc 100644
--- a/src/test/ui/span/issue-26656.stderr
+++ b/src/test/ui/span/issue-26656.stderr
@@ -8,5 +8,5 @@ error[E0597]: `ticking` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-27522.stderr b/src/test/ui/span/issue-27522.stderr
index 443595c6d2c..117b109780b 100644
--- a/src/test/ui/span/issue-27522.stderr
+++ b/src/test/ui/span/issue-27522.stderr
@@ -7,5 +7,5 @@ error[E0308]: mismatched method receiver
    = note: expected type `&Self`
               found type `&SomeType`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-29106.stderr b/src/test/ui/span/issue-29106.stderr
index b645cbf402d..f146028c2fc 100644
--- a/src/test/ui/span/issue-29106.stderr
+++ b/src/test/ui/span/issue-29106.stderr
@@ -18,5 +18,5 @@ error[E0597]: `x` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-29595.stderr b/src/test/ui/span/issue-29595.stderr
index 4065c4fb857..abbac245f89 100644
--- a/src/test/ui/span/issue-29595.stderr
+++ b/src/test/ui/span/issue-29595.stderr
@@ -6,5 +6,5 @@ error[E0277]: the trait bound `u8: Tr` is not satisfied
    |
    = note: required by `Tr::C`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr
index 38256ec944b..2a874181c7a 100644
--- a/src/test/ui/span/issue-33884.stderr
+++ b/src/test/ui/span/issue-33884.stderr
@@ -8,5 +8,5 @@ error[E0308]: mismatched types
               found type `std::string::String`
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index 48ed0b4ac89..e25caacac8f 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -45,5 +45,5 @@ error[E0061]: this function takes 2 parameters but 3 parameters were supplied
 19 |     bar(1, 2, 3);
    |         ^^^^^^^ expected 2 parameters
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/issue-36530.stderr b/src/test/ui/span/issue-36530.stderr
index 5dc9bd8b79b..dc6190c2e76 100644
--- a/src/test/ui/span/issue-36530.stderr
+++ b/src/test/ui/span/issue-36530.stderr
@@ -14,5 +14,5 @@ error: The attribute `foo` is currently unknown to the compiler and may have mea
    |
    = help: add #![feature(custom_attribute)] to the crate attributes to enable
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-36537.stderr b/src/test/ui/span/issue-36537.stderr
index df06cd1d0ea..803e476b749 100644
--- a/src/test/ui/span/issue-36537.stderr
+++ b/src/test/ui/span/issue-36537.stderr
@@ -8,5 +8,5 @@ error[E0597]: `a` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr
index bd271641e7e..7cf74eaab8d 100644
--- a/src/test/ui/span/issue-37767.stderr
+++ b/src/test/ui/span/issue-37767.stderr
@@ -55,5 +55,5 @@ note: candidate #2 is defined in the trait `F`
    |     ^^^^^^^^^^^^^^^
    = help: to disambiguate the method call, write `F::foo(a)` instead
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr
index f0b940cdf3f..cd3a41b037c 100644
--- a/src/test/ui/span/issue-39018.stderr
+++ b/src/test/ui/span/issue-39018.stderr
@@ -15,5 +15,5 @@ error[E0369]: binary operation `+` cannot be applied to type `World`
    |
    = note: an implementation of `std::ops::Add` might be missing for `World`
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue-39698.stderr b/src/test/ui/span/issue-39698.stderr
index 0d0a07629c4..97d802f8398 100644
--- a/src/test/ui/span/issue-39698.stderr
+++ b/src/test/ui/span/issue-39698.stderr
@@ -38,5 +38,5 @@ error[E0408]: variable `c` is not bound in all patterns
    |         |             pattern doesn't bind `c`
    |         pattern doesn't bind `c`
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr
index 50183aa3bde..b689bef63f1 100644
--- a/src/test/ui/span/issue-40157.stderr
+++ b/src/test/ui/span/issue-40157.stderr
@@ -10,5 +10,5 @@ error[E0597]: `foo` does not live long enough
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index 9bf00b1b574..858c099d374 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -63,5 +63,5 @@ note: candidate #1 is defined in the trait `ManyImplTrait`
    = note: the following trait defines an item `is_str`, perhaps you need to implement it:
            candidate #1: `ManyImplTrait`
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/span/issue28498-reject-ex1.stderr b/src/test/ui/span/issue28498-reject-ex1.stderr
index a2ef99f9d76..6beb3109c75 100644
--- a/src/test/ui/span/issue28498-reject-ex1.stderr
+++ b/src/test/ui/span/issue28498-reject-ex1.stderr
@@ -19,5 +19,5 @@ error[E0597]: `foo.data` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue28498-reject-lifetime-param.stderr b/src/test/ui/span/issue28498-reject-lifetime-param.stderr
index cb77cd3dc99..358fa9b7c45 100644
--- a/src/test/ui/span/issue28498-reject-lifetime-param.stderr
+++ b/src/test/ui/span/issue28498-reject-lifetime-param.stderr
@@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr
index 49116c340ec..0aaf2b27f60 100644
--- a/src/test/ui/span/issue28498-reject-passed-to-fn.stderr
+++ b/src/test/ui/span/issue28498-reject-passed-to-fn.stderr
@@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/issue28498-reject-trait-bound.stderr b/src/test/ui/span/issue28498-reject-trait-bound.stderr
index bb4de82422a..27a4d2384ab 100644
--- a/src/test/ui/span/issue28498-reject-trait-bound.stderr
+++ b/src/test/ui/span/issue28498-reject-trait-bound.stderr
@@ -20,5 +20,5 @@ error[E0597]: `first_dropped` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr
index 2f5e60a1b3c..f4998e08907 100644
--- a/src/test/ui/span/lint-unused-unsafe.stderr
+++ b/src/test/ui/span/lint-unused-unsafe.stderr
@@ -106,5 +106,5 @@ note: because it's nested under this `unsafe` fn
 44 | | }
    | |_^
 
-error: aborting due to previous error(s)
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/span/loan-extend.stderr b/src/test/ui/span/loan-extend.stderr
index 036c4bd6b8d..91bdd8a8cad 100644
--- a/src/test/ui/span/loan-extend.stderr
+++ b/src/test/ui/span/loan-extend.stderr
@@ -9,5 +9,5 @@ error[E0597]: `short` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr
index f76c5b049c4..2294e6476d6 100644
--- a/src/test/ui/span/move-closure.stderr
+++ b/src/test/ui/span/move-closure.stderr
@@ -7,5 +7,5 @@ error[E0308]: mismatched types
    = note: expected type `()`
               found type `[closure@$DIR/move-closure.rs:15:17: 15:27]`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr
index 881c2f5df45..a06cbd04deb 100644
--- a/src/test/ui/span/multiline-span-E0072.stderr
+++ b/src/test/ui/span/multiline-span-E0072.stderr
@@ -12,5 +12,5 @@ error[E0072]: recursive type `ListNode` has infinite size
    |
    = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/multiline-span-simple.stderr b/src/test/ui/span/multiline-span-simple.stderr
index 0224cef8da1..3915f1b655c 100644
--- a/src/test/ui/span/multiline-span-simple.stderr
+++ b/src/test/ui/span/multiline-span-simple.stderr
@@ -6,5 +6,5 @@ error[E0277]: the trait bound `u32: std::ops::Add<()>` is not satisfied
    |
    = help: the trait `std::ops::Add<()>` is not implemented for `u32`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr
index 754e96aa808..f8584c67390 100644
--- a/src/test/ui/span/mut-arg-hint.stderr
+++ b/src/test/ui/span/mut-arg-hint.stderr
@@ -22,5 +22,5 @@ error[E0596]: cannot borrow immutable borrowed content `*a` as mutable
 25 |         a.push_str("foo");
    |         ^ cannot borrow as mutable
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr
index 5bd6a786cfd..007a9fad830 100644
--- a/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr
+++ b/src/test/ui/span/mut-ptr-cant-outlive-ref.stderr
@@ -8,5 +8,5 @@ error[E0597]: `b` does not live long enough
 20 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/pub-struct-field.stderr b/src/test/ui/span/pub-struct-field.stderr
index 835b08f8907..c66361c8546 100644
--- a/src/test/ui/span/pub-struct-field.stderr
+++ b/src/test/ui/span/pub-struct-field.stderr
@@ -15,5 +15,5 @@ error[E0124]: field `bar` is already declared
 17 |     pub(crate) bar: u8,
    |     ^^^^^^^^^^^^^^^^^^ field already declared
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/range-2.stderr b/src/test/ui/span/range-2.stderr
index 465a663a741..285ab4aee4b 100644
--- a/src/test/ui/span/range-2.stderr
+++ b/src/test/ui/span/range-2.stderr
@@ -20,5 +20,5 @@ error[E0597]: `b` does not live long enough
 21 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr
index 72177754681..b4d0b5a6a25 100644
--- a/src/test/ui/span/recursive-type-field.stderr
+++ b/src/test/ui/span/recursive-type-field.stderr
@@ -27,5 +27,5 @@ error[E0072]: recursive type `Bar` has infinite size
    |
    = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr
index 80dadd97a17..29848412e4e 100644
--- a/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr
+++ b/src/test/ui/span/regionck-unboxed-closure-lifetimes.stderr
@@ -9,5 +9,5 @@ error[E0597]: `c` does not live long enough
 20 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
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 25386cb30b1..e671f1daf61 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
@@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough
 23 | }
    | - temporary value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.stderr
index 9b5383877a0..a89127b1436 100644
--- a/src/test/ui/span/regions-close-over-type-parameter-2.stderr
+++ b/src/test/ui/span/regions-close-over-type-parameter-2.stderr
@@ -9,5 +9,5 @@ error[E0597]: `tmp0` does not live long enough
    |     |
    |     `tmp0` dropped here while still borrowed
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/regions-escape-loop-via-variable.stderr b/src/test/ui/span/regions-escape-loop-via-variable.stderr
index 9f8c91cb9cd..cfdd1c8b153 100644
--- a/src/test/ui/span/regions-escape-loop-via-variable.stderr
+++ b/src/test/ui/span/regions-escape-loop-via-variable.stderr
@@ -8,5 +8,5 @@ error[E0597]: `x` does not live long enough
 23 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/regions-escape-loop-via-vec.stderr b/src/test/ui/span/regions-escape-loop-via-vec.stderr
index 4f0e61f1133..b61df82e8a1 100644
--- a/src/test/ui/span/regions-escape-loop-via-vec.stderr
+++ b/src/test/ui/span/regions-escape-loop-via-vec.stderr
@@ -37,5 +37,5 @@ error[E0506]: cannot assign to `x` because it is borrowed
 24 |         x += 1; //~ ERROR cannot assign
    |         ^^^^^^ assignment to borrowed `x` occurs here
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr
index 43103e619a5..0960f5e1b25 100644
--- a/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr
+++ b/src/test/ui/span/regions-infer-borrow-scope-within-loop.stderr
@@ -10,5 +10,5 @@ error[E0597]: `*x` does not live long enough
 30 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr
index b5e55adfb45..02fc9820495 100644
--- a/src/test/ui/span/send-is-not-static-ensures-scoping.stderr
+++ b/src/test/ui/span/send-is-not-static-ensures-scoping.stderr
@@ -24,5 +24,5 @@ error[E0597]: `y` does not live long enough
 35 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.stderr
index 2845c4f6bda..318dab599f5 100644
--- a/src/test/ui/span/send-is-not-static-std-sync-2.stderr
+++ b/src/test/ui/span/send-is-not-static-std-sync-2.stderr
@@ -32,5 +32,5 @@ error[E0597]: `x` does not live long enough
 44 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/span/send-is-not-static-std-sync.stderr b/src/test/ui/span/send-is-not-static-std-sync.stderr
index 3d75a1b717a..988ff228105 100644
--- a/src/test/ui/span/send-is-not-static-std-sync.stderr
+++ b/src/test/ui/span/send-is-not-static-std-sync.stderr
@@ -52,5 +52,5 @@ error[E0505]: cannot move out of `y` because it is borrowed
 49 |     drop(y); //~ ERROR cannot move out
    |          ^ move out of `y` occurs here
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr
index 0c07d068d28..b60ccd0fbf3 100644
--- a/src/test/ui/span/slice-borrow.stderr
+++ b/src/test/ui/span/slice-borrow.stderr
@@ -9,5 +9,5 @@ error[E0597]: borrowed value does not live long enough
 19 | }
    | - temporary value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr
index 68d43d3f5cd..c2ab7542d8a 100644
--- a/src/test/ui/span/suggestion-non-ascii.stderr
+++ b/src/test/ui/span/suggestion-non-ascii.stderr
@@ -4,5 +4,5 @@ error[E0608]: cannot index into a value of type `({integer},)`
 14 |     println!("☃{}", tup[0]);
    |                     ^^^^^^ help: to access tuple elements, use `tup.0`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/type-binding.stderr b/src/test/ui/span/type-binding.stderr
index afe069e7aa6..dc37acaf3f9 100644
--- a/src/test/ui/span/type-binding.stderr
+++ b/src/test/ui/span/type-binding.stderr
@@ -4,5 +4,5 @@ error[E0220]: associated type `Trget` not found for `std::ops::Deref`
 16 | fn homura<T: Deref<Trget = i32>>(_: T) {}
    |                    ^^^^^^^^^^^ associated type `Trget` not found
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/span/typo-suggestion.stderr b/src/test/ui/span/typo-suggestion.stderr
index 6556e5b4c00..dca0a93f897 100644
--- a/src/test/ui/span/typo-suggestion.stderr
+++ b/src/test/ui/span/typo-suggestion.stderr
@@ -10,5 +10,5 @@ error[E0425]: cannot find value `fob` in this scope
 18 |     println!("Hello {}", fob);
    |                          ^^^ did you mean `foo`?
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr
index 0efbd8472ae..f7c94ed9f73 100644
--- a/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr
+++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.stderr
@@ -19,5 +19,5 @@ error[E0597]: `c1` does not live long enough
     |
     = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/vec_refs_data_with_early_death.stderr b/src/test/ui/span/vec_refs_data_with_early_death.stderr
index 0dee15b4231..282e5caf207 100644
--- a/src/test/ui/span/vec_refs_data_with_early_death.stderr
+++ b/src/test/ui/span/vec_refs_data_with_early_death.stderr
@@ -20,5 +20,5 @@ error[E0597]: `y` does not live long enough
    |
    = note: values in a scope are dropped in the opposite order they are created
 
-error: aborting due to previous error(s)
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/wf-method-late-bound-regions.stderr b/src/test/ui/span/wf-method-late-bound-regions.stderr
index d5e663ff26d..a37b5d17aac 100644
--- a/src/test/ui/span/wf-method-late-bound-regions.stderr
+++ b/src/test/ui/span/wf-method-late-bound-regions.stderr
@@ -9,5 +9,5 @@ error[E0597]: `pointer` does not live long enough
 33 | }
    | - borrowed value needs to live until here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/static-lifetime.stderr b/src/test/ui/static-lifetime.stderr
index 89008828ac5..f73dff4f73d 100644
--- a/src/test/ui/static-lifetime.stderr
+++ b/src/test/ui/static-lifetime.stderr
@@ -6,5 +6,5 @@ error[E0477]: the type `std::borrow::Cow<'a, A>` does not fulfill the required l
    |
    = note: type must satisfy the static lifetime
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr
index b69d90cf8f7..0ca61127634 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr
@@ -6,5 +6,5 @@ error[E0599]: no method named `closure` found for type `Obj<[closure@$DIR/issue-
    |
    = help: use `(o.closure)(...)` if you meant to call the function stored in the `closure` field
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr
index 21865323908..c6f134f118d 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr
@@ -86,5 +86,5 @@ error[E0599]: no method named `f3` found for type `FuncContainer` in the current
     |
     = help: use `((*self.container).f3)(...)` if you meant to call the function stored in the `f3` field
 
-error: aborting due to previous error(s)
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr
index f1d8df81639..a45e70d48c9 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr
@@ -6,5 +6,5 @@ error[E0599]: no method named `example` found for type `Example` in the current
    |
    = help: use `(demo.example)(...)` if you meant to call the function stored in the `example` field
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr
index 7918fc1e89d..d41f7cbdf56 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr
@@ -22,5 +22,5 @@ error[E0599]: no method named `c_fn_ptr` found for type `&D` in the current scop
    |
    = help: use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr` field
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr
index 5b1c63822f9..94519266260 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr
+++ b/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr
@@ -4,5 +4,5 @@ error[E0599]: no method named `dog_age` found for type `animal::Dog` in the curr
 26 |     let dog_age = dog.dog_age();
    |                       ^^^^^^^ private field, not a method
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr
index 47a1b53cc60..8a121b14536 100644
--- a/src/test/ui/suggestions/tuple-float-index.stderr
+++ b/src/test/ui/suggestions/tuple-float-index.stderr
@@ -7,5 +7,5 @@ error: unexpected token: `1.1`
    |     |           unexpected token
    |     help: try parenthesizing the first index `((1, (2, 3)).1).1`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/token/bounds-obj-parens.stderr b/src/test/ui/token/bounds-obj-parens.stderr
index 15e4d4c72bc..4d60be15eca 100644
--- a/src/test/ui/token/bounds-obj-parens.stderr
+++ b/src/test/ui/token/bounds-obj-parens.stderr
@@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `<eof>`
 15 | FAIL
    | ^^^^ expected one of `!` or `::` here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr
index 4b0b05ca65a..48bbeac75d3 100644
--- a/src/test/ui/token/issue-10636-2.stderr
+++ b/src/test/ui/token/issue-10636-2.stderr
@@ -24,5 +24,5 @@ error: expected expression, found `)`
 
 error[E0601]: main function not found
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr
index 56f71a29953..50a38da9d8c 100644
--- a/src/test/ui/token/issue-41155.stderr
+++ b/src/test/ui/token/issue-41155.stderr
@@ -14,5 +14,5 @@ error[E0412]: cannot find type `S` in this scope
 
 error[E0601]: main function not found
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/token/macro-incomplete-parse.stderr b/src/test/ui/token/macro-incomplete-parse.stderr
index 054364b0048..6bce09af052 100644
--- a/src/test/ui/token/macro-incomplete-parse.stderr
+++ b/src/test/ui/token/macro-incomplete-parse.stderr
@@ -31,5 +31,5 @@ note: caused by the macro expansion here; the usage of `ignored_pat!` is likely
 37 |         ignored_pat!() => (), //~ NOTE caused by the macro expansion here
    |         ^^^^^^^^^^^^^^
 
-error: aborting due to previous error(s)
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/token/trailing-plus-in-bounds.stderr b/src/test/ui/token/trailing-plus-in-bounds.stderr
index 5fe0b3594f6..c765a434b8a 100644
--- a/src/test/ui/token/trailing-plus-in-bounds.stderr
+++ b/src/test/ui/token/trailing-plus-in-bounds.stderr
@@ -4,5 +4,5 @@ error: expected one of `!` or `::`, found `<eof>`
 19 | FAIL
    | ^^^^ expected one of `!` or `::` here
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr
index c5d5a4ed8a6..a7fc0808e18 100644
--- a/src/test/ui/transmute/main.stderr
+++ b/src/test/ui/transmute/main.stderr
@@ -34,5 +34,5 @@ error[E0512]: transmute called with types of different sizes
    = note: source type: i32 (32 bits)
    = note: target type: Foo (0 bits)
 
-error: aborting due to previous error(s)
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr
index 61ee5cf6128..7f1929050bb 100644
--- a/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr
+++ b/src/test/ui/transmute/transmute-from-fn-item-types-error.stderr
@@ -104,5 +104,5 @@ error[E0512]: transmute called with types of different sizes
    = note: source type: std::option::Option<fn()> (64 bits)
    = note: target type: u32 (32 bits)
 
-error: aborting due to previous error(s)
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/transmute/transmute-type-parameters.stderr b/src/test/ui/transmute/transmute-type-parameters.stderr
index bb21cfd3e4c..816c62812f3 100644
--- a/src/test/ui/transmute/transmute-type-parameters.stderr
+++ b/src/test/ui/transmute/transmute-type-parameters.stderr
@@ -52,5 +52,5 @@ error[E0512]: transmute called with types of different sizes
    = note: source type: std::option::Option<T> (size can vary because of T)
    = note: target type: i32 (32 bits)
 
-error: aborting due to previous error(s)
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/type-check/assignment-in-if.stderr b/src/test/ui/type-check/assignment-in-if.stderr
index 29439999273..a077f37eae6 100644
--- a/src/test/ui/type-check/assignment-in-if.stderr
+++ b/src/test/ui/type-check/assignment-in-if.stderr
@@ -55,5 +55,5 @@ error[E0308]: mismatched types
    = note: expected type `bool`
               found type `()`
 
-error: aborting due to previous error(s)
+error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/type-check/cannot_infer_local_or_array.stderr b/src/test/ui/type-check/cannot_infer_local_or_array.stderr
index 007480dc44f..8c52bb5a1d3 100644
--- a/src/test/ui/type-check/cannot_infer_local_or_array.stderr
+++ b/src/test/ui/type-check/cannot_infer_local_or_array.stderr
@@ -6,5 +6,5 @@ error[E0282]: type annotations needed
    |         |
    |         consider giving `x` a type
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr
index 4650df5411b..4788fad2088 100644
--- a/src/test/ui/type-check/cannot_infer_local_or_vec.stderr
+++ b/src/test/ui/type-check/cannot_infer_local_or_vec.stderr
@@ -8,5 +8,5 @@ error[E0282]: type annotations needed
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr
index 08b5ae4bbb6..ccffadebe9e 100644
--- a/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr
+++ b/src/test/ui/type-check/cannot_infer_local_or_vec_in_tuples.stderr
@@ -8,5 +8,5 @@ error[E0282]: type annotations needed
    |
    = note: this error originates in a macro outside of the current crate
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-check/issue-22897.stderr b/src/test/ui/type-check/issue-22897.stderr
index b3c736c3b68..95684118851 100644
--- a/src/test/ui/type-check/issue-22897.stderr
+++ b/src/test/ui/type-check/issue-22897.stderr
@@ -4,5 +4,5 @@ error[E0282]: type annotations needed
 14 |     [];
    |     ^^ cannot infer type for `[_; 0]`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr
index cd474b14193..bb3a371b26e 100644
--- a/src/test/ui/type-check/issue-40294.stderr
+++ b/src/test/ui/type-check/issue-40294.stderr
@@ -12,5 +12,5 @@ error[E0283]: type annotations required: cannot resolve `&'a T: Foo`
    |
    = note: required by `Foo`
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-check/unknown_type_for_closure.stderr b/src/test/ui/type-check/unknown_type_for_closure.stderr
index 200864dfbf7..afbd15ca486 100644
--- a/src/test/ui/type-check/unknown_type_for_closure.stderr
+++ b/src/test/ui/type-check/unknown_type_for_closure.stderr
@@ -4,5 +4,5 @@ error[E0282]: type annotations needed
 12 |     let x = |_| {    };
    |              ^ consider giving this closure parameter a type
 
-error: aborting due to previous error(s)
+error: aborting due to previous error
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 534ce68621ce4feec0b7e8627cfd3b077d4f390
+Subproject eb6cf012a6cc23c9c89c4009564de9fccc38b9c
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index 29ca54fda8d..0b9b9599be6 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -35,7 +35,7 @@ impl FromStr for ErrorKind {
             "ERROR" => Ok(ErrorKind::Error),
             "NOTE" => Ok(ErrorKind::Note),
             "SUGGESTION" => Ok(ErrorKind::Suggestion),
-            "WARN" => Ok(ErrorKind::Warning),
+            "WARN" |
             "WARNING" => Ok(ErrorKind::Warning),
             _ => Err(()),
         }
@@ -95,7 +95,7 @@ pub fn load_errors(testfile: &Path, cfg: Option<&str>) -> Vec<Error> {
 
     let tag = match cfg {
         Some(rev) => format!("//[{}]~", rev),
-        None => format!("//~"),
+        None => "//~".to_string(),
     };
 
     rdr.lines()
@@ -153,7 +153,7 @@ fn parse_expected(last_nonfollow_error: Option<usize>,
     let msg = msg.trim().to_owned();
 
     let (which, line_num) = if follow {
-        assert!(adjusts == 0, "use either //~| or //~^, not both.");
+        assert_eq!(adjusts, 0, "use either //~| or //~^, not both.");
         let line_num = last_nonfollow_error.expect("encountered //~| without \
                                                     preceding //~^ line.");
         (FollowPrevious(line_num), line_num)
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index aa33580b337..5ac60d8f2c8 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -258,7 +258,7 @@ impl TestProps {
             check_stdout: false,
             no_prefer_dynamic: false,
             pretty_expanded: false,
-            pretty_mode: format!("normal"),
+            pretty_mode: "normal".to_string(),
             pretty_compare_only: false,
             forbid_output: vec![],
             incremental_dir: None,
@@ -381,14 +381,11 @@ impl TestProps {
             }
         });
 
-        for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
-            match env::var(key) {
-                Ok(val) => {
-                    if self.exec_env.iter().find(|&&(ref x, _)| *x == key).is_none() {
-                        self.exec_env.push((key.to_owned(), val))
-                    }
+        for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
+            if let Ok(val) = env::var(key) {
+                if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() {
+                    self.exec_env.push(((*key).to_owned(), val))
                 }
-                Err(..) => {}
             }
         }
     }
@@ -409,7 +406,7 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) {
             return;
         } else if ln.starts_with("//[") {
             // A comment like `//[foo]` is specific to revision `foo`
-            if let Some(close_brace) = ln.find("]") {
+            if let Some(close_brace) = ln.find(']') {
                 let lncfg = &ln[3..close_brace];
                 let matches = match cfg {
                     Some(s) => s == &lncfg[..],
@@ -521,12 +518,10 @@ impl Config {
     fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option<PathBuf> {
         if let Some(s) = self.parse_name_value_directive(line, "pp-exact") {
             Some(PathBuf::from(&s))
+        } else if self.parse_name_directive(line, "pp-exact") {
+            testfile.file_name().map(PathBuf::from)
         } else {
-            if self.parse_name_directive(line, "pp-exact") {
-                testfile.file_name().map(PathBuf::from)
-            } else {
-                None
-            }
+            None
         }
     }
 
@@ -554,9 +549,7 @@ impl Config {
 pub fn lldb_version_to_int(version_string: &str) -> isize {
     let error_string = format!("Encountered LLDB version string with unexpected format: {}",
                                version_string);
-    let error_string = error_string;
-    let major: isize = version_string.parse().ok().expect(&error_string);
-    return major;
+    version_string.parse().expect(&error_string)
 }
 
 fn expand_variables(mut value: String, config: &Config) -> String {
diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs
index 06cbd9a3df4..23782c3ccc9 100644
--- a/src/tools/compiletest/src/json.rs
+++ b/src/tools/compiletest/src/json.rs
@@ -65,7 +65,7 @@ pub fn parse_output(file_name: &str, output: &str, proc_res: &ProcRes) -> Vec<Er
 fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) -> Vec<Error> {
     // The compiler sometimes intermingles non-JSON stuff into the
     // output.  This hack just skips over such lines. Yuck.
-    if line.chars().next() == Some('{') {
+    if line.starts_with('{') {
         match json::decode::<Diagnostic>(line) {
             Ok(diagnostic) => {
                 let mut expected_errors = vec![];
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index c88ffba357a..cc42544ef02 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -168,7 +168,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         src_base: opt_path(matches, "src-base"),
         build_base: opt_path(matches, "build-base"),
         stage_id: matches.opt_str("stage-id").unwrap(),
-        mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"),
+        mode: matches.opt_str("mode").unwrap().parse().expect("invalid mode"),
         run_ignored: matches.opt_present("ignored"),
         filter: matches.free.first().cloned(),
         filter_exact: matches.opt_present("exact"),
@@ -208,7 +208,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
 
 pub fn log_config(config: &Config) {
     let c = config;
-    logv(c, format!("configuration:"));
+    logv(c, "configuration:".to_string());
     logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
     logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
     logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
@@ -238,10 +238,10 @@ pub fn log_config(config: &Config) {
                     config.adb_device_status));
     logv(c, format!("verbose: {}", config.verbose));
     logv(c, format!("quiet: {}", config.quiet));
-    logv(c, format!("\n"));
+    logv(c, "\n".to_string());
 }
 
-pub fn opt_str<'a>(maybestr: &'a Option<String>) -> &'a str {
+pub fn opt_str(maybestr: &Option<String>) -> &str {
     match *maybestr {
         None => "(none)",
         Some(ref s) => s,
@@ -465,17 +465,16 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
     };
 
     // Debugging emscripten code doesn't make sense today
-    let mut ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props);
-    if (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) &&
-        config.target.contains("emscripten") {
-        ignore = true;
-    }
+    let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props) ||
+                 (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb) &&
+                  config.target.contains("emscripten");
 
     test::TestDescAndFn {
         desc: test::TestDesc {
             name: make_test_name(config, testpaths),
             ignore: ignore,
             should_panic: should_panic,
+            allow_fail: false,
         },
         testfn: make_test_closure(config, testpaths),
     }
@@ -487,7 +486,7 @@ fn stamp(config: &Config, testpaths: &TestPaths) -> PathBuf {
                                            .to_str().unwrap(),
                              config.stage_id);
     config.build_base.canonicalize()
-          .unwrap_or(config.build_base.clone())
+          .unwrap_or_else(|_| config.build_base.clone())
           .join(stamp_name)
 }
 
@@ -512,7 +511,7 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
 fn mtime(path: &Path) -> FileTime {
     fs::metadata(path).map(|f| {
         FileTime::from_last_modification_time(&f)
-    }).unwrap_or(FileTime::zero())
+    }).unwrap_or_else(|_| FileTime::zero())
 }
 
 pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName {
@@ -560,7 +559,7 @@ fn analyze_gdb(gdb: Option<String>) -> (Option<String>, Option<u32>, bool) {
 
     let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST);
 
-    return (Some(gdb.to_owned()), version, gdb_native_rust);
+    (Some(gdb.to_owned()), version, gdb_native_rust)
 }
 
 fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
@@ -600,7 +599,8 @@ fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
             Some(idx) => if line.as_bytes()[idx] == b'.' {
                 let patch = &line[idx + 1..];
 
-                let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or(patch.len());
+                let patch_len = patch.find(|c: char| !c.is_digit(10))
+                                                       .unwrap_or_else(|| patch.len());
                 let patch = &patch[..patch_len];
                 let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) };
 
diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs
index dbda8f4d802..35f6ed243fe 100644
--- a/src/tools/compiletest/src/procsrv.rs
+++ b/src/tools/compiletest/src/procsrv.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use std::env;
-use std::ffi::OsString;
 use std::io::prelude::*;
 use std::io;
 use std::path::PathBuf;
@@ -31,7 +30,7 @@ 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()))
+    let mut path = env::split_paths(&env::var_os(var).unwrap_or_default())
         .collect::<Vec<_>>();
     if let Some(p) = aux_path {
         path.insert(0, PathBuf::from(p))
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 0692e07253f..2254d6d23a8 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -68,7 +68,7 @@ pub fn run(config: Config, testpaths: &TestPaths) {
     } else {
         for revision in &base_props.revisions {
             let mut revision_props = base_props.clone();
-            revision_props.load_from(&testpaths.file, Some(&revision), &config);
+            revision_props.load_from(&testpaths.file, Some(revision), &config);
             let rev_cx = TestCx {
                 config: &config,
                 props: &revision_props,
@@ -81,7 +81,7 @@ pub fn run(config: Config, testpaths: &TestPaths) {
 
     base_cx.complete_all();
 
-    File::create(::stamp(&config, &testpaths)).unwrap();
+    File::create(::stamp(&config, testpaths)).unwrap();
 }
 
 struct TestCx<'test> {
@@ -101,9 +101,8 @@ impl<'test> TestCx<'test> {
     /// invoked once before any revisions have been processed
     fn init_all(&self) {
         assert!(self.revision.is_none(), "init_all invoked for a revision");
-        match self.config.mode {
-            Incremental => self.init_incremental_test(),
-            _ => { }
+        if let Incremental = self.config.mode {
+            self.init_incremental_test()
         }
     }
 
@@ -111,7 +110,7 @@ impl<'test> TestCx<'test> {
     /// revisions, exactly once, with revision == None).
     fn run_revision(&self) {
         match self.config.mode {
-            CompileFail => self.run_cfail_test(),
+            CompileFail |
             ParseFail => self.run_cfail_test(),
             RunFail => self.run_rfail_test(),
             RunPass => self.run_rpass_test(),
@@ -352,10 +351,10 @@ impl<'test> TestCx<'test> {
                             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());
-        return ProcArgs {
+        ProcArgs {
             prog: self.config.rustc_path.to_str().unwrap().to_owned(),
             args: args,
-        };
+        }
     }
 
     fn compare_source(&self,
@@ -407,17 +406,17 @@ actual:\n\
                             aux_dir.to_str().unwrap().to_owned()];
         if let Some(revision) = self.revision {
             args.extend(vec![
-                format!("--cfg"),
-                format!("{}", revision),
+                "--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
-        return ProcArgs {
+        ProcArgs {
             prog: self.config.rustc_path.to_str().unwrap().to_owned(),
             args: args,
-        };
+        }
     }
 
     fn run_debuginfo_gdb_test(&self) {
@@ -692,7 +691,7 @@ actual:\n\
         }
 
         if !debugger_run_result.status.success() {
-            self.fatal("gdb failed to execute");
+            self.fatal_proc_rec("gdb failed to execute", &debugger_run_result);
         }
 
         self.check_debugger_output(&debugger_run_result, &check_lines);
@@ -708,7 +707,7 @@ actual:\n\
             }
         }
 
-        return None;
+        None
     }
 
     fn run_debuginfo_lldb_test(&self) {
@@ -875,13 +874,13 @@ actual:\n\
                     for &(ref command_directive, ref check_directive) in &directives {
                         self.config.parse_name_value_directive(
                             &line,
-                            &command_directive).map(|cmd| {
+                            command_directive).map(|cmd| {
                                 commands.push(cmd)
                             });
 
                         self.config.parse_name_value_directive(
                             &line,
-                            &check_directive).map(|cmd| {
+                            check_directive).map(|cmd| {
                                 check_lines.push(cmd)
                             });
                     }
@@ -962,8 +961,7 @@ actual:\n\
                 (line, 0)
             };
 
-            for fragment_index in first_fragment .. check_fragments.len() {
-                let current_fragment = check_fragments[fragment_index];
+            for current_fragment in &check_fragments[first_fragment..] {
                 match rest.find(current_fragment) {
                     Some(pos) => {
                         rest = &rest[pos + current_fragment.len() .. ];
@@ -976,7 +974,7 @@ actual:\n\
                 return false;
             }
 
-            return true;
+            true
         }
     }
 
@@ -1059,7 +1057,7 @@ actual:\n\
         let expect_note = expected_errors.iter().any(|ee| ee.kind == Some(ErrorKind::Note));
 
         // Parse the JSON output from the compiler and extract out the messages.
-        let actual_errors = json::parse_output(&file_name, &proc_res.stderr, &proc_res);
+        let actual_errors = json::parse_output(&file_name, &proc_res.stderr, proc_res);
         let mut unexpected = Vec::new();
         let mut found = vec![false; expected_errors.len()];
         for actual_error in &actual_errors {
@@ -1092,7 +1090,7 @@ actual:\n\
                                      .map_or(String::from("message"),
                                              |k| k.to_string()),
                                      actual_error.msg));
-                        unexpected.push(actual_error.clone());
+                        unexpected.push(actual_error);
                     }
                 }
             }
@@ -1110,20 +1108,20 @@ actual:\n\
                              .map_or("message".into(),
                                      |k| k.to_string()),
                              expected_error.msg));
-                not_found.push(expected_error.clone());
+                not_found.push(expected_error);
             }
         }
 
-        if unexpected.len() > 0 || not_found.len() > 0 {
+        if !unexpected.is_empty() || !not_found.is_empty() {
             self.error(
                 &format!("{} unexpected errors found, {} expected errors not found",
                          unexpected.len(), not_found.len()));
-            print!("status: {}\ncommand: {}\n",
+            println!("status: {}\ncommand: {}",
                    proc_res.status, proc_res.cmdline);
-            if unexpected.len() > 0 {
+            if !unexpected.is_empty() {
                 println!("unexpected errors (from JSON output): {:#?}\n", unexpected);
             }
-            if not_found.len() > 0 {
+            if !not_found.is_empty() {
                 println!("not found errors (from test file): {:#?}\n", not_found);
             }
             panic!();
@@ -1142,9 +1140,9 @@ actual:\n\
         match actual_error.kind {
             Some(ErrorKind::Help) => expect_help,
             Some(ErrorKind::Note) => expect_note,
-            Some(ErrorKind::Error) => true,
+            Some(ErrorKind::Error) |
             Some(ErrorKind::Warning) => true,
-            Some(ErrorKind::Suggestion) => false,
+            Some(ErrorKind::Suggestion) |
             None => false
         }
     }
@@ -1287,7 +1285,8 @@ actual:\n\
                                                      self.config);
             let mut crate_type = if aux_props.no_prefer_dynamic {
                 Vec::new()
-            } else {
+            } 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
                 // to avoid code size bloat and large binaries as much as possible
                 // for the test suite (otherwise including libstd statically in all
@@ -1297,13 +1296,9 @@ 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.
-                if (self.config.target.contains("musl") && !aux_props.force_host) ||
-                    self.config.target.contains("emscripten")
-                {
-                    vec!["--crate-type=lib".to_owned()]
-                } else {
-                    vec!["--crate-type=dylib".to_owned()]
-                }
+                vec!["--crate-type=lib".to_owned()]
+            } else {
+                vec!["--crate-type=dylib".to_owned()]
             };
             crate_type.extend(extra_link_args.clone());
             let aux_output = {
@@ -1344,7 +1339,7 @@ actual:\n\
                        lib_path: &str,
                        aux_path: Option<&str>,
                        input: Option<String>) -> ProcRes {
-        return self.program_output(lib_path, prog, aux_path, args, procenv, input);
+        self.program_output(lib_path, prog, aux_path, args, procenv, input)
     }
 
     fn make_compile_args(&self,
@@ -1367,7 +1362,7 @@ actual:\n\
         // Optionally prevent default --target if specified in test compile-flags.
         let custom_target = self.props.compile_flags
             .iter()
-            .fold(false, |acc, ref x| acc || x.starts_with("--target"));
+            .fold(false, |acc, x| acc || x.starts_with("--target"));
 
         if !custom_target {
             args.extend(vec![
@@ -1377,14 +1372,14 @@ actual:\n\
 
         if let Some(revision) = self.revision {
             args.extend(vec![
-                format!("--cfg"),
-                format!("{}", revision),
+                "--cfg".to_string(),
+                revision.to_string(),
             ]);
         }
 
         if let Some(ref incremental_dir) = self.props.incremental_dir {
             args.extend(vec![
-                format!("-Z"),
+                "-Z".to_string(),
                 format!("incremental={}", incremental_dir.display()),
             ]);
         }
@@ -1457,10 +1452,10 @@ actual:\n\
             args.extend(self.split_maybe_args(&self.config.target_rustcflags));
         }
         args.extend(self.props.compile_flags.iter().cloned());
-        return ProcArgs {
+        ProcArgs {
             prog: self.config.rustc_path.to_str().unwrap().to_owned(),
             args: args,
-        };
+        }
     }
 
     fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
@@ -1508,10 +1503,10 @@ actual:\n\
         args.extend(self.split_maybe_args(&self.props.run_flags));
 
         let prog = args.remove(0);
-        return ProcArgs {
+         ProcArgs {
             prog: prog,
             args: args,
-        };
+        }
     }
 
     fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<String> {
@@ -1558,12 +1553,12 @@ actual:\n\
                          env,
                          input).expect(&format!("failed to exec `{}`", prog));
         self.dump_output(&out, &err);
-        return ProcRes {
+        ProcRes {
             status: status,
             stdout: out,
             stderr: err,
             cmdline: cmdline,
-        };
+        }
     }
 
     fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String {
@@ -1764,7 +1759,7 @@ actual:\n\
             self.fatal_proc_rec("rustdoc failed!", &proc_res);
         }
 
-        if self.props.check_test_line_numbers_match == true {
+        if self.props.check_test_line_numbers_match {
             self.check_rustdoc_test_option(proc_res);
         } else {
             let root = self.find_rust_src_root().unwrap();
@@ -1791,7 +1786,7 @@ actual:\n\
                .filter_map(|(line_nb, line)| {
                    if (line.trim_left().starts_with("pub mod ") ||
                        line.trim_left().starts_with("mod ")) &&
-                      line.ends_with(";") {
+                      line.ends_with(';') {
                        if let Some(ref mut other_files) = other_files {
                            other_files.push(line.rsplit("mod ")
                                       .next()
@@ -1840,7 +1835,7 @@ actual:\n\
         }
 
         let mut tested = 0;
-        for _ in res.stdout.split("\n")
+        for _ in res.stdout.split('\n')
                            .filter(|s| s.starts_with("test "))
                            .inspect(|s| {
                                let tmp: Vec<&str> = s.split(" - ").collect();
@@ -1853,7 +1848,7 @@ actual:\n\
                                        iter.next();
                                        let line = iter.next()
                                                       .unwrap_or(")")
-                                                      .split(")")
+                                                      .split(')')
                                                       .next()
                                                       .unwrap_or("0")
                                                       .parse()
@@ -1873,7 +1868,7 @@ actual:\n\
             self.fatal_proc_rec(&format!("No test has been found... {:?}", files), &res);
         } else {
             for (entry, v) in &files {
-                if v.len() != 0 {
+                if !v.is_empty() {
                     self.fatal_proc_rec(&format!("Not found test at line{} \"{}\":{:?}",
                                                  if v.len() > 1 { "s" } else { "" }, entry, v),
                                         &res);
@@ -1916,11 +1911,10 @@ actual:\n\
                                                    .find(|ti| ti.name == expected_item.name);
 
             if let Some(actual_item) = actual_item_with_same_name {
-                if !expected_item.codegen_units.is_empty() {
-                    // Also check for codegen units
-                    if expected_item.codegen_units != actual_item.codegen_units {
-                        wrong_cgus.push((expected_item.clone(), actual_item.clone()));
-                    }
+                if !expected_item.codegen_units.is_empty() &&
+                   // Also check for codegen units
+                   expected_item.codegen_units != actual_item.codegen_units {
+                    wrong_cgus.push((expected_item.clone(), actual_item.clone()));
                 }
             } else {
                 missing.push(expected_item.string.clone());
@@ -2005,7 +1999,7 @@ actual:\n\
             let cgus = if parts.len() > 1 {
                 let cgus_str = parts[1];
 
-                cgus_str.split(" ")
+                cgus_str.split(' ')
                         .map(str::trim)
                         .filter(|s| !s.is_empty())
                         .map(str::to_owned)
@@ -2323,7 +2317,7 @@ actual:\n\
         }
     }
 
-    fn compare_mir_test_output(&self, test_name: &str, expected_content: &Vec<&str>) {
+    fn compare_mir_test_output(&self, test_name: &str, expected_content: &[&str]) {
         let mut output_file = PathBuf::new();
         output_file.push(self.get_mir_dump_dir());
         output_file.push(test_name);
diff --git a/src/tools/rls b/src/tools/rls
-Subproject d26fd6f089a4e7f1216a03a6d604bee33b2301d
+Subproject 4c0a8b63d61942349c18727409b2a600446e02d