about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/Cargo.lock53
-rw-r--r--src/bootstrap/bootstrap.py1
-rw-r--r--src/bootstrap/build/compile.rs82
-rw-r--r--src/bootstrap/build/mod.rs75
-rw-r--r--src/bootstrap/build/native.rs8
-rw-r--r--src/bootstrap/build/step.rs71
-rw-r--r--src/bootstrap/rustc.rs6
-rw-r--r--src/compiletest/compiletest.rs97
-rw-r--r--src/compiletest/runtest.rs347
-rw-r--r--src/doc/book/concurrency.md2
-rw-r--r--src/doc/book/const-and-static.md8
-rw-r--r--src/doc/book/guessing-game.md22
-rw-r--r--src/doc/book/iterators.md10
-rw-r--r--src/doc/book/ownership.md62
-rw-r--r--src/doc/book/patterns.md2
-rw-r--r--src/doc/book/using-rust-without-the-standard-library.md2
-rw-r--r--src/doc/book/vectors.md11
-rw-r--r--src/doc/nomicon/other-reprs.md2
-rw-r--r--src/doc/reference.md22
-rw-r--r--src/error_index_generator/main.rs (renamed from src/error-index-generator/main.rs)0
-rw-r--r--src/etc/licenseck.py4
-rw-r--r--src/etc/maketest.py1
-rw-r--r--src/etc/tidy.py21
-rw-r--r--src/liballoc/Cargo.toml2
-rw-r--r--src/liballoc/lib.rs8
-rw-r--r--src/liballoc_jemalloc/lib.rs10
-rw-r--r--src/libarena/lib.rs1
-rw-r--r--src/libcollections/borrow.rs4
-rw-r--r--src/libcollections/btree/map.rs11
-rw-r--r--src/libcollections/lib.rs4
-rw-r--r--src/libcollections/linked_list.rs150
-rw-r--r--src/libcollections/slice.rs28
-rw-r--r--src/libcollections/str.rs71
-rw-r--r--src/libcollections/vec.rs61
-rw-r--r--src/libcollectionstest/lib.rs2
-rw-r--r--src/libcollectionstest/slice.rs24
-rw-r--r--src/libcollectionstest/string.rs4
-rw-r--r--src/libcollectionstest/vec.rs18
-rw-r--r--src/libcore/cell.rs11
-rw-r--r--src/libcore/fmt/mod.rs4
-rw-r--r--src/libcore/intrinsics.rs32
-rw-r--r--src/libcore/iter.rs16
-rw-r--r--src/libcore/mem.rs20
-rw-r--r--src/libcore/num/flt2dec/mod.rs4
-rw-r--r--src/libcore/num/u16.rs2
-rw-r--r--src/libcore/num/u32.rs2
-rw-r--r--src/libcore/num/u64.rs2
-rw-r--r--src/libcore/num/u8.rs2
-rw-r--r--src/libcore/num/uint_macros.rs2
-rw-r--r--src/libcore/num/usize.rs4
-rw-r--r--src/libcore/num/wrapping.rs16
-rw-r--r--src/libcore/ops.rs80
-rw-r--r--src/libcore/option.rs2
-rw-r--r--src/libcore/ptr.rs50
-rw-r--r--src/libcore/result.rs4
-rw-r--r--src/libcore/slice.rs14
-rw-r--r--src/libcore/sync/atomic.rs435
-rw-r--r--src/libcoretest/cell.rs2
-rw-r--r--src/libcoretest/lib.rs1
-rw-r--r--src/libcoretest/num/flt2dec/mod.rs4
-rw-r--r--src/libgetopts/lib.rs5
m---------src/liblibc0
-rw-r--r--src/librbml/lib.rs5
-rw-r--r--src/librustc/Cargo.toml1
-rw-r--r--src/librustc/diagnostics.rs247
-rw-r--r--src/librustc/front/check_attr.rs1
-rw-r--r--src/librustc/front/map/collector.rs2
-rw-r--r--src/librustc/front/map/mod.rs14
-rw-r--r--src/librustc/lib.rs8
-rw-r--r--src/librustc/lint/builtin.rs9
-rw-r--r--src/librustc/lint/context.rs10
-rw-r--r--src/librustc/lint/mod.rs12
-rw-r--r--src/librustc/middle/cfg/construct.rs29
-rw-r--r--src/librustc/middle/check_match.rs157
-rw-r--r--src/librustc/middle/const_eval.rs20
-rw-r--r--src/librustc/middle/cstore.rs37
-rw-r--r--src/librustc/middle/dataflow.rs4
-rw-r--r--src/librustc/middle/dead.rs6
-rw-r--r--src/librustc/middle/expr_use_visitor.rs29
-rw-r--r--src/librustc/middle/lang_items.rs7
-rw-r--r--src/librustc/middle/mem_categorization.rs37
-rw-r--r--src/librustc/middle/pat_util.rs45
-rw-r--r--src/librustc/middle/region.rs16
-rw-r--r--src/librustc/middle/stability.rs8
-rw-r--r--src/librustc/middle/subst.rs5
-rw-r--r--src/librustc/middle/traits/fulfill.rs43
-rw-r--r--src/librustc/middle/ty/adjustment.rs31
-rw-r--r--src/librustc/middle/ty/context.rs27
-rw-r--r--src/librustc/middle/ty/mod.rs8
-rw-r--r--src/librustc/mir/mir_map.rs14
-rw-r--r--src/librustc/mir/repr.rs19
-rw-r--r--src/librustc/mir/tcx.rs88
-rw-r--r--src/librustc/mir/transform.rs4
-rw-r--r--src/librustc/session/config.rs207
-rw-r--r--src/librustc/util/ppaux.rs3
-rw-r--r--src/librustc_back/lib.rs1
-rw-r--r--src/librustc_back/sha2.rs6
-rw-r--r--src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs2
-rw-r--r--src/librustc_back/target/freebsd_base.rs13
-rw-r--r--src/librustc_back/target/mod.rs3
-rw-r--r--src/librustc_back/target/x86_64_sun_solaris.rs1
-rw-r--r--src/librustc_back/target/x86_64_unknown_openbsd.rs1
-rw-r--r--src/librustc_bitflags/Cargo.toml3
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs4
-rw-r--r--src/librustc_borrowck/diagnostics.rs20
-rw-r--r--src/librustc_data_structures/bitvec.rs79
-rw-r--r--src/librustc_data_structures/graph/mod.rs20
-rw-r--r--src/librustc_data_structures/snapshot_vec.rs4
-rw-r--r--src/librustc_driver/driver.rs20
-rw-r--r--src/librustc_driver/lib.rs150
-rw-r--r--src/librustc_driver/pretty.rs25
-rw-r--r--src/librustc_front/Cargo.toml1
-rw-r--r--src/librustc_front/fold.rs37
-rw-r--r--src/librustc_front/hir.rs55
-rw-r--r--src/librustc_front/intravisit.rs25
-rw-r--r--src/librustc_front/lowering.rs36
-rw-r--r--src/librustc_front/print/pprust.rs41
-rw-r--r--src/librustc_front/util.rs23
-rw-r--r--src/librustc_lint/bad_style.rs6
-rw-r--r--src/librustc_lint/builtin.rs6
-rw-r--r--src/librustc_lint/lib.rs4
-rw-r--r--src/librustc_llvm/Cargo.toml3
-rw-r--r--src/librustc_llvm/build.rs46
-rw-r--r--src/librustc_llvm/lib.rs7
-rw-r--r--src/librustc_metadata/Cargo.toml1
-rw-r--r--src/librustc_metadata/astencode.rs16
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_mir/build/expr/as_lvalue.rs2
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs35
-rw-r--r--src/librustc_mir/build/matches/test.rs3
-rw-r--r--src/librustc_mir/build/matches/util.rs3
-rw-r--r--src/librustc_mir/build/mod.rs5
-rw-r--r--src/librustc_mir/build/scope.rs40
-rw-r--r--src/librustc_mir/hair/cx/expr.rs120
-rw-r--r--src/librustc_mir/hair/cx/pattern.rs45
-rw-r--r--src/librustc_mir/hair/mod.rs8
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_mir/mir_map.rs11
-rw-r--r--src/librustc_mir/transform/clear_dead_blocks.rs81
-rw-r--r--src/librustc_mir/transform/erase_regions.rs13
-rw-r--r--src/librustc_mir/transform/mod.rs4
-rw-r--r--src/librustc_mir/transform/no_landing_pads.rs50
-rw-r--r--src/librustc_mir/transform/simplify_cfg.rs48
-rw-r--r--src/librustc_mir/transform/type_check.rs598
-rw-r--r--src/librustc_mir/transform/util.rs51
-rw-r--r--src/librustc_passes/consts.rs9
-rw-r--r--src/librustc_plugin/Cargo.toml1
-rw-r--r--src/librustc_privacy/diagnostics.rs14
-rw-r--r--src/librustc_privacy/lib.rs171
-rw-r--r--src/librustc_resolve/Cargo.toml1
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs19
-rw-r--r--src/librustc_resolve/diagnostics.rs94
-rw-r--r--src/librustc_resolve/lib.rs411
-rw-r--r--src/librustc_resolve/resolve_imports.rs103
-rw-r--r--src/librustc_trans/back/link.rs10
-rw-r--r--src/librustc_trans/lib.rs2
-rw-r--r--src/librustc_trans/trans/_match.rs72
-rw-r--r--src/librustc_trans/trans/base.rs20
-rw-r--r--src/librustc_trans/trans/build.rs5
-rw-r--r--src/librustc_trans/trans/builder.rs5
-rw-r--r--src/librustc_trans/trans/common.rs9
-rw-r--r--src/librustc_trans/trans/consts.rs18
-rw-r--r--src/librustc_trans/trans/debuginfo/create_scope_map.rs22
-rw-r--r--src/librustc_trans/trans/debuginfo/metadata.rs4
-rw-r--r--src/librustc_trans/trans/expr.rs7
-rw-r--r--src/librustc_trans/trans/foreign.rs14
-rw-r--r--src/librustc_trans/trans/intrinsic.rs65
-rw-r--r--src/librustc_trans/trans/mir/block.rs171
-rw-r--r--src/librustc_trans/trans/mir/lvalue.rs2
-rw-r--r--src/librustc_trans/trans/mir/operand.rs98
-rw-r--r--src/librustc_trans/trans/type_of.rs10
-rw-r--r--src/librustc_typeck/check/_match.rs43
-rw-r--r--src/librustc_typeck/check/coercion.rs4
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/check/method/suggest.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs38
-rw-r--r--src/librustc_typeck/check/regionck.rs6
-rw-r--r--src/librustc_typeck/check/writeback.rs40
-rw-r--r--src/librustc_typeck/collect.rs6
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/librustc_typeck/variance.rs1250
-rw-r--r--src/librustc_typeck/variance/README.md302
-rw-r--r--src/librustc_typeck/variance/constraints.rs553
-rw-r--r--src/librustc_typeck/variance/mod.rs37
-rw-r--r--src/librustc_typeck/variance/solve.rs167
-rw-r--r--src/librustc_typeck/variance/terms.rs287
-rw-r--r--src/librustc_typeck/variance/xform.rs61
-rw-r--r--src/librustc_unicode/char.rs18
-rw-r--r--src/librustc_unicode/u_str.rs6
-rw-r--r--src/librustdoc/clean/inline.rs27
-rw-r--r--src/librustdoc/clean/mod.rs33
-rw-r--r--src/librustdoc/html/layout.rs2
-rw-r--r--src/librustdoc/html/markdown.rs4
-rw-r--r--src/librustdoc/html/render.rs259
-rw-r--r--src/librustdoc/html/static/main.js19
-rw-r--r--src/librustdoc/html/static/styles/main.css2
-rw-r--r--src/librustdoc/lib.rs5
-rw-r--r--src/libserialize/json.rs8
-rw-r--r--src/libstd/Cargo.toml1
-rw-r--r--src/libstd/collections/hash/map.rs11
-rw-r--r--src/libstd/collections/hash/table.rs5
-rw-r--r--src/libstd/collections/mod.rs9
-rw-r--r--src/libstd/env.rs17
-rw-r--r--src/libstd/ffi/c_str.rs78
-rw-r--r--src/libstd/ffi/os_str.rs216
-rw-r--r--src/libstd/io/cursor.rs2
-rw-r--r--src/libstd/io/impls.rs6
-rw-r--r--src/libstd/io/mod.rs15
-rw-r--r--src/libstd/lib.rs9
-rw-r--r--src/libstd/net/addr.rs9
-rw-r--r--src/libstd/net/ip.rs4
-rw-r--r--src/libstd/net/parser.rs9
-rw-r--r--src/libstd/os/dragonfly/raw.rs17
-rw-r--r--src/libstd/os/freebsd/raw.rs177
-rw-r--r--src/libstd/os/netbsd/fs.rs13
-rw-r--r--src/libstd/os/netbsd/raw.rs4
-rw-r--r--src/libstd/os/solaris/fs.rs2
-rw-r--r--src/libstd/panic.rs6
-rw-r--r--src/libstd/path.rs114
-rw-r--r--src/libstd/primitive_docs.rs83
-rw-r--r--src/libstd/rand/mod.rs95
-rw-r--r--src/libstd/sync/condvar.rs3
-rw-r--r--src/libstd/sync/mpsc/mod.rs8
-rw-r--r--src/libstd/sync/rwlock.rs8
-rw-r--r--src/libstd/sys/common/net.rs10
-rw-r--r--src/libstd/sys/common/poison.rs2
-rw-r--r--src/libstd/sys/common/unwind/gcc.rs1
-rw-r--r--src/libstd/sys/common/unwind/mod.rs17
-rw-r--r--src/libstd/sys/common/unwind/seh.rs29
-rw-r--r--src/libstd/sys/common/unwind/seh64_gnu.rs1
-rw-r--r--src/libstd/sys/common/wtf8.rs16
-rw-r--r--src/libstd/sys/unix/fs.rs56
-rw-r--r--src/libstd/sys/unix/mod.rs1
-rw-r--r--src/libstd/sys/unix/net.rs2
-rw-r--r--src/libstd/sys/unix/os_str.rs41
-rw-r--r--src/libstd/sys/unix/rand.rs (renamed from src/libstd/rand/os.rs)166
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs32
-rw-r--r--src/libstd/sys/windows/backtrace.rs8
-rw-r--r--src/libstd/sys/windows/c.rs228
-rw-r--r--src/libstd/sys/windows/compat.rs2
-rw-r--r--src/libstd/sys/windows/fs.rs54
-rw-r--r--src/libstd/sys/windows/handle.rs16
-rw-r--r--src/libstd/sys/windows/mod.rs1
-rw-r--r--src/libstd/sys/windows/net.rs5
-rw-r--r--src/libstd/sys/windows/os_str.rs35
-rw-r--r--src/libstd/sys/windows/printing/msvc.rs8
-rw-r--r--src/libstd/sys/windows/rand.rs76
-rw-r--r--src/libstd/sys/windows/stdio.rs2
-rw-r--r--src/libstd/sys/windows/thread_local.rs9
-rw-r--r--src/libstd/thread/mod.rs1
-rw-r--r--src/libstd/thread/scoped_tls.rs9
-rw-r--r--src/libstd/time/mod.rs82
-rw-r--r--src/libsyntax/Cargo.toml3
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ext/base.rs7
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs22
-rw-r--r--src/libsyntax/feature_gate.rs15
-rw-r--r--src/libsyntax/parse/attr.rs4
-rw-r--r--src/libsyntax/parse/common.rs20
-rw-r--r--src/libsyntax/parse/parser.rs77
-rw-r--r--src/libsyntax_ext/deriving/clone.rs50
-rw-r--r--src/libsyntax_ext/deriving/debug.rs10
-rw-r--r--src/libsyntax_ext/deriving/encodable.rs2
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs21
-rw-r--r--src/libsyntax_ext/deriving/hash.rs2
-rw-r--r--src/libterm/Cargo.toml3
-rw-r--r--src/libterm/lib.rs4
-rw-r--r--src/libterm/terminfo/mod.rs4
-rw-r--r--src/libtest/lib.rs8
m---------src/llvm0
-rw-r--r--src/nightlies.txt2
-rw-r--r--src/rustc/Cargo.lock16
-rw-r--r--src/rustc/std_shim/Cargo.lock10
-rw-r--r--src/rustllvm/RustWrapper.cpp14
-rw-r--r--src/rustllvm/llvm-auto-clean-trigger2
-rw-r--r--src/snapshots.txt9
-rw-r--r--src/test/auxiliary/augmented_assignments.rs6
-rw-r--r--src/test/auxiliary/custom_derive_plugin_attr.rs2
-rw-r--r--src/test/auxiliary/dummy_mir_pass.rs7
-rw-r--r--src/test/auxiliary/empty-struct.rs2
-rw-r--r--src/test/auxiliary/issue-21221-3.rs29
-rw-r--r--src/test/auxiliary/issue-21221-4.rs22
-rw-r--r--src/test/auxiliary/issue-29584.rs18
-rw-r--r--src/test/auxiliary/issue-31702-1.rs26
-rw-r--r--src/test/auxiliary/issue-31702-2.rs30
-rw-r--r--src/test/auxiliary/privacy_reexport.rs1
-rw-r--r--src/test/auxiliary/reachable-unnameable-items.rs116
-rw-r--r--src/test/auxiliary/thread-local-extern-static.rs17
-rw-r--r--src/test/compile-fail/associated-types-eq-1.rs2
-rw-r--r--src/test/compile-fail/augmented-assignments.rs2
-rw-r--r--src/test/compile-fail/bad-type-env-capture.rs2
-rw-r--r--src/test/compile-fail/borrowck/borrowck-and-init.rs (renamed from src/test/compile-fail/borrowck-and-init.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-anon-fields-struct.rs (renamed from src/test/compile-fail/borrowck-anon-fields-struct.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-anon-fields-tuple.rs (renamed from src/test/compile-fail/borrowck-anon-fields-tuple.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-anon-fields-variant.rs (renamed from src/test/compile-fail/borrowck-anon-fields-variant.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-argument.rs (renamed from src/test/compile-fail/borrowck-argument.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-comp-idx.rs (renamed from src/test/compile-fail/borrowck-assign-comp-idx.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-comp.rs (renamed from src/test/compile-fail/borrowck-assign-comp.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs (renamed from src/test/compile-fail/borrowck-assign-to-andmut-in-aliasable-loc.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs (renamed from src/test/compile-fail/borrowck-assign-to-andmut-in-borrowed-loc.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs (renamed from src/test/compile-fail/borrowck-assign-to-constants.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-auto-mut-ref-to-immut-var.rs (renamed from src/test/compile-fail/borrowck-auto-mut-ref-to-immut-var.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-autoref-3261.rs (renamed from src/test/compile-fail/borrowck-autoref-3261.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-bad-nested-calls-free.rs (renamed from src/test/compile-fail/borrowck-bad-nested-calls-free.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-bad-nested-calls-move.rs (renamed from src/test/compile-fail/borrowck-bad-nested-calls-move.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-block-unint.rs (renamed from src/test/compile-fail/borrowck-block-unint.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-from-owned-ptr.rs (renamed from src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-from-stack-variable.rs (renamed from src/test/compile-fail/borrowck-borrow-from-stack-variable.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs (renamed from src/test/compile-fail/borrowck-borrow-from-temporary.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs (renamed from src/test/compile-fail/borrowck-borrow-immut-deref-of-box-as-mut.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs (renamed from src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-mut-object-twice.rs (renamed from src/test/compile-fail/borrowck-borrow-mut-object-twice.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref-mut.rs (renamed from src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref.rs (renamed from src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-overloaded-deref-mut.rs (renamed from src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrow-overloaded-deref.rs (renamed from src/test/compile-fail/borrowck-borrow-overloaded-deref.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue-2.rs (renamed from src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue.rs (renamed from src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-box-insensitivity.rs (renamed from src/test/compile-fail/borrowck-box-insensitivity.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-break-uninit-2.rs (renamed from src/test/compile-fail/borrowck-break-uninit-2.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-break-uninit.rs (renamed from src/test/compile-fail/borrowck-break-uninit.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs (renamed from src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-call-method-from-mut-aliasable.rs (renamed from src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs (renamed from src/test/compile-fail/borrowck-closures-mut-and-imm.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-mut-of-imm.rs (renamed from src/test/compile-fail/borrowck-closures-mut-of-imm.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-two-mut.rs (renamed from src/test/compile-fail/borrowck-closures-two-mut.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-unique-imm.rs (renamed from src/test/compile-fail/borrowck-closures-unique-imm.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-unique.rs (renamed from src/test/compile-fail/borrowck-closures-unique.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-use-after-free.rs (renamed from src/test/compile-fail/borrowck-closures-use-after-free.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-consume-unsize-vec.rs (renamed from src/test/compile-fail/borrowck-consume-unsize-vec.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-consume-upcast-box.rs (renamed from src/test/compile-fail/borrowck-consume-upcast-box.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-escaping-closure-error-1.rs (renamed from src/test/compile-fail/borrowck-escaping-closure-error-1.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-escaping-closure-error-2.rs (renamed from src/test/compile-fail/borrowck-escaping-closure-error-2.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-field-sensitivity.rs (renamed from src/test/compile-fail/borrowck-field-sensitivity.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-fn-in-const-a.rs (renamed from src/test/compile-fail/borrowck-fn-in-const-a.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-fn-in-const-b.rs (renamed from src/test/compile-fail/borrowck-fn-in-const-b.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-fn-in-const-c.rs (renamed from src/test/compile-fail/borrowck-fn-in-const-c.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs (renamed from src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-for-loop-head-linkage.rs (renamed from src/test/compile-fail/borrowck-for-loop-head-linkage.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-if-no-else.rs (renamed from src/test/compile-fail/borrowck-if-no-else.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-if-with-else.rs (renamed from src/test/compile-fail/borrowck-if-with-else.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs (renamed from src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-in-static.rs (renamed from src/test/compile-fail/borrowck-in-static.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-init-in-called-fn-expr.rs (renamed from src/test/compile-fail/borrowck-init-in-called-fn-expr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-init-in-fn-expr.rs (renamed from src/test/compile-fail/borrowck-init-in-fn-expr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-init-in-fru.rs (renamed from src/test/compile-fail/borrowck-init-in-fru.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-init-op-equal.rs (renamed from src/test/compile-fail/borrowck-init-op-equal.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-init-plus-equal.rs (renamed from src/test/compile-fail/borrowck-init-plus-equal.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-insert-during-each.rs (renamed from src/test/compile-fail/borrowck-insert-during-each.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-issue-14498.rs (renamed from src/test/compile-fail/borrowck-issue-14498.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-issue-2657-1.rs (renamed from src/test/compile-fail/borrowck-issue-2657-1.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-issue-2657-2.rs (renamed from src/test/compile-fail/borrowck-issue-2657-2.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-lend-flow-if.rs (renamed from src/test/compile-fail/borrowck-lend-flow-if.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-lend-flow-loop.rs (renamed from src/test/compile-fail/borrowck-lend-flow-loop.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs (renamed from src/test/compile-fail/borrowck-lend-flow-match.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-lend-flow.rs (renamed from src/test/compile-fail/borrowck-lend-flow.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs (renamed from src/test/compile-fail/borrowck-let-suggestion-suffixes.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-let-suggestion.rs (renamed from src/test/compile-fail/borrowck-let-suggestion.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-blocks-move-cc.rs (renamed from src/test/compile-fail/borrowck-loan-blocks-move-cc.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-blocks-move.rs (renamed from src/test/compile-fail/borrowck-loan-blocks-move.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-blocks-mut-uniq.rs (renamed from src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-in-overloaded-op.rs (renamed from src/test/compile-fail/borrowck-loan-in-overloaded-op.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-of-static-data-issue-27616.rs (renamed from src/test/compile-fail/borrowck-loan-of-static-data-issue-27616.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-rcvr-overloaded-op.rs (renamed from src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-rcvr.rs (renamed from src/test/compile-fail/borrowck-loan-rcvr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-loan-vec-content.rs (renamed from src/test/compile-fail/borrowck-loan-vec-content.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs (renamed from src/test/compile-fail/borrowck-match-binding-is-assignment.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-by-capture.rs (renamed from src/test/compile-fail/borrowck-move-by-capture.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-error-with-note.rs (renamed from src/test/compile-fail/borrowck-move-error-with-note.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs (renamed from src/test/compile-fail/borrowck-move-from-subpath-of-borrowed-path.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs (renamed from src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-in-irrefut-pat.rs (renamed from src/test/compile-fail/borrowck-move-in-irrefut-pat.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs (renamed from src/test/compile-fail/borrowck-move-moved-value-into-closure.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-mut-base-ptr.rs (renamed from src/test/compile-fail/borrowck-move-mut-base-ptr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs (renamed from src/test/compile-fail/borrowck-move-out-of-overloaded-auto-deref.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-deref.rs (renamed from src/test/compile-fail/borrowck-move-out-of-overloaded-deref.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-out-of-static-item.rs (renamed from src/test/compile-fail/borrowck-move-out-of-static-item.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-out-of-struct-with-dtor.rs (renamed from src/test/compile-fail/borrowck-move-out-of-struct-with-dtor.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs (renamed from src/test/compile-fail/borrowck-move-out-of-tuple-struct-with-dtor.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-out-of-vec-tail.rs (renamed from src/test/compile-fail/borrowck-move-out-of-vec-tail.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-move-subcomponent.rs (renamed from src/test/compile-fail/borrowck-move-subcomponent.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-multiple-captures.rs (renamed from src/test/compile-fail/borrowck-multiple-captures.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-mut-addr-of-imm-var.rs (renamed from src/test/compile-fail/borrowck-mut-addr-of-imm-var.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs (renamed from src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs (renamed from src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-mut-slice-of-imm-vec.rs (renamed from src/test/compile-fail/borrowck-mut-slice-of-imm-vec.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-mutate-in-guard.rs (renamed from src/test/compile-fail/borrowck-mutate-in-guard.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-no-cycle-in-exchange-heap.rs (renamed from src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-object-lifetime.rs (renamed from src/test/compile-fail/borrowck-object-lifetime.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-object-mutability.rs (renamed from src/test/compile-fail/borrowck-object-mutability.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-or-init.rs (renamed from src/test/compile-fail/borrowck-or-init.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-overloaded-call.rs (renamed from src/test/compile-fail/borrowck-overloaded-call.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs (renamed from src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-overloaded-index-autoderef.rs (renamed from src/test/compile-fail/borrowck-overloaded-index-autoderef.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-overloaded-index-move-from-vec.rs (renamed from src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-overloaded-index-move-index.rs (renamed from src/test/compile-fail/borrowck-overloaded-index-move-index.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs (renamed from src/test/compile-fail/borrowck-overloaded-index-ref-index.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-partial-reinit-1.rs (renamed from src/test/compile-fail/borrowck-partial-reinit-1.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-partial-reinit-2.rs (renamed from src/test/compile-fail/borrowck-partial-reinit-2.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-partial-reinit-3.rs (renamed from src/test/compile-fail/borrowck-partial-reinit-3.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-partial-reinit-4.rs (renamed from src/test/compile-fail/borrowck-partial-reinit-4.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs (renamed from src/test/compile-fail/borrowck-pat-reassign-binding.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-reborrow-from-mut.rs (renamed from src/test/compile-fail/borrowck-reborrow-from-mut.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs (renamed from src/test/compile-fail/borrowck-reborrow-from-shorter-lived-andmut.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-ref-into-rvalue.rs (renamed from src/test/compile-fail/borrowck-ref-into-rvalue.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-ref-mut-of-imm.rs (renamed from src/test/compile-fail/borrowck-ref-mut-of-imm.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-report-with-custom-diagnostic.rs (renamed from src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-return-variable-on-stack-via-clone.rs (renamed from src/test/compile-fail/borrowck-return-variable-on-stack-via-clone.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-return.rs (renamed from src/test/compile-fail/borrowck-return.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-struct-update-with-dtor.rs (renamed from src/test/compile-fail/borrowck-struct-update-with-dtor.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-swap-mut-base-ptr.rs (renamed from src/test/compile-fail/borrowck-swap-mut-base-ptr.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-unary-move.rs (renamed from src/test/compile-fail/borrowck-unary-move.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs (renamed from src/test/compile-fail/borrowck-unboxed-closures.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-uninit-after-item.rs (renamed from src/test/compile-fail/borrowck-uninit-after-item.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-uninit-in-assignop.rs (renamed from src/test/compile-fail/borrowck-uninit-in-assignop.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-uninit.rs (renamed from src/test/compile-fail/borrowck-uninit.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-uniq-via-lend.rs (renamed from src/test/compile-fail/borrowck-uniq-via-lend.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-use-in-index-lvalue.rs (renamed from src/test/compile-fail/borrowck-use-in-index-lvalue.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-use-mut-borrow.rs (renamed from src/test/compile-fail/borrowck-use-mut-borrow.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast-trait.rs (renamed from src/test/compile-fail/borrowck-use-uninitialized-in-cast-trait.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs (renamed from src/test/compile-fail/borrowck-use-uninitialized-in-cast.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs (renamed from src/test/compile-fail/borrowck-vec-pattern-element-loan.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-vec-pattern-loan-from-mut.rs (renamed from src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs (renamed from src/test/compile-fail/borrowck-vec-pattern-move-tail.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-vec-pattern-nesting.rs (renamed from src/test/compile-fail/borrowck-vec-pattern-nesting.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-vec-pattern-tail-element-loan.rs (renamed from src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-while-break.rs (renamed from src/test/compile-fail/borrowck-while-break.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-while-cond.rs (renamed from src/test/compile-fail/borrowck-while-cond.rs)0
-rw-r--r--src/test/compile-fail/borrowck/borrowck-while.rs (renamed from src/test/compile-fail/borrowck-while.rs)0
-rw-r--r--src/test/compile-fail/cfg-arg-invalid.rs13
-rw-r--r--src/test/compile-fail/dep-graph-struct-signature.rs14
-rw-r--r--src/test/compile-fail/duplicate_entry_error.rs22
-rw-r--r--src/test/compile-fail/empty-struct-braces-expr.rs2
-rw-r--r--src/test/compile-fail/empty-struct-braces-pat-1.rs2
-rw-r--r--src/test/compile-fail/empty-struct-braces-pat-2.rs2
-rw-r--r--src/test/compile-fail/empty-struct-braces-pat-3.rs2
-rw-r--r--src/test/compile-fail/empty-struct-unit-expr.rs2
-rw-r--r--src/test/compile-fail/empty-struct-unit-pat.rs23
-rw-r--r--src/test/compile-fail/extern-crate-visibility.rs34
-rw-r--r--src/test/compile-fail/extern-with-type-bounds.rs2
-rw-r--r--src/test/compile-fail/glob-resolve1.rs6
-rw-r--r--src/test/compile-fail/import-shadow-6.rs4
-rw-r--r--src/test/compile-fail/import.rs7
-rw-r--r--src/test/compile-fail/inner-static-type-parameter.rs2
-rw-r--r--src/test/compile-fail/issue-18058.rs2
-rw-r--r--src/test/compile-fail/issue-18119.rs6
-rw-r--r--src/test/compile-fail/issue-19883.rs2
-rw-r--r--src/test/compile-fail/issue-21221-1.rs94
-rw-r--r--src/test/compile-fail/issue-21221-2.rs30
-rw-r--r--src/test/compile-fail/issue-21221-3.rs30
-rw-r--r--src/test/compile-fail/issue-21221-4.rs26
-rw-r--r--src/test/compile-fail/issue-22037.rs2
-rw-r--r--src/test/compile-fail/issue-22384.rs2
-rw-r--r--src/test/compile-fail/issue-27831.rs6
-rw-r--r--src/test/compile-fail/issue-3021-c.rs4
-rw-r--r--src/test/compile-fail/issue-31769.rs14
-rw-r--r--src/test/compile-fail/issue-31845.rs22
-rw-r--r--src/test/compile-fail/issue-3214.rs2
-rw-r--r--src/test/compile-fail/issue-4366-2.rs2
-rw-r--r--src/test/compile-fail/issue-5997-enum.rs2
-rw-r--r--src/test/compile-fail/issue-5997-struct.rs2
-rw-r--r--src/test/compile-fail/issue-7607-1.rs2
-rw-r--r--src/test/compile-fail/issue-8767.rs2
-rw-r--r--src/test/compile-fail/lint-unused-imports.rs7
-rw-r--r--src/test/compile-fail/macro_undefined.rs25
-rw-r--r--src/test/compile-fail/mir-unpretty.rs (renamed from src/test/compile-fail/warn-pub-extern-crate.rs)9
-rw-r--r--src/test/compile-fail/no-implicit-prelude-nested.rs30
-rw-r--r--src/test/compile-fail/no-implicit-prelude.rs10
-rw-r--r--src/test/compile-fail/no-method-suggested-traits.rs16
-rw-r--r--src/test/compile-fail/non-inline-mod-restriction.rs (renamed from src/test/compile-fail/no-extern-crate-in-glob-import.rs)13
-rw-r--r--src/test/compile-fail/privacy-ns1.rs4
-rw-r--r--src/test/compile-fail/privacy5.rs36
-rw-r--r--src/test/compile-fail/private-variant-and-crate-reexport.rs (renamed from src/test/compile-fail/private-variant-reexport.rs)4
-rw-r--r--src/test/compile-fail/resolve-type-param-in-item-in-trait.rs8
-rw-r--r--src/test/compile-fail/resolve-unknown-trait.rs6
-rw-r--r--src/test/compile-fail/trait-impl-for-module.rs2
-rw-r--r--src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs2
-rw-r--r--src/test/run-fail/mir_drop_panics.rs1
-rw-r--r--src/test/run-fail/mir_trans_calls_converging_drops.rs1
-rw-r--r--src/test/run-fail/mir_trans_calls_converging_drops_2.rs1
-rw-r--r--src/test/run-fail/mir_trans_calls_diverging_drops.rs1
-rw-r--r--src/test/run-make/llvm-module-pass/Makefile14
-rw-r--r--src/test/run-make/llvm-pass/Makefile17
-rw-r--r--src/test/run-make/llvm-pass/llvm-function-pass.so.cc56
-rw-r--r--src/test/run-make/llvm-pass/llvm-module-pass.so.cc (renamed from src/test/run-make/llvm-module-pass/llvm-pass.so.cc)2
-rw-r--r--src/test/run-make/llvm-pass/main.rs (renamed from src/test/run-make/llvm-module-pass/main.rs)0
-rw-r--r--src/test/run-make/llvm-pass/plugin.rs (renamed from src/test/run-make/llvm-module-pass/plugin.rs)6
-rw-r--r--src/test/run-make/volatile-intrinsics/main.rs8
-rw-r--r--src/test/run-pass-valgrind/cast-enum-with-dtor.rs2
-rw-r--r--src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs1
-rw-r--r--src/test/run-pass-valgrind/cleanup-stdin.rs2
-rw-r--r--src/test/run-pass-valgrind/down-with-thread-dtors.rs2
-rw-r--r--src/test/run-pass-valgrind/dst-dtor-1.rs2
-rw-r--r--src/test/run-pass-valgrind/dst-dtor-2.rs2
-rw-r--r--src/test/run-pass-valgrind/exit-flushes.rs1
-rw-r--r--src/test/run-pass-valgrind/osx-frameworks.rs1
-rw-r--r--src/test/run-pass/atomic-compare_exchange.rs37
-rw-r--r--src/test/run-pass/augmented-assignments-feature-gate-cross.rs (renamed from src/test/compile-fail/augmented-assignments-feature-gate-cross.rs)5
-rw-r--r--src/test/run-pass/augmented-assignments-feature-gate.rs (renamed from src/test/compile-fail/augmented-assignments-feature-gate.rs)3
-rw-r--r--src/test/run-pass/augmented-assignments-trait.rs (renamed from src/test/compile-fail/augmented-assignments-trait.rs)3
-rw-r--r--src/test/run-pass/augmented-assignments.rs3
-rw-r--r--src/test/run-pass/borrowck/borrowck-assign-to-subfield.rs (renamed from src/test/run-pass/borrowck-assign-to-subfield.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-binding-mutbl.rs (renamed from src/test/run-pass/borrowck-binding-mutbl.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-borrow-from-expr-block.rs (renamed from src/test/run-pass/borrowck-borrow-from-expr-block.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs (renamed from src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-closures-two-imm.rs (renamed from src/test/run-pass/borrowck-closures-two-imm.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-field-sensitivity.rs (renamed from src/test/run-pass/borrowck-field-sensitivity.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-fixed-length-vecs.rs (renamed from src/test/run-pass/borrowck-fixed-length-vecs.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-freeze-frozen-mut.rs (renamed from src/test/run-pass/borrowck-freeze-frozen-mut.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-lend-args.rs (renamed from src/test/run-pass/borrowck-lend-args.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-macro-interaction-issue-6304.rs (renamed from src/test/run-pass/borrowck-macro-interaction-issue-6304.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs (renamed from src/test/run-pass/borrowck-move-by-capture-ok.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-mut-uniq.rs (renamed from src/test/run-pass/borrowck-mut-uniq.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-mut-vec-as-imm-slice.rs (renamed from src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-pat-enum.rs (renamed from src/test/run-pass/borrowck-pat-enum.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-pat-reassign-no-binding.rs (renamed from src/test/run-pass/borrowck-pat-reassign-no-binding.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-rvalues-mutable.rs (renamed from src/test/run-pass/borrowck-rvalues-mutable.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-scope-of-deref-issue-4666.rs (renamed from src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-static-item-in-fn.rs (renamed from src/test/run-pass/borrowck-static-item-in-fn.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-trait-lifetime.rs (renamed from src/test/run-pass/borrowck-trait-lifetime.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-uniq-via-ref.rs (renamed from src/test/run-pass/borrowck-uniq-via-ref.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-univariant-enum.rs (renamed from src/test/run-pass/borrowck-univariant-enum.rs)0
-rw-r--r--src/test/run-pass/borrowck/borrowck-use-mut-borrow.rs (renamed from src/test/run-pass/borrowck-use-mut-borrow.rs)0
-rw-r--r--src/test/run-pass/empty-struct-braces-derive.rs44
-rw-r--r--src/test/run-pass/empty-struct-braces-gate-1.rs (renamed from src/test/compile-fail/empty-struct-braces-gate-1.rs)4
-rw-r--r--src/test/run-pass/empty-struct-braces-gate-2.rs (renamed from src/test/compile-fail/empty-struct-braces-gate-2.rs)14
-rw-r--r--src/test/run-pass/empty-struct-braces.rs2
-rw-r--r--src/test/run-pass/foreign-mod-src/compiletest-ignore-dir0
-rw-r--r--src/test/run-pass/foreign-src/compiletest-ignore-dir0
-rw-r--r--src/test/run-pass/intrinsic-atomics.rs31
-rw-r--r--src/test/run-pass/issue-16819.rs2
-rw-r--r--src/test/run-pass/issue-25916.rs35
-rw-r--r--src/test/run-pass/issue-29914-2.rs15
-rw-r--r--src/test/run-pass/issue-29914-3.rs16
-rw-r--r--src/test/run-pass/issue-29914.rs16
-rw-r--r--src/test/run-pass/issue-31702.rs24
-rw-r--r--src/test/run-pass/issue-pr29383.rs2
-rw-r--r--src/test/run-pass/issue_26873_multifile/compiletest-ignore-dir0
-rw-r--r--src/test/run-pass/mir_augmented_assignments.rs185
-rw-r--r--src/test/run-pass/mir_autoderef.rs41
-rw-r--r--src/test/run-pass/mir_struct_with_assoc_ty.rs41
-rw-r--r--src/test/run-pass/mir_trans_calls.rs36
-rw-r--r--src/test/run-pass/mod_dir_implicit_aux/compiletest-ignore-dir0
-rw-r--r--src/test/run-pass/mod_dir_simple/compiletest-ignore-dir0
-rw-r--r--src/test/run-pass/module-polymorphism3-files/compiletest-ignore-dir0
-rw-r--r--src/test/run-pass/num-wrapping.rs2
-rw-r--r--src/test/run-pass/privacy-reexport.rs3
-rw-r--r--src/test/run-pass/reachable-unnameable-items.rs41
-rw-r--r--src/test/run-pass/reachable-unnameable-type-alias.rs24
-rw-r--r--src/test/run-pass/signal-alternate-stack-cleanup.rs44
-rw-r--r--src/test/run-pass/thread-local-extern-static.rs26
-rw-r--r--src/test/run-pass/write-fmt-errors.rs54
-rw-r--r--src/test/rustdoc/issue-26995.rs17
-rw-r--r--src/test/rustdoc/issue-29584.rs18
-rw-r--r--src/test/rustdoc/issue-31808.rs23
-rw-r--r--src/test/rustdoc/issue-31899.rs70
-rw-r--r--src/test/rustdoc/src-links/compiletest-ignore-dir0
558 files changed, 9167 insertions, 4312 deletions
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index f9593eb1609..05186d48ce2 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -3,57 +3,42 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cmake 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "advapi32-sys"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "build_helper"
 version = "0.1.0"
 
 [[package]]
 name = "cmake"
-version = "0.1.10"
+version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "filetime"
-version = "0.1.8"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gcc"
-version = "0.3.19"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
-]
 
 [[package]]
 name = "getopts"
@@ -71,30 +56,28 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.2"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "num_cpus"
-version = "0.2.9"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-serialize"
-version = "0.3.16"
+version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "toml"
-version = "0.1.23"
+version = "0.1.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 744c30aa08f..6659894a171 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -73,6 +73,7 @@ class RustBuild:
 
         if self.rustc().startswith(self.bin_root()) and \
            (not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
+            shutil.rmtree(self.bin_root())
             filename = "rust-std-nightly-" + self.build + ".tar.gz"
             url = "https://static.rust-lang.org/dist/" + self.snap_rustc_date()
             tarball = os.path.join(rustc_cache, filename)
diff --git a/src/bootstrap/build/compile.rs b/src/bootstrap/build/compile.rs
index c22648b4710..3be4199352c 100644
--- a/src/bootstrap/build/compile.rs
+++ b/src/bootstrap/build/compile.rs
@@ -58,6 +58,30 @@ pub fn std<'a>(build: &'a Build, stage: u32, target: &str,
     }
 
     build.run(&mut cargo);
+    std_link(build, stage, target, compiler, host);
+}
+
+/// Link all libstd rlibs/dylibs into the sysroot location.
+///
+/// Links those artifacts generated in the given `stage` for `target` produced
+/// by `compiler` into `host`'s sysroot.
+pub fn std_link(build: &Build,
+                stage: u32,
+                target: &str,
+                compiler: &Compiler,
+                host: &str) {
+    let libdir = build.sysroot_libdir(stage, host, target);
+    let out_dir = build.cargo_out(stage, compiler.host, true, target);
+
+    // If we're linking one compiler host's output into another, then we weren't
+    // called from the `std` method above. In that case we clean out what's
+    // already there and then also link compiler-rt into place.
+    if host != compiler.host {
+        let _ = fs::remove_dir_all(&libdir);
+        t!(fs::create_dir_all(&libdir));
+        t!(fs::hard_link(&build.compiler_rt_built.borrow()[target],
+                         libdir.join(staticlib("compiler-rt", target))));
+    }
     add_to_sysroot(&out_dir, &libdir);
 }
 
@@ -99,7 +123,6 @@ pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str,
              host, target);
 
     let out_dir = build.cargo_out(stage, &host, false, target);
-    let rustc = out_dir.join(exe("rustc", target));
     build.clear_if_dirty(&out_dir, &libstd_shim(build, stage, &host, target));
 
     let mut cargo = build.cargo(stage, compiler, false, target, "build");
@@ -131,10 +154,13 @@ pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str,
     if !build.unstable_features {
         cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1");
     }
-    if let Some(config) = build.config.target_config.get(target) {
-        if let Some(ref s) = config.llvm_config {
-            cargo.env("LLVM_CONFIG", s);
-        }
+    let target_config = build.config.target_config.get(target);
+    if let Some(ref s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
+        cargo.env("LLVM_CONFIG", s);
+    } else {
+        let llvm_config = build.llvm_out(&build.config.build).join("bin")
+                               .join(exe("llvm-config", target));
+        cargo.env("LLVM_CONFIG", llvm_config);
     }
     if build.config.llvm_static_stdcpp {
         cargo.env("LLVM_STATIC_STDCPP",
@@ -148,12 +174,21 @@ pub fn rustc<'a>(build: &'a Build, stage: u32, target: &str,
     }
     build.run(&mut cargo);
 
-    let sysroot_libdir = build.sysroot_libdir(stage, host, target);
-    add_to_sysroot(&out_dir, &sysroot_libdir);
+    rustc_link(build, stage, target, compiler, compiler.host);
+}
 
-    if host == target {
-        assemble_compiler(build, stage, target, &rustc);
-    }
+/// Link all librustc rlibs/dylibs into the sysroot location.
+///
+/// Links those artifacts generated in the given `stage` for `target` produced
+/// by `compiler` into `host`'s sysroot.
+pub fn rustc_link(build: &Build,
+                  stage: u32,
+                  target: &str,
+                  compiler: &Compiler,
+                  host: &str) {
+    let libdir = build.sysroot_libdir(stage, host, target);
+    let out_dir = build.cargo_out(stage, compiler.host, false, target);
+    add_to_sysroot(&out_dir, &libdir);
 }
 
 /// Cargo's output path for the standard library in a given stage, compiled
@@ -169,21 +204,21 @@ fn compiler_file(compiler: &Path, file: &str) -> String {
 
 /// Prepare a new compiler from the artifacts in `stage`
 ///
-/// This will link the compiler built by `host` during the stage
-/// specified to the sysroot location for `host` to be the official
-/// `stage + 1` compiler for that host. This means that the `rustc` binary
-/// itself will be linked into place along with all supporting dynamic
-/// libraries.
-fn assemble_compiler(build: &Build, stage: u32, host: &str, rustc: &Path) {
+/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
+/// must have been previously produced by the `stage - 1` build.config.build
+/// compiler.
+pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
+    assert!(stage > 0, "the stage0 compiler isn't assembled, it's downloaded");
+
     // Clear out old files
-    let sysroot = build.sysroot(stage + 1, host);
+    let sysroot = build.sysroot(stage, host);
     let _ = fs::remove_dir_all(&sysroot);
     t!(fs::create_dir_all(&sysroot));
 
     // Link in all dylibs to the libdir
     let sysroot_libdir = sysroot.join(libdir(host));
     t!(fs::create_dir_all(&sysroot_libdir));
-    let src_libdir = build.sysroot_libdir(stage, host, host);
+    let src_libdir = build.sysroot_libdir(stage - 1, &build.config.build, host);
     for f in t!(fs::read_dir(&src_libdir)).map(|f| t!(f)) {
         let filename = f.file_name().into_string().unwrap();
         if is_dylib(&filename) {
@@ -191,17 +226,20 @@ fn assemble_compiler(build: &Build, stage: u32, host: &str, rustc: &Path) {
         }
     }
 
+    let out_dir = build.cargo_out(stage - 1, &build.config.build, false, host);
+
     // Link the compiler binary itself into place
+    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 + 1, host));
+    let compiler = build.compiler_path(&Compiler::new(stage, host));
     let _ = fs::remove_file(&compiler);
     t!(fs::hard_link(rustc, compiler));
 
     // See if rustdoc exists to link it into place
-    let exe = exe("rustdoc", host);
-    let rustdoc_src = rustc.parent().unwrap().join(&exe);
-    let rustdoc_dst = bindir.join(exe);
+    let rustdoc = exe("rustdoc", host);
+    let rustdoc_src = out_dir.join(&rustdoc);
+    let rustdoc_dst = bindir.join(&rustdoc);
     if fs::metadata(&rustdoc_src).is_ok() {
         let _ = fs::remove_file(&rustdoc_dst);
         t!(fs::hard_link(&rustdoc_src, &rustdoc_dst));
diff --git a/src/bootstrap/build/mod.rs b/src/bootstrap/build/mod.rs
index 2bb169a5ebc..98d821b8b90 100644
--- a/src/bootstrap/build/mod.rs
+++ b/src/bootstrap/build/mod.rs
@@ -40,6 +40,14 @@ mod sanity;
 mod step;
 mod util;
 
+#[cfg(windows)]
+mod job;
+
+#[cfg(not(windows))]
+mod job {
+    pub unsafe fn setup() {}
+}
+
 pub use build::config::Config;
 pub use build::flags::Flags;
 
@@ -115,14 +123,9 @@ impl Build {
     pub fn build(&mut self) {
         use build::step::Source::*;
 
-        // see comments in job.rs for what's going on here
-        #[cfg(windows)]
-        fn setup_job() {
-            mod job;
-            unsafe { job::setup() }
+        unsafe {
+            job::setup();
         }
-        #[cfg(not(windows))] fn setup_job() {}
-        setup_job();
 
         if self.flags.clean {
             return clean::clean(self);
@@ -148,8 +151,19 @@ impl Build {
                 Librustc { stage, compiler } => {
                     compile::rustc(self, stage, target.target, &compiler);
                 }
+                LibstdLink { stage, compiler, host } => {
+                    compile::std_link(self, stage, target.target,
+                                      &compiler, host);
+                }
+                LibrustcLink { stage, compiler, host } => {
+                    compile::rustc_link(self, stage, target.target,
+                                        &compiler, host);
+                }
+                Rustc { stage: 0 } => {
+                    // nothing to do...
+                }
                 Rustc { stage } => {
-                    println!("ok, rustc stage{} in {}", stage, target.target);
+                    compile::assemble_rustc(self, stage, target.target);
                 }
                 DocBook { stage } => {
                     doc::rustbook(self, stage, target.target, "book", &doc_out);
@@ -177,24 +191,25 @@ impl Build {
         if fs::metadata(self.src.join(".git")).is_err() {
             return
         }
-        let out = output(Command::new("git").arg("submodule").arg("status"));
+        let git_submodule = || {
+            let mut cmd = Command::new("git");
+            cmd.current_dir(&self.src).arg("submodule");
+            return cmd
+        };
+        let out = output(git_submodule().arg("status"));
         if !out.lines().any(|l| l.starts_with("+") || l.starts_with("-")) {
             return
         }
 
-        self.run(Command::new("git").arg("submodule").arg("sync"));
-        self.run(Command::new("git").arg("submodule").arg("init"));
-        self.run(Command::new("git").arg("submodule").arg("update"));
-        self.run(Command::new("git").arg("submodule").arg("update")
-                                    .arg("--recursive"));
-        self.run(Command::new("git").arg("submodule").arg("status")
-                                    .arg("--recursive"));
-        self.run(Command::new("git").arg("submodule").arg("foreach")
-                                    .arg("--recursive")
-                                    .arg("git").arg("clean").arg("-fdx"));
-        self.run(Command::new("git").arg("submodule").arg("foreach")
-                                    .arg("--recursive")
-                                    .arg("git").arg("checkout").arg("."));
+        self.run(git_submodule().arg("sync"));
+        self.run(git_submodule().arg("init"));
+        self.run(git_submodule().arg("update"));
+        self.run(git_submodule().arg("update").arg("--recursive"));
+        self.run(git_submodule().arg("status").arg("--recursive"));
+        self.run(git_submodule().arg("foreach").arg("--recursive")
+                                .arg("git").arg("clean").arg("-fdx"));
+        self.run(git_submodule().arg("foreach").arg("--recursive")
+                                .arg("git").arg("checkout").arg("."));
     }
 
     /// Clear out `dir` if our build has been flagged as dirty, and also set
@@ -441,21 +456,7 @@ impl Build {
     }
 
     fn rustc_flags(&self, target: &str) -> Vec<String> {
-        let mut base = match target {
-            "arm-unknown-linux-gnueabihf" => {
-                vec!["-Ctarget-feature=+v6,+vfp2".to_string()]
-            }
-            "mips-unknown-linux-gnu" => {
-                vec!["-Ctarget-cpu=mips32r2".to_string(),
-                     "-Ctarget-feature=+mips32r2".to_string(),
-                     "-Csoft-float".to_string()]
-            }
-            "mipsel-unknown-linux-gnu" => {
-                vec!["-Ctarget-cpu=mips32".to_string(),
-                     "-Ctarget-feature=+mips32".to_string()]
-            }
-            _ => Vec::new(),
-        };
+        let mut base = Vec::new();
         if target != self.config.build && !target.contains("msvc") {
             base.push(format!("-Clinker={}", self.cc(target).display()));
         }
diff --git a/src/bootstrap/build/native.rs b/src/bootstrap/build/native.rs
index 6ad5f404123..a9d84b60fbf 100644
--- a/src/bootstrap/build/native.rs
+++ b/src/bootstrap/build/native.rs
@@ -115,6 +115,11 @@ pub fn compiler_rt(build: &Build, target: &str) {
     let mode = if build.config.rust_optimize {"Release"} else {"Debug"};
     let (dir, build_target, libname) = if target.contains("linux") {
         let os = if target.contains("android") {"-android"} else {""};
+        let arch = if arch.starts_with("arm") && target.contains("eabihf") {
+            "armhf"
+        } else {
+            arch
+        };
         let target = format!("clang_rt.builtins-{}{}", arch, os);
         ("linux".to_string(), target.clone(), target)
     } else if target.contains("darwin") {
@@ -151,7 +156,10 @@ pub fn compiler_rt(build: &Build, target: &str) {
        .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target)
        .define("COMPILER_RT_BUILD_SANITIZERS", "OFF")
        .define("COMPILER_RT_BUILD_EMUTLS", "OFF")
+       // inform about c/c++ compilers, the c++ compiler isn't actually used but
+       // it's needed to get the initial configure to work on all platforms.
        .define("CMAKE_C_COMPILER", build.cc(target))
+       .define("CMAKE_CXX_COMPILER", build.cc(target))
        .build_target(&build_target);
     cfg.build();
 }
diff --git a/src/bootstrap/build/step.rs b/src/bootstrap/build/step.rs
index d82c62b3667..ba0095ce849 100644
--- a/src/bootstrap/build/step.rs
+++ b/src/bootstrap/build/step.rs
@@ -21,9 +21,36 @@ pub struct Step<'a> {
 macro_rules! targets {
     ($m:ident) => {
         $m! {
+            // Step representing building the stageN compiler. This is just the
+            // compiler executable itself, not any of the support libraries
             (rustc, Rustc { stage: u32 }),
+
+            // Steps for the two main cargo builds, one for the standard library
+            // and one for the compiler itself. These are parameterized over the
+            // stage output they're going to be placed in along with the
+            // compiler which is producing the copy of libstd or librustc
             (libstd, Libstd { stage: u32, compiler: Compiler<'a> }),
             (librustc, Librustc { stage: u32, compiler: Compiler<'a> }),
+
+            // Links the standard library/librustc produced by the compiler
+            // provided into the host's directory also provided.
+            (libstd_link, LibstdLink {
+                stage: u32,
+                compiler: Compiler<'a>,
+                host: &'a str
+            }),
+            (librustc_link, LibrustcLink {
+                stage: u32,
+                compiler: Compiler<'a>,
+                host: &'a str
+            }),
+
+            // Steps for long-running native builds. Ideally these wouldn't
+            // actually exist and would be part of build scripts, but for now
+            // these are here.
+            //
+            // There aren't really any parameters to this, but empty structs
+            // with braces are unstable so we just pick something that works.
             (llvm, Llvm { _dummy: () }),
             (compiler_rt, CompilerRt { _dummy: () }),
             (doc, Doc { stage: u32 }),
@@ -99,13 +126,25 @@ fn top_level(build: &Build) -> Vec<Step> {
                 continue
             }
             let host = t.target(host);
-            targets.push(host.librustc(stage, host.compiler(stage)));
+            if host.target == build.config.build {
+                targets.push(host.librustc(stage, host.compiler(stage)));
+            } else {
+                targets.push(host.librustc_link(stage, t.compiler(stage),
+                                                host.target));
+            }
             for target in build.config.target.iter() {
                 if !build.flags.target.contains(target) {
                     continue
                 }
-                targets.push(host.target(target)
-                                 .libstd(stage, host.compiler(stage)));
+
+                if host.target == build.config.build {
+                    targets.push(host.target(target)
+                                     .libstd(stage, host.compiler(stage)));
+                } else {
+                    targets.push(host.target(target)
+                                     .libstd_link(stage, t.compiler(stage),
+                                                  host.target));
+                }
             }
         }
     }
@@ -120,10 +159,14 @@ fn add_steps<'a>(build: &'a Build,
                  target: &Step<'a>,
                  targets: &mut Vec<Step<'a>>) {
     for step in build.flags.step.iter() {
-        let compiler = host.compiler(stage);
+        let compiler = host.target(&build.config.build).compiler(stage);
         match &step[..] {
             "libstd" => targets.push(target.libstd(stage, compiler)),
-            "librustc" => targets.push(target.libstd(stage, compiler)),
+            "librustc" => targets.push(target.librustc(stage, compiler)),
+            "libstd-link" => targets.push(target.libstd_link(stage, compiler,
+                                                             host.target)),
+            "librustc-link" => targets.push(target.librustc_link(stage, compiler,
+                                                                 host.target)),
             "rustc" => targets.push(host.rustc(stage)),
             "llvm" => targets.push(target.llvm(())),
             "compiler-rt" => targets.push(target.compiler_rt(())),
@@ -162,15 +205,11 @@ impl<'a> Step<'a> {
     pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
         match self.src {
             Source::Rustc { stage: 0 } => {
-                if self.target == build.config.build {
-                    Vec::new()
-                } else {
-                    let compiler = Compiler::new(0, &build.config.build);
-                    vec![self.librustc(0, compiler)]
-                }
+                Vec::new()
             }
             Source::Rustc { stage } => {
-                vec![self.librustc(stage - 1, self.compiler(stage - 1))]
+                let compiler = Compiler::new(stage - 1, &build.config.build);
+                vec![self.librustc(stage - 1, compiler)]
             }
             Source::Librustc { stage, compiler } => {
                 vec![self.libstd(stage, compiler), self.llvm(())]
@@ -179,6 +218,14 @@ impl<'a> Step<'a> {
                 vec![self.compiler_rt(()),
                      self.rustc(compiler.stage).target(compiler.host)]
             }
+            Source::LibrustcLink { stage, compiler, host } => {
+                vec![self.librustc(stage, compiler),
+                     self.libstd_link(stage, compiler, host)]
+            }
+            Source::LibstdLink { stage, compiler, host } => {
+                vec![self.libstd(stage, compiler),
+                     self.target(host).rustc(stage)]
+            }
             Source::CompilerRt { _dummy } => {
                 vec![self.llvm(()).target(&build.config.build)]
             }
diff --git a/src/bootstrap/rustc.rs b/src/bootstrap/rustc.rs
index 0c30360ba79..4e9d6da9157 100644
--- a/src/bootstrap/rustc.rs
+++ b/src/bootstrap/rustc.rs
@@ -61,6 +61,9 @@ fn main() {
             root.push("/lib");
             cmd.arg("-L").arg(&root);
         }
+        if let Ok(s) = env::var("RUSTC_FLAGS") {
+            cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
+        }
     }
 
     // Set various options from config.toml to configure how we're building
@@ -79,9 +82,6 @@ fn main() {
     if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") {
         cmd.arg("-C").arg(format!("codegen-units={}", s));
     }
-    if let Ok(s) = env::var("RUSTC_FLAGS") {
-        cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
-    }
 
     // Actually run the compiler!
     std::process::exit(match cmd.status() {
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index da8331fc062..bbace16f059 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -28,10 +28,12 @@ extern crate log;
 
 use std::env;
 use std::fs;
+use std::io;
 use std::path::{Path, PathBuf};
 use getopts::{optopt, optflag, reqopt};
 use common::Config;
 use common::{Pretty, DebugInfoGdb, DebugInfoLldb};
+use test::TestPaths;
 use util::logv;
 
 pub mod procsrv;
@@ -267,15 +269,61 @@ pub fn make_tests(config: &Config) -> Vec<test::TestDescAndFn> {
     debug!("making tests from {:?}",
            config.src_base.display());
     let mut tests = Vec::new();
-    let dirs = fs::read_dir(&config.src_base).unwrap();
+    collect_tests_from_dir(config,
+                           &config.src_base,
+                           &config.src_base,
+                           &PathBuf::new(),
+                           &mut tests)
+        .unwrap();
+    tests
+}
+
+fn collect_tests_from_dir(config: &Config,
+                          base: &Path,
+                          dir: &Path,
+                          relative_dir_path: &Path,
+                          tests: &mut Vec<test::TestDescAndFn>)
+                          -> io::Result<()> {
+    // Ignore directories that contain a file
+    // `compiletest-ignore-dir`.
+    for file in try!(fs::read_dir(dir)) {
+        let file = try!(file);
+        if file.file_name() == *"compiletest-ignore-dir" {
+            return Ok(());
+        }
+    }
+
+    let dirs = try!(fs::read_dir(dir));
     for file in dirs {
-        let file = file.unwrap().path();
-        debug!("inspecting file {:?}", file.display());
-        if is_test(config, &file) {
-            tests.push(make_test(config, &file))
+        let file = try!(file);
+        let file_path = file.path();
+        debug!("inspecting file {:?}", file_path.display());
+        if is_test(config, &file_path) {
+            // If we find a test foo/bar.rs, we have to build the
+            // output directory `$build/foo` so we can write
+            // `$build/foo/bar` into it. We do this *now* in this
+            // sequential loop because otherwise, if we do it in the
+            // tests themselves, they race for the privilege of
+            // creating the directories and sometimes fail randomly.
+            let build_dir = config.build_base.join(&relative_dir_path);
+            fs::create_dir_all(&build_dir).unwrap();
+
+            let paths = TestPaths {
+                file: file_path,
+                base: base.to_path_buf(),
+                relative_dir: relative_dir_path.to_path_buf(),
+            };
+            tests.push(make_test(config, &paths))
+        } else if file_path.is_dir() {
+            let relative_file_path = relative_dir_path.join(file.file_name());
+            try!(collect_tests_from_dir(config,
+                                        base,
+                                        &file_path,
+                                        &relative_file_path,
+                                        tests));
         }
     }
-    tests
+    Ok(())
 }
 
 pub fn is_test(config: &Config, testfile: &Path) -> bool {
@@ -305,36 +353,33 @@ pub fn is_test(config: &Config, testfile: &Path) -> bool {
     return valid;
 }
 
-pub fn make_test(config: &Config, testfile: &Path) -> test::TestDescAndFn
-{
+pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn {
     test::TestDescAndFn {
         desc: test::TestDesc {
-            name: make_test_name(config, testfile),
-            ignore: header::is_test_ignored(config, testfile),
+            name: make_test_name(config, testpaths),
+            ignore: header::is_test_ignored(config, &testpaths.file),
             should_panic: test::ShouldPanic::No,
         },
-        testfn: make_test_closure(config, &testfile),
+        testfn: make_test_closure(config, testpaths),
     }
 }
 
-pub fn make_test_name(config: &Config, testfile: &Path) -> test::TestName {
-
-    // Try to elide redundant long paths
-    fn shorten(path: &Path) -> String {
-        let filename = path.file_name().unwrap().to_str();
-        let p = path.parent().unwrap();
-        let dir = p.file_name().unwrap().to_str();
-        format!("{}/{}", dir.unwrap_or(""), filename.unwrap_or(""))
-    }
-
-    test::DynTestName(format!("[{}] {}", config.mode, shorten(testfile)))
+pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName {
+    // Convert a complete path to something like
+    //
+    //    run-pass/foo/bar/baz.rs
+    let path =
+        PathBuf::from(config.mode.to_string())
+        .join(&testpaths.relative_dir)
+        .join(&testpaths.file.file_name().unwrap());
+    test::DynTestName(format!("[{}] {}", config.mode, path.display()))
 }
 
-pub fn make_test_closure(config: &Config, testfile: &Path) -> test::TestFn {
-    let config = (*config).clone();
-    let testfile = testfile.to_path_buf();
+pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn {
+    let config = config.clone();
+    let testpaths = testpaths.clone();
     test::DynTestFn(Box::new(move || {
-        runtest::run(config, &testfile)
+        runtest::run(config, &testpaths)
     }))
 }
 
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 5eef6b7f24c..7cad5a4391c 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -15,6 +15,7 @@ use errors;
 use header::TestProps;
 use header;
 use procsrv;
+use test::TestPaths;
 use util::logv;
 
 use std::env;
@@ -27,7 +28,7 @@ use std::net::TcpStream;
 use std::path::{Path, PathBuf, Component};
 use std::process::{Command, Output, ExitStatus};
 
-pub fn run(config: Config, testfile: &Path) {
+pub fn run(config: Config, testpaths: &TestPaths) {
     match &*config.target {
 
         "arm-linux-androideabi" | "aarch64-linux-android" => {
@@ -43,21 +44,21 @@ pub fn run(config: Config, testfile: &Path) {
         // We're going to be dumping a lot of info. Start on a new line.
         print!("\n\n");
     }
-    debug!("running {:?}", testfile.display());
-    let props = header::load_props(&testfile);
+    debug!("running {:?}", testpaths.file.display());
+    let props = header::load_props(&testpaths.file);
     debug!("loaded props");
     match config.mode {
-        CompileFail => run_cfail_test(&config, &props, &testfile),
-        ParseFail => run_cfail_test(&config, &props, &testfile),
-        RunFail => run_rfail_test(&config, &props, &testfile),
-        RunPass => run_rpass_test(&config, &props, &testfile),
-        RunPassValgrind => run_valgrind_test(&config, &props, &testfile),
-        Pretty => run_pretty_test(&config, &props, &testfile),
-        DebugInfoGdb => run_debuginfo_gdb_test(&config, &props, &testfile),
-        DebugInfoLldb => run_debuginfo_lldb_test(&config, &props, &testfile),
-        Codegen => run_codegen_test(&config, &props, &testfile),
-        Rustdoc => run_rustdoc_test(&config, &props, &testfile),
-        CodegenUnits => run_codegen_units_test(&config, &props, &testfile),
+        CompileFail => run_cfail_test(&config, &props, &testpaths),
+        ParseFail => run_cfail_test(&config, &props, &testpaths),
+        RunFail => run_rfail_test(&config, &props, &testpaths),
+        RunPass => run_rpass_test(&config, &props, &testpaths),
+        RunPassValgrind => run_valgrind_test(&config, &props, &testpaths),
+        Pretty => run_pretty_test(&config, &props, &testpaths),
+        DebugInfoGdb => run_debuginfo_gdb_test(&config, &props, &testpaths),
+        DebugInfoLldb => run_debuginfo_lldb_test(&config, &props, &testpaths),
+        Codegen => run_codegen_test(&config, &props, &testpaths),
+        Rustdoc => run_rustdoc_test(&config, &props, &testpaths),
+        CodegenUnits => run_codegen_units_test(&config, &props, &testpaths),
     }
 }
 
@@ -69,8 +70,8 @@ fn get_output(props: &TestProps, proc_res: &ProcRes) -> String {
     }
 }
 
-fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
-    let proc_res = compile_test(config, props, testfile);
+fn run_cfail_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+    let proc_res = compile_test(config, props, testpaths);
 
     if proc_res.status.success() {
         fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[..],
@@ -84,27 +85,27 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
     }
 
     let output_to_check = get_output(props, &proc_res);
-    let expected_errors = errors::load_errors(testfile);
+    let expected_errors = errors::load_errors(&testpaths.file);
     if !expected_errors.is_empty() {
         if !props.error_patterns.is_empty() {
             fatal("both error pattern and expected errors specified");
         }
-        check_expected_errors(expected_errors, testfile, &proc_res);
+        check_expected_errors(expected_errors, testpaths, &proc_res);
     } else {
-        check_error_patterns(props, testfile, &output_to_check, &proc_res);
+        check_error_patterns(props, testpaths, &output_to_check, &proc_res);
     }
     check_no_compiler_crash(&proc_res);
     check_forbid_output(props, &output_to_check, &proc_res);
 }
 
-fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) {
-    let proc_res = compile_test(config, props, testfile);
+fn run_rfail_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+    let proc_res = compile_test(config, props, testpaths);
 
     if !proc_res.status.success() {
         fatal_proc_rec("compilation failed!", &proc_res);
     }
 
-    let proc_res = exec_compiled_test(config, props, testfile);
+    let proc_res = exec_compiled_test(config, props, testpaths);
 
     // The value our Makefile configures valgrind to return on failure
     const VALGRIND_ERR: i32 = 100;
@@ -114,7 +115,7 @@ fn run_rfail_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     let output_to_check = get_output(props, &proc_res);
     check_correct_failure_status(&proc_res);
-    check_error_patterns(props, testfile, &output_to_check, &proc_res);
+    check_error_patterns(props, testpaths, &output_to_check, &proc_res);
 }
 
 fn check_correct_failure_status(proc_res: &ProcRes) {
@@ -128,27 +129,27 @@ fn check_correct_failure_status(proc_res: &ProcRes) {
     }
 }
 
-fn run_rpass_test(config: &Config, props: &TestProps, testfile: &Path) {
-    let proc_res = compile_test(config, props, testfile);
+fn run_rpass_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+    let proc_res = compile_test(config, props, testpaths);
 
     if !proc_res.status.success() {
         fatal_proc_rec("compilation failed!", &proc_res);
     }
 
-    let proc_res = exec_compiled_test(config, props, testfile);
+    let proc_res = exec_compiled_test(config, props, testpaths);
 
     if !proc_res.status.success() {
         fatal_proc_rec("test run failed!", &proc_res);
     }
 }
 
-fn run_valgrind_test(config: &Config, props: &TestProps, testfile: &Path) {
+fn run_valgrind_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
     if config.valgrind_path.is_none() {
         assert!(!config.force_valgrind);
-        return run_rpass_test(config, props, testfile);
+        return run_rpass_test(config, props, testpaths);
     }
 
-    let mut proc_res = compile_test(config, props, testfile);
+    let mut proc_res = compile_test(config, props, testpaths);
 
     if !proc_res.status.success() {
         fatal_proc_rec("compilation failed!", &proc_res);
@@ -156,14 +157,14 @@ fn run_valgrind_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     let mut new_config = config.clone();
     new_config.runtool = new_config.valgrind_path.clone();
-    proc_res = exec_compiled_test(&new_config, props, testfile);
+    proc_res = exec_compiled_test(&new_config, props, testpaths);
 
     if !proc_res.status.success() {
         fatal_proc_rec("test run failed!", &proc_res);
     }
 }
 
-fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
+fn run_pretty_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
     if props.pp_exact.is_some() {
         logv(config, "testing for exact pretty-printing".to_owned());
     } else {
@@ -174,7 +175,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
         match props.pp_exact { Some(_) => 1, None => 2 };
 
     let mut src = String::new();
-    File::open(testfile).unwrap().read_to_string(&mut src).unwrap();
+    File::open(&testpaths.file).unwrap().read_to_string(&mut src).unwrap();
     let mut srcs = vec!(src);
 
     let mut round = 0;
@@ -182,7 +183,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
         logv(config, format!("pretty-printing round {}", round));
         let proc_res = print_source(config,
                                     props,
-                                    testfile,
+                                    testpaths,
                                     srcs[round].to_owned(),
                                     &props.pretty_mode);
 
@@ -198,7 +199,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     let mut expected = match props.pp_exact {
         Some(ref file) => {
-            let filepath = testfile.parent().unwrap().join(file);
+            let filepath = testpaths.file.parent().unwrap().join(file);
             let mut s = String::new();
             File::open(&filepath).unwrap().read_to_string(&mut s).unwrap();
             s
@@ -220,7 +221,7 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
     if props.pretty_compare_only { return; }
 
     // Finally, let's make sure it actually appears to remain valid code
-    let proc_res = typecheck_source(config, props, testfile, actual);
+    let proc_res = typecheck_source(config, props, testpaths, actual);
 
     if !proc_res.status.success() {
         fatal_proc_rec("pretty-printed source does not typecheck", &proc_res);
@@ -228,13 +229,13 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
     if !props.pretty_expanded { return }
 
     // additionally, run `--pretty expanded` and try to build it.
-    let proc_res = print_source(config, props, testfile, srcs[round].clone(), "expanded");
+    let proc_res = print_source(config, props, testpaths, srcs[round].clone(), "expanded");
     if !proc_res.status.success() {
         fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
     }
 
     let ProcRes{ stdout: expanded_src, .. } = proc_res;
-    let proc_res = typecheck_source(config, props, testfile, expanded_src);
+    let proc_res = typecheck_source(config, props, testpaths, expanded_src);
     if !proc_res.status.success() {
         fatal_proc_rec("pretty-printed source (expanded) does not typecheck",
                       &proc_res);
@@ -244,15 +245,15 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     fn print_source(config: &Config,
                     props: &TestProps,
-                    testfile: &Path,
+                    testpaths: &TestPaths,
                     src: String,
                     pretty_type: &str) -> ProcRes {
-        let aux_dir = aux_output_dir_name(config, testfile);
+        let aux_dir = aux_output_dir_name(config, testpaths);
         compose_and_run(config,
-                        testfile,
+                        testpaths,
                         make_pp_args(config,
                                      props,
-                                     testfile,
+                                     testpaths,
                                      pretty_type.to_owned()),
                         props.exec_env.clone(),
                         &config.compile_lib_path,
@@ -262,9 +263,9 @@ fn run_pretty_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     fn make_pp_args(config: &Config,
                     props: &TestProps,
-                    testfile: &Path,
+                    testpaths: &TestPaths,
                     pretty_type: String) -> ProcArgs {
-        let aux_dir = aux_output_dir_name(config, testfile);
+        let aux_dir = aux_output_dir_name(config, testpaths);
         // FIXME (#9639): This needs to handle non-utf8 paths
         let mut args = vec!("-".to_owned(),
                             "-Zunstable-options".to_owned(),
@@ -300,13 +301,13 @@ actual:\n\
     }
 
     fn typecheck_source(config: &Config, props: &TestProps,
-                        testfile: &Path, src: String) -> ProcRes {
-        let args = make_typecheck_args(config, props, testfile);
-        compose_and_run_compiler(config, props, testfile, args, Some(src))
+                        testpaths: &TestPaths, src: String) -> ProcRes {
+        let args = make_typecheck_args(config, props, testpaths);
+        compose_and_run_compiler(config, props, testpaths, args, Some(src))
     }
 
-    fn make_typecheck_args(config: &Config, props: &TestProps, testfile: &Path) -> ProcArgs {
-        let aux_dir = aux_output_dir_name(config, testfile);
+    fn make_typecheck_args(config: &Config, props: &TestProps, testpaths: &TestPaths) -> ProcArgs {
+        let aux_dir = aux_output_dir_name(config, testpaths);
         let target = if props.force_host {
             &*config.host
         } else {
@@ -330,7 +331,7 @@ actual:\n\
     }
 }
 
-fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
+fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
     let mut config = Config {
         target_rustcflags: cleanup_debug_info_options(&config.target_rustcflags),
         host_rustcflags: cleanup_debug_info_options(&config.host_rustcflags),
@@ -342,16 +343,16 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
         commands,
         check_lines,
         breakpoint_lines
-    } = parse_debugger_commands(testfile, "gdb");
+    } = parse_debugger_commands(testpaths, "gdb");
     let mut cmds = commands.join("\n");
 
     // compile test file (it should have 'compile-flags:-g' in the header)
-    let compiler_run_result = compile_test(config, props, testfile);
+    let compiler_run_result = compile_test(config, props, testpaths);
     if !compiler_run_result.status.success() {
         fatal_proc_rec("compilation failed!", &compiler_run_result);
     }
 
-    let exe_file = make_exe_name(config, testfile);
+    let exe_file = make_exe_name(config, testpaths);
 
     let debugger_run_result;
     match &*config.target {
@@ -369,8 +370,10 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
                                          config.host, config.target));
             for line in &breakpoint_lines {
                 script_str.push_str(&format!("break {:?}:{}\n",
-                                             testfile.file_name().unwrap()
-                                                     .to_string_lossy(),
+                                             testpaths.file
+                                                      .file_name()
+                                                      .unwrap()
+                                                      .to_string_lossy(),
                                              *line)[..]);
             }
             script_str.push_str(&cmds);
@@ -378,7 +381,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
 
             debug!("script_str = {}", script_str);
             dump_output_file(config,
-                             testfile,
+                             testpaths,
                              &script_str,
                              "debugger.script");
 
@@ -441,7 +444,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
                 None => fatal("cannot find android cross path")
             };
 
-            let debugger_script = make_out_name(config, testfile, "debugger.script");
+            let debugger_script = make_out_name(config, testpaths, "debugger.script");
             // FIXME (#9639): This needs to handle non-utf8 paths
             let debugger_opts =
                 vec!("-quiet".to_owned(),
@@ -531,7 +534,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
             // Add line breakpoints
             for line in &breakpoint_lines {
                 script_str.push_str(&format!("break '{}':{}\n",
-                                             testfile.file_name().unwrap()
+                                             testpaths.file.file_name().unwrap()
                                                      .to_string_lossy(),
                                              *line));
             }
@@ -541,7 +544,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
 
             debug!("script_str = {}", script_str);
             dump_output_file(config,
-                             testfile,
+                             testpaths,
                              &script_str,
                              "debugger.script");
 
@@ -550,7 +553,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
                 if cfg!(windows) {"gdb.exe"} else {"gdb"}
             }
 
-            let debugger_script = make_out_name(config, testfile, "debugger.script");
+            let debugger_script = make_out_name(config, testpaths, "debugger.script");
 
             // FIXME (#9639): This needs to handle non-utf8 paths
             let debugger_opts =
@@ -567,7 +570,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
             let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)];
 
             debugger_run_result = compose_and_run(config,
-                                                  testfile,
+                                                  testpaths,
                                                   proc_args,
                                                   environment,
                                                   &config.run_lib_path,
@@ -596,7 +599,7 @@ fn find_rust_src_root(config: &Config) -> Option<PathBuf> {
     return None;
 }
 
-fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) {
+fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
     if config.lldb_python_dir.is_none() {
         fatal("Can't run LLDB test because LLDB's python path is not set.");
     }
@@ -610,12 +613,12 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
     let config = &mut config;
 
     // compile test file (it should have 'compile-flags:-g' in the header)
-    let compile_result = compile_test(config, props, testfile);
+    let compile_result = compile_test(config, props, testpaths);
     if !compile_result.status.success() {
         fatal_proc_rec("compilation failed!", &compile_result);
     }
 
-    let exe_file = make_exe_name(config, testfile);
+    let exe_file = make_exe_name(config, testpaths);
 
     match config.lldb_version {
         Some(ref version) => {
@@ -634,7 +637,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
         check_lines,
         breakpoint_lines,
         ..
-    } = parse_debugger_commands(testfile, "lldb");
+    } = parse_debugger_commands(testpaths, "lldb");
 
     // Write debugger script:
     // We don't want to hang when calling `quit` while the process is still running
@@ -676,13 +679,14 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
     // Write the script into a file
     debug!("script_str = {}", script_str);
     dump_output_file(config,
-                     testfile,
+                     testpaths,
                      &script_str,
                      "debugger.script");
-    let debugger_script = make_out_name(config, testfile, "debugger.script");
+    let debugger_script = make_out_name(config, testpaths, "debugger.script");
 
     // Let LLDB execute the script via lldb_batchmode.py
     let debugger_run_result = run_lldb(config,
+                                       testpaths,
                                        &exe_file,
                                        &debugger_script,
                                        &rust_src_root);
@@ -694,6 +698,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
     check_debugger_output(&debugger_run_result, &check_lines);
 
     fn run_lldb(config: &Config,
+                testpaths: &TestPaths,
                 test_executable: &Path,
                 debugger_script: &Path,
                 rust_src_root: &Path)
@@ -701,7 +706,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
         // Prepare the lldb_batchmode which executes the debugger script
         let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
         cmd2procres(config,
-                    test_executable,
+                    testpaths,
                     Command::new(&config.python)
                             .arg(&lldb_script_path)
                             .arg(test_executable)
@@ -711,7 +716,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
     }
 }
 
-fn cmd2procres(config: &Config, test_executable: &Path, cmd: &mut Command)
+fn cmd2procres(config: &Config, testpaths: &TestPaths, cmd: &mut Command)
               -> ProcRes {
     let (status, out, err) = match cmd.output() {
         Ok(Output { status, stdout, stderr }) => {
@@ -725,7 +730,7 @@ fn cmd2procres(config: &Config, test_executable: &Path, cmd: &mut Command)
         }
     };
 
-    dump_output(config, test_executable, &out, &err);
+    dump_output(config, testpaths, &out, &err);
     ProcRes {
         status: Status::Normal(status),
         stdout: out,
@@ -740,7 +745,7 @@ struct DebuggerCommands {
     breakpoint_lines: Vec<usize>,
 }
 
-fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
+fn parse_debugger_commands(testpaths: &TestPaths, debugger_prefix: &str)
                            -> DebuggerCommands {
     let command_directive = format!("{}-command", debugger_prefix);
     let check_directive = format!("{}-check", debugger_prefix);
@@ -749,7 +754,7 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
     let mut commands = vec!();
     let mut check_lines = vec!();
     let mut counter = 1;
-    let reader = BufReader::new(File::open(file_path).unwrap());
+    let reader = BufReader::new(File::open(&testpaths.file).unwrap());
     for line in reader.lines() {
         match line {
             Ok(line) => {
@@ -860,11 +865,12 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String])
 }
 
 fn check_error_patterns(props: &TestProps,
-                        testfile: &Path,
+                        testpaths: &TestPaths,
                         output_to_check: &str,
                         proc_res: &ProcRes) {
     if props.error_patterns.is_empty() {
-        fatal(&format!("no error pattern specified in {:?}", testfile.display()));
+        fatal(&format!("no error pattern specified in {:?}",
+                       testpaths.file.display()));
     }
     let mut next_err_idx = 0;
     let mut next_err_pat = &props.error_patterns[next_err_idx];
@@ -915,7 +921,7 @@ fn check_forbid_output(props: &TestProps,
 }
 
 fn check_expected_errors(expected_errors: Vec<errors::ExpectedError>,
-                         testfile: &Path,
+                         testpaths: &TestPaths,
                          proc_res: &ProcRes) {
 
     // true if we found the error in question
@@ -926,7 +932,9 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError>,
     }
 
     let prefixes = expected_errors.iter().map(|ee| {
-        format!("{}:{}:", testfile.display(), ee.line)
+        let expected = format!("{}:{}:", testpaths.file.display(), ee.line);
+        // On windows just translate all '\' path separators to '/'
+        expected.replace(r"\", "/")
     }).collect::<Vec<String>>();
 
     let (expect_help, expect_note) =
@@ -1142,62 +1150,64 @@ impl fmt::Display for Status {
 }
 
 fn compile_test(config: &Config, props: &TestProps,
-                testfile: &Path) -> ProcRes {
-    let aux_dir = aux_output_dir_name(config, testfile);
+                testpaths: &TestPaths) -> ProcRes {
+    let aux_dir = aux_output_dir_name(config, testpaths);
     // FIXME (#9639): This needs to handle non-utf8 paths
     let link_args = vec!("-L".to_owned(),
                          aux_dir.to_str().unwrap().to_owned());
     let args = make_compile_args(config,
                                  props,
                                  link_args,
-                                 |a, b| TargetLocation::ThisFile(make_exe_name(a, b)), testfile);
-    compose_and_run_compiler(config, props, testfile, args, None)
+                                 |a, b| TargetLocation::ThisFile(make_exe_name(a, b)), testpaths);
+    compose_and_run_compiler(config, props, testpaths, args, None)
 }
 
-fn document(config: &Config, props: &TestProps,
-            testfile: &Path, out_dir: &Path) -> ProcRes {
+fn document(config: &Config,
+            props: &TestProps,
+            testpaths: &TestPaths,
+            out_dir: &Path)
+            -> ProcRes {
     if props.build_aux_docs {
         for rel_ab in &props.aux_builds {
-            let abs_ab = config.aux_base.join(rel_ab);
-            let aux_props = header::load_props(&abs_ab);
-
-            let auxres = document(config, &aux_props, &abs_ab, out_dir);
+            let aux_testpaths = compute_aux_test_paths(config, testpaths, rel_ab);
+            let aux_props = header::load_props(&aux_testpaths.file);
+            let auxres = document(config, &aux_props, &aux_testpaths, out_dir);
             if !auxres.status.success() {
                 return auxres;
             }
         }
     }
 
-    let aux_dir = aux_output_dir_name(config, testfile);
+    let aux_dir = aux_output_dir_name(config, testpaths);
     let mut args = vec!["-L".to_owned(),
                         aux_dir.to_str().unwrap().to_owned(),
                         "-o".to_owned(),
                         out_dir.to_str().unwrap().to_owned(),
-                        testfile.to_str().unwrap().to_owned()];
+                        testpaths.file.to_str().unwrap().to_owned()];
     args.extend(split_maybe_args(&props.compile_flags));
     let args = ProcArgs {
         prog: config.rustdoc_path.to_str().unwrap().to_owned(),
         args: args,
     };
-    compose_and_run_compiler(config, props, testfile, args, None)
+    compose_and_run_compiler(config, props, testpaths, args, None)
 }
 
 fn exec_compiled_test(config: &Config, props: &TestProps,
-                      testfile: &Path) -> ProcRes {
+                      testpaths: &TestPaths) -> ProcRes {
 
     let env = props.exec_env.clone();
 
     match &*config.target {
 
         "arm-linux-androideabi" | "aarch64-linux-android" => {
-            _arm_exec_compiled_test(config, props, testfile, env)
+            _arm_exec_compiled_test(config, props, testpaths, env)
         }
 
         _=> {
-            let aux_dir = aux_output_dir_name(config, testfile);
+            let aux_dir = aux_output_dir_name(config, testpaths);
             compose_and_run(config,
-                            testfile,
-                            make_run_args(config, props, testfile),
+                            testpaths,
+                            make_run_args(config, props, testpaths),
                             env,
                             &config.run_lib_path,
                             Some(aux_dir.to_str().unwrap()),
@@ -1206,21 +1216,36 @@ fn exec_compiled_test(config: &Config, props: &TestProps,
     }
 }
 
+fn compute_aux_test_paths(config: &Config,
+                          testpaths: &TestPaths,
+                          rel_ab: &str)
+                          -> TestPaths
+{
+    let abs_ab = config.aux_base.join(rel_ab);
+    TestPaths {
+        file: abs_ab,
+        base: testpaths.base.clone(),
+        relative_dir: Path::new(rel_ab).parent()
+                                       .map(|p| p.to_path_buf())
+                                       .unwrap_or_else(|| PathBuf::new())
+    }
+}
+
 fn compose_and_run_compiler(config: &Config, props: &TestProps,
-                            testfile: &Path, args: ProcArgs,
+                            testpaths: &TestPaths, args: ProcArgs,
                             input: Option<String>) -> ProcRes {
     if !props.aux_builds.is_empty() {
-        ensure_dir(&aux_output_dir_name(config, testfile));
+        ensure_dir(&aux_output_dir_name(config, testpaths));
     }
 
-    let aux_dir = aux_output_dir_name(config, testfile);
+    let aux_dir = aux_output_dir_name(config, testpaths);
     // FIXME (#9639): This needs to handle non-utf8 paths
     let extra_link_args = vec!["-L".to_owned(),
                                aux_dir.to_str().unwrap().to_owned()];
 
     for rel_ab in &props.aux_builds {
-        let abs_ab = config.aux_base.join(rel_ab);
-        let aux_props = header::load_props(&abs_ab);
+        let aux_testpaths = compute_aux_test_paths(config, testpaths, rel_ab);
+        let aux_props = header::load_props(&aux_testpaths.file);
         let mut crate_type = if aux_props.no_prefer_dynamic {
             Vec::new()
         } else {
@@ -1247,13 +1272,13 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
                               &aux_props,
                               crate_type,
                               |a,b| {
-                                  let f = make_lib_name(a, b, testfile);
+                                  let f = make_lib_name(a, &b.file, testpaths);
                                   let parent = f.parent().unwrap();
                                   TargetLocation::ThisDirectory(parent.to_path_buf())
                               },
-                              &abs_ab);
+                              &aux_testpaths);
         let auxres = compose_and_run(config,
-                                     &abs_ab,
+                                     &aux_testpaths,
                                      aux_args,
                                      Vec::new(),
                                      &config.compile_lib_path,
@@ -1262,20 +1287,20 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
         if !auxres.status.success() {
             fatal_proc_rec(
                 &format!("auxiliary build of {:?} failed to compile: ",
-                        abs_ab.display()),
+                        aux_testpaths.file.display()),
                 &auxres);
         }
 
         match &*config.target {
             "arm-linux-androideabi"  | "aarch64-linux-android" => {
-                _arm_push_aux_shared_library(config, testfile);
+                _arm_push_aux_shared_library(config, testpaths);
             }
             _ => {}
         }
     }
 
     compose_and_run(config,
-                    testfile,
+                    testpaths,
                     args,
                     Vec::new(),
                     &config.compile_lib_path,
@@ -1285,16 +1310,17 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
 
 fn ensure_dir(path: &Path) {
     if path.is_dir() { return; }
-    fs::create_dir(path).unwrap();
+    fs::create_dir_all(path).unwrap();
 }
 
-fn compose_and_run(config: &Config, testfile: &Path,
+fn compose_and_run(config: &Config,
+                   testpaths: &TestPaths,
                    ProcArgs{ args, prog }: ProcArgs,
                    procenv: Vec<(String, String)> ,
                    lib_path: &str,
                    aux_path: Option<&str>,
                    input: Option<String>) -> ProcRes {
-    return program_output(config, testfile, lib_path,
+    return program_output(config, testpaths, lib_path,
                           prog, aux_path, args, procenv, input);
 }
 
@@ -1307,18 +1333,18 @@ fn make_compile_args<F>(config: &Config,
                         props: &TestProps,
                         extras: Vec<String> ,
                         xform: F,
-                        testfile: &Path)
+                        testpaths: &TestPaths)
                         -> ProcArgs where
-    F: FnOnce(&Config, &Path) -> TargetLocation,
+    F: FnOnce(&Config, &TestPaths) -> TargetLocation,
 {
-    let xform_file = xform(config, testfile);
+    let xform_file = xform(config, testpaths);
     let target = if props.force_host {
         &*config.host
     } else {
         &*config.target
     };
     // FIXME (#9639): This needs to handle non-utf8 paths
-    let mut args = vec!(testfile.to_str().unwrap().to_owned(),
+    let mut args = vec!(testpaths.file.to_str().unwrap().to_owned(),
                         "-L".to_owned(),
                         config.build_base.to_str().unwrap().to_owned(),
                         format!("--target={}", target));
@@ -1350,15 +1376,15 @@ fn make_compile_args<F>(config: &Config,
     };
 }
 
-fn make_lib_name(config: &Config, auxfile: &Path, testfile: &Path) -> PathBuf {
+fn make_lib_name(config: &Config, auxfile: &Path, testpaths: &TestPaths) -> PathBuf {
     // what we return here is not particularly important, as it
     // happens; rustc ignores everything except for the directory.
     let auxname = output_testname(auxfile);
-    aux_output_dir_name(config, testfile).join(&auxname)
+    aux_output_dir_name(config, testpaths).join(&auxname)
 }
 
-fn make_exe_name(config: &Config, testfile: &Path) -> PathBuf {
-    let mut f = output_base_name(config, testfile);
+fn make_exe_name(config: &Config, testpaths: &TestPaths) -> PathBuf {
+    let mut f = output_base_name(config, testpaths);
     // FIXME: This is using the host architecture exe suffix, not target!
     if config.target == "asmjs-unknown-emscripten" {
         let mut fname = f.file_name().unwrap().to_os_string();
@@ -1372,7 +1398,7 @@ fn make_exe_name(config: &Config, testfile: &Path) -> PathBuf {
     f
 }
 
-fn make_run_args(config: &Config, props: &TestProps, testfile: &Path)
+fn make_run_args(config: &Config, props: &TestProps, testpaths: &TestPaths)
                  -> ProcArgs {
     // If we've got another tool to run under (valgrind),
     // then split apart its command
@@ -1383,7 +1409,7 @@ fn make_run_args(config: &Config, props: &TestProps, testfile: &Path)
         args.push("nodejs".to_owned());
     }
 
-    let exe_file = make_exe_name(config, testfile);
+    let exe_file = make_exe_name(config, testpaths);
 
     // FIXME (#9639): This needs to handle non-utf8 paths
     args.push(exe_file.to_str().unwrap().to_owned());
@@ -1415,7 +1441,7 @@ fn split_maybe_args(argstr: &Option<String>) -> Vec<String> {
     }
 }
 
-fn program_output(config: &Config, testfile: &Path, lib_path: &str, prog: String,
+fn program_output(config: &Config, testpaths: &TestPaths, lib_path: &str, prog: String,
                   aux_path: Option<&str>, args: Vec<String>,
                   env: Vec<(String, String)>,
                   input: Option<String>) -> ProcRes {
@@ -1437,7 +1463,7 @@ fn program_output(config: &Config, testfile: &Path, lib_path: &str, prog: String
                      &args,
                      env,
                      input).expect(&format!("failed to exec `{}`", prog));
-    dump_output(config, testfile, &out, &err);
+    dump_output(config, testpaths, &out, &err);
     return ProcRes {
         status: Status::Normal(status),
         stdout: out,
@@ -1463,36 +1489,41 @@ fn make_cmdline(libpath: &str, prog: &str, args: &[String]) -> String {
     }
 }
 
-fn dump_output(config: &Config, testfile: &Path, out: &str, err: &str) {
-    dump_output_file(config, testfile, out, "out");
-    dump_output_file(config, testfile, err, "err");
+fn dump_output(config: &Config, testpaths: &TestPaths, out: &str, err: &str) {
+    dump_output_file(config, testpaths, out, "out");
+    dump_output_file(config, testpaths, err, "err");
     maybe_dump_to_stdout(config, out, err);
 }
 
-fn dump_output_file(config: &Config, testfile: &Path,
-                    out: &str, extension: &str) {
-    let outfile = make_out_name(config, testfile, extension);
+fn dump_output_file(config: &Config,
+                    testpaths: &TestPaths,
+                    out: &str,
+                    extension: &str) {
+    let outfile = make_out_name(config, testpaths, extension);
     File::create(&outfile).unwrap().write_all(out.as_bytes()).unwrap();
 }
 
-fn make_out_name(config: &Config, testfile: &Path, extension: &str) -> PathBuf {
-    output_base_name(config, testfile).with_extension(extension)
+fn make_out_name(config: &Config, testpaths: &TestPaths, extension: &str) -> PathBuf {
+    output_base_name(config, testpaths).with_extension(extension)
 }
 
-fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf {
-    let f = output_base_name(config, testfile);
+fn aux_output_dir_name(config: &Config, testpaths: &TestPaths) -> PathBuf {
+    let f = output_base_name(config, testpaths);
     let mut fname = f.file_name().unwrap().to_os_string();
     fname.push(&format!(".{}.libaux", config.mode));
     f.with_file_name(&fname)
 }
 
-fn output_testname(testfile: &Path) -> PathBuf {
-    PathBuf::from(testfile.file_stem().unwrap())
+fn output_testname(filepath: &Path) -> PathBuf {
+    PathBuf::from(filepath.file_stem().unwrap())
 }
 
-fn output_base_name(config: &Config, testfile: &Path) -> PathBuf {
-    config.build_base
-        .join(&output_testname(testfile))
+fn output_base_name(config: &Config, testpaths: &TestPaths) -> PathBuf {
+    let dir = config.build_base.join(&testpaths.relative_dir);
+
+    // Note: The directory `dir` is created during `collect_tests_from_dir`
+    dir
+        .join(&output_testname(&testpaths.file))
         .with_extension(&config.stage_id)
 }
 
@@ -1531,10 +1562,10 @@ stderr:\n\
 
 fn _arm_exec_compiled_test(config: &Config,
                            props: &TestProps,
-                           testfile: &Path,
+                           testpaths: &TestPaths,
                            env: Vec<(String, String)>)
                            -> ProcRes {
-    let args = make_run_args(config, props, testfile);
+    let args = make_run_args(config, props, testpaths);
     let cmdline = make_cmdline("",
                                &args.prog,
                                &args.args);
@@ -1645,7 +1676,7 @@ fn _arm_exec_compiled_test(config: &Config,
         .expect(&format!("failed to exec `{}`", config.adb_path));
 
     dump_output(config,
-                testfile,
+                testpaths,
                 &stdout_out,
                 &stderr_out);
 
@@ -1657,8 +1688,8 @@ fn _arm_exec_compiled_test(config: &Config,
     }
 }
 
-fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) {
-    let tdir = aux_output_dir_name(config, testfile);
+fn _arm_push_aux_shared_library(config: &Config, testpaths: &TestPaths) {
+    let tdir = aux_output_dir_name(config, testpaths);
 
     let dirs = fs::read_dir(&tdir).unwrap();
     for file in dirs {
@@ -1692,8 +1723,8 @@ fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) {
 // codegen tests (using FileCheck)
 
 fn compile_test_and_save_ir(config: &Config, props: &TestProps,
-                                 testfile: &Path) -> ProcRes {
-    let aux_dir = aux_output_dir_name(config, testfile);
+                                 testpaths: &TestPaths) -> ProcRes {
+    let aux_dir = aux_output_dir_name(config, testpaths);
     // FIXME (#9639): This needs to handle non-utf8 paths
     let mut link_args = vec!("-L".to_owned(),
                              aux_dir.to_str().unwrap().to_owned());
@@ -1705,34 +1736,34 @@ fn compile_test_and_save_ir(config: &Config, props: &TestProps,
                                  |a, b| TargetLocation::ThisDirectory(
                                      output_base_name(a, b).parent()
                                         .unwrap().to_path_buf()),
-                                 testfile);
-    compose_and_run_compiler(config, props, testfile, args, None)
+                                 testpaths);
+    compose_and_run_compiler(config, props, testpaths, args, None)
 }
 
-fn check_ir_with_filecheck(config: &Config, testfile: &Path) -> ProcRes {
-    let irfile = output_base_name(config, testfile).with_extension("ll");
+fn check_ir_with_filecheck(config: &Config, testpaths: &TestPaths) -> ProcRes {
+    let irfile = output_base_name(config, testpaths).with_extension("ll");
     let prog = config.llvm_bin_path.as_ref().unwrap().join("FileCheck");
     let proc_args = ProcArgs {
         // FIXME (#9639): This needs to handle non-utf8 paths
         prog: prog.to_str().unwrap().to_owned(),
         args: vec!(format!("-input-file={}", irfile.to_str().unwrap()),
-                   testfile.to_str().unwrap().to_owned())
+                   testpaths.file.to_str().unwrap().to_owned())
     };
-    compose_and_run(config, testfile, proc_args, Vec::new(), "", None, None)
+    compose_and_run(config, testpaths, proc_args, Vec::new(), "", None, None)
 }
 
-fn run_codegen_test(config: &Config, props: &TestProps, testfile: &Path) {
+fn run_codegen_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
 
     if config.llvm_bin_path.is_none() {
         fatal("missing --llvm-bin-path");
     }
 
-    let mut proc_res = compile_test_and_save_ir(config, props, testfile);
+    let mut proc_res = compile_test_and_save_ir(config, props, testpaths);
     if !proc_res.status.success() {
         fatal_proc_rec("compilation failed!", &proc_res);
     }
 
-    proc_res = check_ir_with_filecheck(config, testfile);
+    proc_res = check_ir_with_filecheck(config, testpaths);
     if !proc_res.status.success() {
         fatal_proc_rec("verification with 'FileCheck' failed",
                       &proc_res);
@@ -1750,30 +1781,30 @@ fn charset() -> &'static str {
     }
 }
 
-fn run_rustdoc_test(config: &Config, props: &TestProps, testfile: &Path) {
-    let out_dir = output_base_name(config, testfile);
+fn run_rustdoc_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+    let out_dir = output_base_name(config, testpaths);
     let _ = fs::remove_dir_all(&out_dir);
     ensure_dir(&out_dir);
 
-    let proc_res = document(config, props, testfile, &out_dir);
+    let proc_res = document(config, props, testpaths, &out_dir);
     if !proc_res.status.success() {
         fatal_proc_rec("rustdoc failed!", &proc_res);
     }
     let root = find_rust_src_root(config).unwrap();
 
     let res = cmd2procres(config,
-                          testfile,
+                          testpaths,
                           Command::new(&config.python)
                                   .arg(root.join("src/etc/htmldocck.py"))
                                   .arg(out_dir)
-                                  .arg(testfile));
+                                  .arg(&testpaths.file));
     if !res.status.success() {
         fatal_proc_rec("htmldocck failed!", &res);
     }
 }
 
-fn run_codegen_units_test(config: &Config, props: &TestProps, testfile: &Path) {
-    let proc_res = compile_test(config, props, testfile);
+fn run_codegen_units_test(config: &Config, props: &TestProps, testpaths: &TestPaths) {
+    let proc_res = compile_test(config, props, testpaths);
 
     if !proc_res.status.success() {
         fatal_proc_rec("compilation failed!", &proc_res);
@@ -1790,7 +1821,7 @@ fn run_codegen_units_test(config: &Config, props: &TestProps, testfile: &Path) {
         .map(|s| (&s[prefix.len()..]).to_string())
         .collect();
 
-    let expected: HashSet<String> = errors::load_errors(testfile)
+    let expected: HashSet<String> = errors::load_errors(&testpaths.file)
         .iter()
         .map(|e| e.msg.trim().to_string())
         .collect();
diff --git a/src/doc/book/concurrency.md b/src/doc/book/concurrency.md
index 752c0972102..30e4ad7ba5b 100644
--- a/src/doc/book/concurrency.md
+++ b/src/doc/book/concurrency.md
@@ -259,7 +259,7 @@ thread::spawn(move || {
 ```
 
 First, we call `lock()`, which acquires the mutex's lock. Because this may fail,
-it returns an `Result<T, E>`, and because this is just an example, we `unwrap()`
+it returns a `Result<T, E>`, and because this is just an example, we `unwrap()`
 it to get a reference to the data. Real code would have more robust error handling
 here. We're then free to mutate it, since we have the lock.
 
diff --git a/src/doc/book/const-and-static.md b/src/doc/book/const-and-static.md
index 7d555b52a98..b7042854bd2 100644
--- a/src/doc/book/const-and-static.md
+++ b/src/doc/book/const-and-static.md
@@ -64,16 +64,16 @@ unsafe {
 
 [unsafe]: unsafe.html
 
-Furthermore, any type stored in a `static` must be `Sync`, and may not have
+Furthermore, any type stored in a `static` must be `Sync`, and must not have
 a [`Drop`][drop] implementation.
 
 [drop]: drop.html
 
 # Initializing
 
-Both `const` and `static` have requirements for giving them a value. They may
-only be given a value that’s a constant expression. In other words, you cannot
-use the result of a function call or anything similarly complex or at runtime.
+Both `const` and `static` have requirements for giving them a value. They must
+be given a value that’s a constant expression. In other words, you cannot use 
+the result of a function call or anything similarly complex or at runtime.
 
 # Which construct should I use?
 
diff --git a/src/doc/book/guessing-game.md b/src/doc/book/guessing-game.md
index a5259e9ca4c..b9b6e9a4c95 100644
--- a/src/doc/book/guessing-game.md
+++ b/src/doc/book/guessing-game.md
@@ -258,7 +258,7 @@ done:
     io::stdin().read_line(&mut guess).expect("failed to read line");
 ```
 
-But that gets hard to read. So we’ve split it up, three lines for three method
+But that gets hard to read. So we’ve split it up, two lines for two method
 calls. We already talked about `read_line()`, but what about `expect()`? Well,
 we already mentioned that `read_line()` puts what the user types into the `&mut
 String` we pass it. But it also returns a value: in this case, an
@@ -644,7 +644,7 @@ So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
 Rust doesn’t know how to compare the `guess` and the `secret_number`. They
 need to be the same type. Ultimately, we want to convert the `String` we
 read as input into a real number type, for comparison. We can do that
-with three more lines. Here’s our new program:
+with two more lines. Here’s our new program:
 
 ```rust,ignore
 extern crate rand;
@@ -906,17 +906,17 @@ let guess: u32 = match guess.trim().parse() {
     Err(_) => continue,
 };
 ```
-
 This is how you generally move from ‘crash on error’ to ‘actually handle the
-error’, by switching from `expect()` to a `match` statement. The `Result`
-returned by `parse()` is an `enum`  like `Ordering`, but in this case, each
-variant has some data associated with it: `Ok` is a success, and `Err` is a
+error’, by switching from `expect()` to a `match` statement. A `Result` is
+returned by `parse()`, this is an `enum`  like `Ordering`, but in this case,
+each variant has some data associated with it: `Ok` is a success, and `Err` is a
 failure. Each contains more information: the successfully parsed integer, or an
-error type. In this case, we `match` on `Ok(num)`, which sets the inner value
-of the `Ok` to the name `num`, and then we  return it on the right-hand
-side. In the `Err` case, we don’t care what kind of error it is, so we
-use `_` instead of a name. This ignores the error, and `continue` causes us
-to go to the next iteration of the `loop`.
+error type. In this case, we `match` on `Ok(num)`, which sets the name `num` to
+the unwrapped `Ok` value (ythe integer), and then we  return it on the
+right-hand side. In the `Err` case, we don’t care what kind of error it is, so
+we just use the catch all `_` instead of a name. This catches everything that
+isn't `Ok`, and `continue` lets us move to the next iteration of the loop; in
+effect, this enables us to ignore all errors and continue with our program.
 
 Now we should be good! Let’s try:
 
diff --git a/src/doc/book/iterators.md b/src/doc/book/iterators.md
index 5622326d20c..0c4f8041266 100644
--- a/src/doc/book/iterators.md
+++ b/src/doc/book/iterators.md
@@ -311,10 +311,12 @@ for i in (1..100).filter(|&x| x % 2 == 0) {
 ```
 
 This will print all of the even numbers between one and a hundred.
-(Note that because `filter` doesn't consume the elements that are
-being iterated over, it is passed a reference to each element, and
-thus the filter predicate uses the `&x` pattern to extract the integer
-itself.)
+(Note that, unlike `map`, the closure passed to `filter` is passed a reference
+to the element instead of the element itself. The filter predicate here uses
+the `&x` pattern to extract the integer. The filter closure is passed a
+reference because it returns `true` or `false` instead of the element,
+so the `filter` implementation must retain ownership to put the elements
+into the newly constructed iterator.)
 
 You can chain all three things together: start with an iterator, adapt it
 a few times, and then consume the result. Check it out:
diff --git a/src/doc/book/ownership.md b/src/doc/book/ownership.md
index 175960f67b6..70d71c14ddf 100644
--- a/src/doc/book/ownership.md
+++ b/src/doc/book/ownership.md
@@ -124,21 +124,65 @@ special annotation here, it’s the default thing that Rust does.
 ## The details
 
 The reason that we cannot use a binding after we’ve moved it is subtle, but
-important. When we write code like this:
+important. 
+
+When we write code like this:
+
+```rust
+let x = 10;
+```
+
+Rust allocates memory for an integer [i32] on the [stack][sh], copies the bit
+pattern representing the value of 10 to the allocated memory and binds the
+variable name x to this memory region for future reference.
+
+Now consider the following code fragment:
 
 ```rust
 let v = vec![1, 2, 3];
 
-let v2 = v;
+let mut v2 = v;
+```
+
+The first line allocates memory for the vector object `v` on the stack like
+it does for `x` above. But in addition to that it also allocates some memory
+on the [heap][sh] for the actual data (`[1, 2, 3]`). Rust copies the address
+of this heap allocation to an internal pointer, which is part of the vector
+object placed on the stack (let's call it the data pointer). 
+
+It is worth pointing out (even at the risk of stating the obvious) that the
+vector object and its data live in separate memory regions instead of being a
+single contiguous memory allocation (due to reasons we will not go into at
+this point of time). These two parts of the vector (the one on the stack and
+one on the heap) must agree with each other at all times with regards to
+things like the length, capacity etc.
+
+When we move `v` to `v2`, Rust actually does a bitwise copy of the vector
+object `v` into the stack allocation represented by `v2`. This shallow copy
+does not create a copy of the heap allocation containing the actual data.
+Which means that there would be two pointers to the contents of the vector
+both pointing to the same memory allocation on the heap. It would violate
+Rust’s safety guarantees by introducing a data race if one could access both
+`v` and `v2` at the same time. 
+
+For example if we truncated the vector to just two elements through `v2`:
+
+```rust
+# let v = vec![1, 2, 3];
+# let mut v2 = v;
+v2.truncate(2);
 ```
 
-The first line allocates memory for the vector object, `v`, and for the data it
-contains. The vector object is stored on the [stack][sh] and contains a pointer
-to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`,
-it creates a copy of that pointer, for `v2`. Which means that there would be two
-pointers to the content of the vector on the heap. It would violate Rust’s
-safety guarantees by introducing a data race. Therefore, Rust forbids using `v`
-after we’ve done the move.
+and `v1` were still accessible we'd end up with an invalid vector since `v1`
+would not know that the heap data has been truncated. Now, the part of the
+vector `v1` on the stack does not agree with the corresponding part on the
+heap. `v1` still thinks there are three elements in the vector and will
+happily let us access the non existent element `v1[2]` but as you might
+already know this is a recipe for disaster. Especially because it might lead
+to a segmentation fault or worse allow an unauthorized user to read from
+memory to which they don't have access.
+
+This is why Rust forbids using `v` after we’ve done the move.
 
 [sh]: the-stack-and-the-heap.html
 
diff --git a/src/doc/book/patterns.md b/src/doc/book/patterns.md
index 6fd7f4cd475..7325d448962 100644
--- a/src/doc/book/patterns.md
+++ b/src/doc/book/patterns.md
@@ -303,7 +303,7 @@ struct Person {
 }
 
 let name = "Steve".to_string();
-let mut x: Option<Person> = Some(Person { name: Some(name) });
+let x: Option<Person> = Some(Person { name: Some(name) });
 match x {
     Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
     _ => {}
diff --git a/src/doc/book/using-rust-without-the-standard-library.md b/src/doc/book/using-rust-without-the-standard-library.md
index 2c7a097fe80..1179aebe54c 100644
--- a/src/doc/book/using-rust-without-the-standard-library.md
+++ b/src/doc/book/using-rust-without-the-standard-library.md
@@ -25,7 +25,7 @@ Much of the functionality that’s exposed in the standard library is also
 available via the [`core` crate](../core/). When we’re using the standard
 library, Rust automatically brings `std` into scope, allowing you to use
 its features without an explicit import. By the same token, when using
-`!#[no_std]`, Rust will bring `core` into scope for you, as well as [its
+`#![no_std]`, Rust will bring `core` into scope for you, as well as [its
 prelude](../core/prelude/v1/). This means that a lot of code will Just Work:
 
 ```rust
diff --git a/src/doc/book/vectors.md b/src/doc/book/vectors.md
index b09735c3fee..f5a543d75b1 100644
--- a/src/doc/book/vectors.md
+++ b/src/doc/book/vectors.md
@@ -11,8 +11,8 @@ let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>
 ```
 
 (Notice that unlike the `println!` macro we’ve used in the past, we use square
-brackets `[]` with `vec!` macro. Rust allows you to use either in either situation,
-this is just convention.)
+brackets `[]` with `vec!` macro. Rust allows you to use either in either
+situation, this is just convention.)
 
 There’s an alternate form of `vec!` for repeating an initial value:
 
@@ -20,6 +20,12 @@ There’s an alternate form of `vec!` for repeating an initial value:
 let v = vec![0; 10]; // ten zeroes
 ```
 
+Vectors store their contents as contiguous arrays of `T` on the heap. This means
+that they must be able to know the size of `T` at compile time (that is, how
+many bytes are needed to store a `T`?). The size of some things can't be known
+at compile time. For these you'll have to store a pointer to that thing:
+thankfully, the [`Box`][box] type works perfectly for this.
+
 ## Accessing elements
 
 To get the value at a particular index in the vector, we use `[]`s:
@@ -113,6 +119,7 @@ Vectors have many more useful methods, which you can read about in [their
 API documentation][vec].
 
 [vec]: ../std/vec/index.html
+[box]: ../std/boxed/index.html
 [generic]: generics.html
 [panic]: concurrency.html#panics
 [get]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get
diff --git a/src/doc/nomicon/other-reprs.md b/src/doc/nomicon/other-reprs.md
index 2639c1d4d6f..b124f3ffc46 100644
--- a/src/doc/nomicon/other-reprs.md
+++ b/src/doc/nomicon/other-reprs.md
@@ -57,7 +57,7 @@ These reprs have no effect on a struct.
 
 # repr(packed)
 
-`repr(packed)` forces rust to strip any padding, and only align the type to a
+`repr(packed)` forces Rust to strip any padding, and only align the type to a
 byte. This may improve the memory footprint, but will likely have other negative
 side-effects.
 
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 19c9b571a33..6fb8de78094 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -236,6 +236,8 @@ following forms:
 * A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
   (`r`), or `U+0074` (`t`), denoting the Unicode values `U+000A` (LF),
   `U+000D` (CR) or `U+0009` (HT) respectively.
+* The _null escape_ is the character `U+0030` (`0`) and denotes the Unicode
+  value `U+0000` (NUL).
 * The _backslash escape_ is the character `U+005C` (`\`) which must be
   escaped in order to denote *itself*.
 
@@ -297,6 +299,8 @@ following forms:
 * A _whitespace escape_ is one of the characters `U+006E` (`n`), `U+0072`
   (`r`), or `U+0074` (`t`), denoting the bytes values `0x0A` (ASCII LF),
   `0x0D` (ASCII CR) or `0x09` (ASCII HT) respectively.
+* The _null escape_ is the character `U+0030` (`0`) and denotes the byte
+  value `0x00` (ASCII NUL).
 * The _backslash escape_ is the character `U+005C` (`\`) which must be
   escaped in order to denote its ASCII encoding `0x5C`.
 
@@ -841,8 +845,8 @@ extern crate std as ruststd; // linking to 'std' under another name
 
 A _use declaration_ creates one or more local name bindings synonymous with
 some other [path](#paths). Usually a `use` declaration is used to shorten the
-path required to refer to a module item. These declarations may appear at the
-top of [modules](#modules) and [blocks](grammar.html#block-expressions).
+path required to refer to a module item. These declarations may appear in
+[modules](#modules) and [blocks](grammar.html#block-expressions), usually at the top.
 
 > **Note**: Unlike in many languages,
 > `use` declarations in Rust do *not* declare linkage dependency with external crates.
@@ -1137,7 +1141,6 @@ the list of fields entirely. Such a struct implicitly defines a constant of
 its type with the same name. For example:
 
 ```
-# #![feature(braced_empty_structs)]
 struct Cookie;
 let c = [Cookie, Cookie {}, Cookie, Cookie {}];
 ```
@@ -1145,7 +1148,6 @@ let c = [Cookie, Cookie {}, Cookie, Cookie {}];
 is equivalent to
 
 ```
-# #![feature(braced_empty_structs)]
 struct Cookie {}
 const Cookie: Cookie = Cookie {};
 let c = [Cookie, Cookie {}, Cookie, Cookie {}];
@@ -1764,7 +1766,7 @@ pub mod submodule {
 # fn main() {}
 ```
 
-For a rust program to pass the privacy checking pass, all paths must be valid
+For a Rust program to pass the privacy checking pass, all paths must be valid
 accesses given the two rules above. This includes all use statements,
 expressions, types, etc.
 
@@ -2381,7 +2383,6 @@ The currently implemented features of the reference compiler are:
                               terms of encapsulation).
 * - `default_type_parameter_fallback` - Allows type parameter defaults to
                                         influence type inference.
-* - `braced_empty_structs` - Allows use of empty structs and enum variants with braces.
 
 * - `stmt_expr_attributes` - Allows attributes on expressions and
                              non-item statements.
@@ -3036,7 +3037,7 @@ the case of a `while` loop, the head is the conditional expression controlling
 the loop. In the case of a `for` loop, the head is the call-expression
 controlling the loop. If the label is present, then `continue 'foo` returns
 control to the head of the loop with label `'foo`, which need not be the
-innermost label enclosing the `break` expression, but must enclose it.
+innermost label enclosing the `continue` expression, but must enclose it.
 
 A `continue` expression is only permitted in the body of a loop.
 
@@ -3564,8 +3565,9 @@ Each instance of a trait object includes:
    each method of `SomeTrait` that `T` implements, a pointer to `T`'s
    implementation (i.e. a function pointer).
 
-The purpose of trait objects is to permit "late binding" of methods. A call to
-a method on a trait object is only resolved to a vtable entry at compile time.
+The purpose of trait objects is to permit "late binding" of methods. Calling a
+method on a trait object results in virtual dispatch at runtime: that is, a
+function pointer is loaded from the trait object vtable and invoked indirectly.
 The actual implementation for each vtable entry can vary on an object-by-object
 basis.
 
@@ -4060,7 +4062,7 @@ the guarantee that these issues are never caused by safe code.
 * Breaking the [pointer aliasing
   rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
   with raw pointers (a subset of the rules used by C)
-* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
+* `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T`
   contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
   guarantees.
 * Mutating non-mutable data (that is, data reached through a shared reference or
diff --git a/src/error-index-generator/main.rs b/src/error_index_generator/main.rs
index db9dd006f3c..db9dd006f3c 100644
--- a/src/error-index-generator/main.rs
+++ b/src/error_index_generator/main.rs
diff --git a/src/etc/licenseck.py b/src/etc/licenseck.py
index 889b2c95a7e..aa2a00beae5 100644
--- a/src/etc/licenseck.py
+++ b/src/etc/licenseck.py
@@ -9,6 +9,7 @@
 # except according to those terms.
 
 import re
+import os
 
 license_re = re.compile(
 u"""(#|//) Copyright .* The Rust Project Developers. See the COPYRIGHT
@@ -40,8 +41,9 @@ exceptions = [
 ]
 
 def check_license(name, contents):
+    name = os.path.normpath(name)
     # Whitelist check
-    if any(name.endswith(e) for e in exceptions):
+    if any(name.endswith(os.path.normpath(e)) for e in exceptions):
         return True
 
     # Xfail check
diff --git a/src/etc/maketest.py b/src/etc/maketest.py
index 1687838289b..c7d17b23bff 100644
--- a/src/etc/maketest.py
+++ b/src/etc/maketest.py
@@ -57,6 +57,7 @@ putenv('S', os.path.abspath(sys.argv[13]))
 putenv('RUSTFLAGS', sys.argv[15])
 putenv('LLVM_COMPONENTS', sys.argv[16])
 putenv('LLVM_CXXFLAGS', sys.argv[17])
+putenv('CXX', sys.argv[18])
 putenv('PYTHON', sys.executable)
 os.putenv('TARGET', target_triple)
 
diff --git a/src/etc/tidy.py b/src/etc/tidy.py
index fd3f4bf0b13..ce774d31b08 100644
--- a/src/etc/tidy.py
+++ b/src/etc/tidy.py
@@ -24,6 +24,15 @@ linelength_flag = "ignore-tidy-linelength"
 
 interesting_files = ['.rs', '.py', '.js', '.sh', '.c', '.h']
 uninteresting_files = ['miniz.c', 'jquery', 'rust_android_dummy']
+stable_whitelist = {
+    'src/bootstrap',
+    'src/build_helper',
+    'src/libcollectionstest',
+    'src/libcore',
+    'src/libstd',
+    'src/rustc/std_shim',
+    'src/test'
+}
 
 
 def report_error_name_no(name, no, s):
@@ -93,6 +102,7 @@ count_other_linted_files = 0
 file_counts = {ext: 0 for ext in interesting_files}
 
 all_paths = set()
+needs_unstable_attr = set()
 
 try:
     for (dirpath, dirnames, filenames) in os.walk(src_dir):
@@ -112,7 +122,8 @@ try:
             'src/liblibc',
         }
 
-        if any(d in dirpath for d in skippable_dirs):
+        dirpath = os.path.normpath(dirpath)
+        if any(os.path.normpath(d) in dirpath for d in skippable_dirs):
             continue
 
         file_names = [os.path.join(dirpath, f) for f in filenames
@@ -149,6 +160,9 @@ try:
                 else:
                     if "SNAP " in line:
                         report_warn("unmatched SNAP line: " + line)
+                search = re.search(r'^#!\[unstable', line)
+                if search:
+                    needs_unstable_attr.discard(filename)
 
             if cr_flag in line:
                 check_cr = False
@@ -181,6 +195,9 @@ try:
                 check_cr = True
                 check_tab = True
                 check_linelength = True
+                if all(f not in filename for f in stable_whitelist) and \
+                   re.search(r'src/.*/lib\.rs', filename):
+                    needs_unstable_attr.add(filename)
 
             # Put a reasonable limit on the amount of header data we use for
             # the licenseck
@@ -195,6 +212,8 @@ try:
         update_counts(current_name)
         assert len(current_contents) > 0
         do_license_check(current_name, current_contents)
+    for f in needs_unstable_attr:
+        report_error_name_no(f, 1, "requires unstable attribute")
 
 except UnicodeDecodeError as e:
     report_err("UTF-8 decoding error " + str(e))
diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
index 5af8d9e8e27..5da0f1a10b9 100644
--- a/src/liballoc/Cargo.toml
+++ b/src/liballoc/Cargo.toml
@@ -10,5 +10,3 @@ test = false
 
 [dependencies]
 core = { path = "../libcore" }
-libc = { path = "../rustc/libc_shim" }
-alloc_system = { path = "../liballoc_system" }
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 1438103d7f6..300142d5ec1 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -78,7 +78,6 @@
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(custom_attribute)]
-#![feature(drop_in_place)]
 #![feature(dropck_parametricity)]
 #![feature(fundamental)]
 #![feature(lang_items)]
@@ -92,16 +91,9 @@
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(unsize)]
 
-// Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
-// might be unavailable or disabled
-#![cfg_attr(stage0, feature(alloc_system))]
-
 #![cfg_attr(not(test), feature(raw, fn_traits, placement_new_protocol))]
 #![cfg_attr(test, feature(test, rustc_private, box_heap))]
 
-#[cfg(stage0)]
-extern crate alloc_system;
-
 // Allow testing this library
 
 #[cfg(test)]
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index bda001eb4f4..c96d303e6bb 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -45,19 +45,19 @@ extern {}
 // explicitly request it), and on Android we explicitly request it as
 // unprefixing cause segfaults (mismatches in allocators).
 extern {
-    #[cfg_attr(any(target_os = "macos", target_os = "android"),
+    #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios"),
                link_name = "je_mallocx")]
     fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
-    #[cfg_attr(any(target_os = "macos", target_os = "android"),
+    #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios"),
                link_name = "je_rallocx")]
     fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
-    #[cfg_attr(any(target_os = "macos", target_os = "android"),
+    #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios"),
                link_name = "je_xallocx")]
     fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
-    #[cfg_attr(any(target_os = "macos", target_os = "android"),
+    #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios"),
                link_name = "je_sdallocx")]
     fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
-    #[cfg_attr(any(target_os = "macos", target_os = "android"),
+    #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios"),
                link_name = "je_nallocx")]
     fn nallocx(size: size_t, flags: c_int) -> size_t;
 }
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 46a63390c83..cb1107fb650 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -31,7 +31,6 @@
 
 #![feature(alloc)]
 #![feature(core_intrinsics)]
-#![feature(drop_in_place)]
 #![feature(heap_api)]
 #![feature(raw)]
 #![feature(heap_api)]
diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs
index f174cc09bcd..ce20a25d13a 100644
--- a/src/libcollections/borrow.rs
+++ b/src/libcollections/borrow.rs
@@ -95,12 +95,12 @@ pub enum Cow<'a, B: ?Sized + 'a>
 {
     /// Borrowed data.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Borrowed(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a B),
+    Borrowed(#[stable(feature = "rust1", since = "1.0.0")] &'a B),
 
     /// Owned data.
     #[stable(feature = "rust1", since = "1.0.0")]
     Owned(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] <B as ToOwned>::Owned
+        #[stable(feature = "rust1", since = "1.0.0")] <B as ToOwned>::Owned
     ),
 }
 
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 0ced4e1952a..2a950ce0ab7 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -238,13 +238,13 @@ pub enum Entry<'a, K: 'a, V: 'a> {
     /// A vacant Entry
     #[stable(feature = "rust1", since = "1.0.0")]
     Vacant(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] VacantEntry<'a, K, V>
+        #[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>
     ),
 
     /// An occupied Entry
     #[stable(feature = "rust1", since = "1.0.0")]
     Occupied(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] OccupiedEntry<'a, K, V>
+        #[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>
     ),
 }
 
@@ -375,9 +375,10 @@ impl<K: Ord, V> BTreeMap<K, V> {
     ///
     /// If the map did not have this key present, `None` is returned.
     ///
-    /// If the map did have this key present, the key is not updated, the
-    /// value is updated and the old value is returned.
-    /// See the [module-level documentation] for more.
+    /// If the map did have this key present, the value is updated, and the old
+    /// value is returned. The key is not updated, though; this matters for
+    /// types that can be `==` without being identical. See the [module-level
+    /// documentation] for more.
     ///
     /// [module-level documentation]: index.html#insert-and-complex-keys
     ///
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index b98637d92b4..373fe7dc4c1 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -27,6 +27,7 @@
        test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
 
 #![cfg_attr(test, allow(deprecated))] // rand
+#![cfg_attr(not(test), feature(copy_from_slice))] // impl [T]
 #![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(alloc)]
@@ -34,7 +35,6 @@
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
 #![feature(decode_utf16)]
-#![feature(drop_in_place)]
 #![feature(dropck_parametricity)]
 #![feature(fmt_internals)]
 #![feature(fmt_radix)]
@@ -45,6 +45,8 @@
 #![feature(nonzero)]
 #![feature(num_bits_bytes)]
 #![feature(pattern)]
+#![feature(placement_in)]
+#![feature(placement_new_protocol)]
 #![feature(shared)]
 #![feature(slice_bytes)]
 #![feature(slice_patterns)]
diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs
index 654dae27e74..cb669a9bf9e 100644
--- a/src/libcollections/linked_list.rs
+++ b/src/libcollections/linked_list.rs
@@ -21,13 +21,14 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use alloc::boxed::Box;
+use alloc::boxed::{Box, IntermediateBox};
 use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{Hasher, Hash};
 use core::iter::FromIterator;
 use core::mem;
-use core::ptr::Shared;
+use core::ops::{BoxPlace, InPlace, Place, Placer};
+use core::ptr::{self, Shared};
 
 /// A doubly-linked list.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -660,6 +661,56 @@ impl<T> LinkedList<T> {
 
         second_part
     }
+
+    /// Returns a place for insertion at the front of the list.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_front`]
+    /// (#method.push_front), but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut list = LinkedList::new();
+    /// list.front_place() <- 2;
+    /// list.front_place() <- 4;
+    /// assert!(list.iter().eq(&[4, 2]));
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "method name and placement protocol are subject to change",
+               issue = "30172")]
+    pub fn front_place(&mut self) -> FrontPlace<T> {
+        FrontPlace { list: self, node: IntermediateBox::make_place() }
+    }
+
+    /// Returns a place for insertion at the back of the list.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back),
+    /// but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut list = LinkedList::new();
+    /// list.back_place() <- 2;
+    /// list.back_place() <- 4;
+    /// assert!(list.iter().eq(&[2, 4]));
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "method name and placement protocol are subject to change",
+               issue = "30172")]
+    pub fn back_place(&mut self) -> BackPlace<T> {
+        BackPlace { list: self, node: IntermediateBox::make_place() }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -984,6 +1035,101 @@ impl<A: Hash> Hash for LinkedList<A> {
     }
 }
 
+unsafe fn finalize<T>(node: IntermediateBox<Node<T>>) -> Box<Node<T>> {
+    let mut node = node.finalize();
+    ptr::write(&mut node.next, None);
+    ptr::write(&mut node.prev, Rawlink::none());
+    node
+}
+
+/// A place for insertion at the front of a `LinkedList`.
+///
+/// See [`LinkedList::front_place`](struct.LinkedList.html#method.front_place) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+pub struct FrontPlace<'a, T: 'a> {
+    list: &'a mut LinkedList<T>,
+    node: IntermediateBox<Node<T>>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for FrontPlace<'a, T> {
+    type Place = Self;
+
+    fn make_place(self) -> Self {
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for FrontPlace<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        unsafe { &mut (*self.node.pointer()).value }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for FrontPlace<'a, T> {
+    type Owner = ();
+
+    unsafe fn finalize(self) {
+        let FrontPlace { list, node } = self;
+        list.push_front_node(finalize(node));
+    }
+}
+
+/// A place for insertion at the back of a `LinkedList`.
+///
+/// See [`LinkedList::back_place`](struct.LinkedList.html#method.back_place) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+pub struct BackPlace<'a, T: 'a> {
+    list: &'a mut LinkedList<T>,
+    node: IntermediateBox<Node<T>>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for BackPlace<'a, T> {
+    type Place = Self;
+
+    fn make_place(self) -> Self {
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for BackPlace<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        unsafe { &mut (*self.node.pointer()).value }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for BackPlace<'a, T> {
+    type Owner = ();
+
+    unsafe fn finalize(self) {
+        let BackPlace { list, node } = self;
+        list.push_back_node(finalize(node));
+    }
+}
+
 // Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
 #[allow(dead_code)]
 fn assert_covariance() {
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 6252e4888eb..1446d00b9ea 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -407,7 +407,7 @@ impl<T> [T] {
     }
 
     /// Returns an iterator over `size` elements of the slice at a
-    /// time. The chunks do not overlap. If `size` does not divide the
+    /// time. The chunks are slices and do not overlap. If `size` does not divide the
     /// length of the slice, then the last chunk will not have length
     /// `size`.
     ///
@@ -433,7 +433,7 @@ impl<T> [T] {
     }
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
-    /// The chunks are mutable and do not overlap. If `chunk_size` does
+    /// The chunks are mutable slices, and do not overlap. If `chunk_size` does
     /// not divide the length of the slice, then the last chunk will not
     /// have length `chunk_size`.
     ///
@@ -837,6 +837,30 @@ impl<T> [T] {
         core_slice::SliceExt::clone_from_slice(self, src)
     }
 
+    /// Copies all elements from `src` into `self`, using a memcpy.
+    ///
+    /// The length of `src` must be the same as `self`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// #![feature(copy_from_slice)]
+    /// let mut dst = [0, 0, 0];
+    /// let src = [1, 2, 3];
+    ///
+    /// dst.copy_from_slice(&src);
+    /// assert_eq!(src, dst);
+    /// ```
+    #[unstable(feature = "copy_from_slice", issue = "31755")]
+    pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
+        core_slice::SliceExt::copy_from_slice(self, src)
+    }
+
+
     /// Copies `self` into a new `Vec`.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index 89b5e5b3075..a30ec452e3c 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -112,17 +112,22 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
     }
 }
 
+/// Deprecated, renamed to EncodeUtf16
+#[unstable(feature = "str_utf16", issue = "27714")]
+#[rustc_deprecated(since = "1.8.0", reason = "renamed to EncodeUtf16")]
+pub type Utf16Units<'a> = EncodeUtf16<'a>;
+
 /// External iterator for a string's UTF-16 code units.
 ///
 /// For use with the `std::iter` module.
 #[derive(Clone)]
-#[unstable(feature = "str_utf16", issue = "27714")]
-pub struct Utf16Units<'a> {
+#[stable(feature = "encode_utf16", since = "1.8.0")]
+pub struct EncodeUtf16<'a> {
     encoder: Utf16Encoder<Chars<'a>>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Iterator for Utf16Units<'a> {
+impl<'a> Iterator for EncodeUtf16<'a> {
     type Item = u16;
 
     #[inline]
@@ -267,9 +272,11 @@ impl str {
     /// Converts a string slice to a raw pointer.
     ///
     /// As string slices are a slice of bytes, the raw pointer points to a
-    /// `u8`. This pointer will be pointing to the first byte of the string
+    /// [`u8`]. This pointer will be pointing to the first byte of the string
     /// slice.
     ///
+    /// [`u8`]: primitive.u8.html
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -661,7 +668,7 @@ impl str {
     /// assert_eq!(None, chars.next());
     /// ```
     ///
-    /// Remember, `char`s may not match your human intuition about characters:
+    /// Remember, [`char`]s may not match your human intuition about characters:
     ///
     /// ```
     /// let y = "y̆";
@@ -678,16 +685,18 @@ impl str {
     pub fn chars(&self) -> Chars {
         core_str::StrExt::chars(self)
     }
-    /// Returns an iterator over the `char`s of a string slice, and their
+    /// Returns an iterator over the [`char`]s of a string slice, and their
     /// positions.
     ///
     /// As a string slice consists of valid UTF-8, we can iterate through a
-    /// string slice by `char`. This method returns an iterator of both
-    /// these `char`s, as well as their byte positions.
+    /// string slice by [`char`]. This method returns an iterator of both
+    /// these [`char`]s, as well as their byte positions.
     ///
-    /// The iterator yields tuples. The position is first, the `char` is
+    /// The iterator yields tuples. The position is first, the [`char`] is
     /// second.
     ///
+    /// [`char`]: primitive.char.html
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -711,7 +720,7 @@ impl str {
     /// assert_eq!(None, char_indices.next());
     /// ```
     ///
-    /// Remember, `char`s may not match your human intuition about characters:
+    /// Remember, [`char`]s may not match your human intuition about characters:
     ///
     /// ```
     /// let y = "y̆";
@@ -849,10 +858,18 @@ impl str {
     #[unstable(feature = "str_utf16",
                reason = "this functionality may only be provided by libunicode",
                issue = "27714")]
+    #[rustc_deprecated(since = "1.8.0", reason = "renamed to encode_utf16")]
+    #[allow(deprecated)]
     pub fn utf16_units(&self) -> Utf16Units {
         Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) }
     }
 
+    /// Returns an iterator of `u16` over the string encoded as UTF-16.
+    #[stable(feature = "encode_utf16", since = "1.8.0")]
+    pub fn encode_utf16(&self) -> EncodeUtf16 {
+        EncodeUtf16 { encoder: Utf16Encoder::new(self[..].chars()) }
+    }
+
     /// Returns `true` if the given pattern matches a sub-slice of
     /// this string slice.
     ///
@@ -918,12 +935,13 @@ impl str {
     /// Returns the byte index of the first character of this string slice that
     /// matches the pattern.
     ///
-    /// Returns `None` if the pattern doesn't match.
+    /// Returns [`None`] if the pattern doesn't match.
     ///
     /// The pattern can be a `&str`, [`char`], or a closure that determines if
     /// a character matches.
     ///
     /// [`char`]: primitive.char.html
+    /// [`None`]: option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -962,12 +980,13 @@ impl str {
     /// Returns the byte index of the last character of this string slice that
     /// matches the pattern.
     ///
-    /// Returns `None` if the pattern doesn't match.
+    /// Returns [`None`] if the pattern doesn't match.
     ///
     /// The pattern can be a `&str`, [`char`], or a closure that determines if
     /// a character matches.
     ///
     /// [`char`]: primitive.char.html
+    /// [`None`]: option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -1187,14 +1206,18 @@ impl str {
     /// An iterator over substrings of `self`, separated by characters
     /// matched by a pattern and yielded in reverse order.
     ///
-    /// The pattern can be a simple `&str`, `char`, or a closure that
+    /// The pattern can be a simple `&str`, [`char`], or a closure that
     /// determines the split.
     /// Additional libraries might provide more complex patterns like
     /// regular expressions.
     ///
-    /// Equivalent to `split`, except that the trailing substring is
+    /// [`char`]: primitive.char.html
+    ///
+    /// Equivalent to [`split()`], except that the trailing substring is
     /// skipped if empty.
     ///
+    /// [`split()`]: #method.split
+    ///
     /// This method can be used for string data that is _terminated_,
     /// rather than _separated_ by a pattern.
     ///
@@ -1457,7 +1480,7 @@ impl str {
     /// # Iterator behavior
     ///
     /// The returned iterator requires that the pattern supports a reverse
-    /// search, and it will be a `[DoubleEndedIterator]` if a forward/reverse
+    /// search, and it will be a [`DoubleEndedIterator`] if a forward/reverse
     /// search yields the same elements.
     ///
     /// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
@@ -1694,9 +1717,11 @@ impl str {
     ///
     /// # Errors
     ///
-    /// Will return `Err` if it's not possible to parse this string slice into
+    /// Will return [`Err`] if it's not possible to parse this string slice into
     /// the desired type.
     ///
+    /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
+    ///
     /// # Example
     ///
     /// Basic usage
@@ -1707,7 +1732,7 @@ impl str {
     /// assert_eq!(4, four);
     /// ```
     ///
-    /// Using the 'turbofish' instead of annotationg `four`:
+    /// Using the 'turbofish' instead of annotating `four`:
     ///
     /// ```
     /// let four = "4".parse::<u32>();
@@ -1765,11 +1790,13 @@ impl str {
         result
     }
 
-    /// Returns the lowercase equivalent of this string slice, as a new `String`.
+    /// Returns the lowercase equivalent of this string slice, as a new [`String`].
     ///
     /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
     /// `Lowercase`.
     ///
+    /// [`String`]: string/struct.String.html
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1839,11 +1866,13 @@ impl str {
         }
     }
 
-    /// Returns the uppercase equivalent of this string slice, as a new `String`.
+    /// Returns the uppercase equivalent of this string slice, as a new [`String`].
     ///
     /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property
     /// `Uppercase`.
     ///
+    /// [`String`]: string/struct.String.html
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1884,7 +1913,9 @@ impl str {
         self.chars().flat_map(|c| c.escape_unicode()).collect()
     }
 
-    /// Converts a `Box<str>` into a `String` without copying or allocating.
+    /// Converts a `Box<str>` into a [`String`] without copying or allocating.
+    ///
+    /// [`String`]: string/struct.String.html
     ///
     /// # Examples
     ///
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 1bc9e6588ad..ae442e155c0 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! A growable list type with heap-allocated contents, written `Vec<T>` but
-//! pronounced 'vector.'
+//! A contiguous growable array type with heap-allocated contents, written
+//! `Vec<T>` but pronounced 'vector.'
 //!
 //! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and
 //! `O(1)` pop (from the end).
@@ -59,9 +59,10 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use alloc::raw_vec::RawVec;
 use alloc::boxed::Box;
 use alloc::heap::EMPTY;
+use alloc::raw_vec::RawVec;
+use borrow::ToOwned;
 use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{self, Hash};
@@ -78,7 +79,7 @@ use borrow::{Cow, IntoCow};
 
 use super::range::RangeArgument;
 
-/// A growable list type, written `Vec<T>` but pronounced 'vector.'
+/// A contiguous growable array type, written `Vec<T>` but pronounced 'vector.'
 ///
 /// # Examples
 ///
@@ -134,6 +135,49 @@ use super::range::RangeArgument;
 /// }
 /// ```
 ///
+/// # Indexing
+///
+/// The Vec type allows to access values by index, because it implements the
+/// `Index` trait. An example will be more explicit:
+///
+/// ```
+/// let v = vec!(0, 2, 4, 6);
+/// println!("{}", v[1]); // it will display '2'
+/// ```
+///
+/// However be careful: if you try to access an index which isn't in the Vec,
+/// your software will panic! You cannot do this:
+///
+/// ```ignore
+/// let v = vec!(0, 2, 4, 6);
+/// println!("{}", v[6]); // it will panic!
+/// ```
+///
+/// In conclusion: always check if the index you want to get really exists
+/// before doing it.
+///
+/// # Slicing
+///
+/// A Vec can be mutable. Slices, on the other hand, are read-only objects.
+/// To get a slice, use "&". Example:
+///
+/// ```
+/// fn read_slice(slice: &[usize]) {
+///     // ...
+/// }
+///
+/// let v = vec!(0, 1);
+/// read_slice(&v);
+///
+/// // ... and that's all!
+/// // you can also do it like this:
+/// let x : &[usize] = &v;
+/// ```
+///
+/// In Rust, it's more common to pass slices as arguments rather than vectors
+/// when you just want to provide a read access. The same goes for String and
+/// &str.
+///
 /// # Capacity and reallocation
 ///
 /// The capacity of a vector is the amount of space allocated for any future
@@ -1633,6 +1677,15 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
+#[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
+impl<T: Clone> Clone for IntoIter<T> {
+    fn clone(&self) -> IntoIter<T> {
+        unsafe {
+            slice::from_raw_parts(self.ptr, self.len()).to_owned().into_iter()
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for IntoIter<T> {
     #[unsafe_destructor_blind_to_params]
diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs
index 891ca22265e..eed530d8b61 100644
--- a/src/libcollectionstest/lib.rs
+++ b/src/libcollectionstest/lib.rs
@@ -16,6 +16,7 @@
 #![feature(btree_range)]
 #![feature(collections)]
 #![feature(collections_bound)]
+#![feature(copy_from_slice)]
 #![feature(const_fn)]
 #![feature(fn_traits)]
 #![feature(enumset)]
@@ -28,7 +29,6 @@
 #![feature(step_by)]
 #![feature(str_char)]
 #![feature(str_escape)]
-#![feature(str_utf16)]
 #![feature(test)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs
index cde7fcaaf51..f3bb58ba45b 100644
--- a/src/libcollectionstest/slice.rs
+++ b/src/libcollectionstest/slice.rs
@@ -1138,6 +1138,30 @@ fn test_box_slice_clone_panics() {
     assert_eq!(drop_count.load(Ordering::SeqCst), 8);
 }
 
+#[test]
+fn test_copy_from_slice() {
+    let src = [0, 1, 2, 3, 4, 5];
+    let mut dst = [0; 6];
+    dst.copy_from_slice(&src);
+    assert_eq!(src, dst)
+}
+
+#[test]
+#[should_panic(expected = "destination and source slices have different lengths")]
+fn test_copy_from_slice_dst_longer() {
+    let src = [0, 1, 2, 3];
+    let mut dst = [0; 5];
+    dst.copy_from_slice(&src);
+}
+
+#[test]
+#[should_panic(expected = "destination and source slices have different lengths")]
+fn test_copy_from_slice_dst_shorter() {
+    let src = [0, 1, 2, 3];
+    let mut dst = [0; 3];
+    dst.copy_from_slice(&src);
+}
+
 mod bench {
     use std::{mem, ptr};
     use std::__rand::{Rng, thread_rng};
diff --git a/src/libcollectionstest/string.rs b/src/libcollectionstest/string.rs
index 158145af2bb..d8e01f3800c 100644
--- a/src/libcollectionstest/string.rs
+++ b/src/libcollectionstest/string.rs
@@ -140,7 +140,7 @@ fn test_from_utf16() {
 
     for p in &pairs {
         let (s, u) = (*p).clone();
-        let s_as_utf16 = s.utf16_units().collect::<Vec<u16>>();
+        let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
         let u_as_string = String::from_utf16(&u).unwrap();
 
         assert!(::rustc_unicode::str::is_utf16(&u));
@@ -150,7 +150,7 @@ fn test_from_utf16() {
         assert_eq!(String::from_utf16_lossy(&u), s);
 
         assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
-        assert_eq!(u_as_string.utf16_units().collect::<Vec<u16>>(), u);
+        assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u);
     }
 }
 
diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs
index 6a47f16c5ca..ccdbf1092ff 100644
--- a/src/libcollectionstest/vec.rs
+++ b/src/libcollectionstest/vec.rs
@@ -468,6 +468,24 @@ fn test_into_iter_count() {
 }
 
 #[test]
+fn test_into_iter_clone() {
+    fn iter_equal<I: Iterator<Item=i32>>(it: I, slice: &[i32]) {
+        let v: Vec<i32> = it.collect();
+        assert_eq!(&v[..], slice);
+    }
+    let mut it = vec![1, 2, 3].into_iter();
+    iter_equal(it.clone(), &[1, 2, 3]);
+    assert_eq!(it.next(), Some(1));
+    let mut it = it.rev();
+    iter_equal(it.clone(), &[3, 2]);
+    assert_eq!(it.next(), Some(3));
+    iter_equal(it.clone(), &[2]);
+    assert_eq!(it.next(), Some(2));
+    iter_equal(it.clone(), &[]);
+    assert_eq!(it.next(), None);
+}
+
+#[test]
 fn test_cow_from() {
     let borrowed: &[_] = &["borrowed", "(slice)"];
     let owned = vec!["owned", "(vec)"];
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 6041355e9db..255c846244b 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -579,8 +579,6 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// # Example
     ///
     /// ```
-    /// #![feature(cell_extras)]
-    ///
     /// use std::cell::{RefCell, Ref};
     ///
     /// let c = RefCell::new((5, 'b'));
@@ -588,8 +586,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// let b2: Ref<u32> = Ref::map(b1, |t| &t.0);
     /// assert_eq!(*b2, 5)
     /// ```
-    #[unstable(feature = "cell_extras", reason = "recently added",
-               issue = "27746")]
+    #[stable(feature = "cell_map", since = "1.8.0")]
     #[inline]
     pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U>
         where F: FnOnce(&T) -> &U
@@ -622,6 +619,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// ```
     #[unstable(feature = "cell_extras", reason = "recently added",
                issue = "27746")]
+    #[rustc_deprecated(since = "1.8.0", reason = "can be built on Ref::map")]
     #[inline]
     pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Option<Ref<'b, U>>
         where F: FnOnce(&T) -> Option<&U>
@@ -646,7 +644,6 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// # Example
     ///
     /// ```
-    /// # #![feature(cell_extras)]
     /// use std::cell::{RefCell, RefMut};
     ///
     /// let c = RefCell::new((5, 'b'));
@@ -658,8 +655,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// }
     /// assert_eq!(*c.borrow(), (42, 'b'));
     /// ```
-    #[unstable(feature = "cell_extras", reason = "recently added",
-               issue = "27746")]
+    #[stable(feature = "cell_map", since = "1.8.0")]
     #[inline]
     pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U>
         where F: FnOnce(&mut T) -> &mut U
@@ -698,6 +694,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// ```
     #[unstable(feature = "cell_extras", reason = "recently added",
                issue = "27746")]
+    #[rustc_deprecated(since = "1.8.0", reason = "can be built on RefMut::map")]
     #[inline]
     pub fn filter_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Option<RefMut<'b, U>>
         where F: FnOnce(&mut T) -> Option<&mut U>
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 5c67930c52f..a3b09e9db42 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -121,6 +121,10 @@ pub trait Write {
                 self.0.write_str(s)
             }
 
+            fn write_char(&mut self, c: char) -> Result {
+                self.0.write_char(c)
+            }
+
             fn write_fmt(&mut self, args: Arguments) -> Result {
                 self.0.write_fmt(args)
             }
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 2e2292d63f4..0417ef84163 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -58,6 +58,33 @@ extern "rust-intrinsic" {
     pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> T;
     pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> T;
     pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> T;
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchg_failrelaxed<T>(dst: *mut T, old: T, src: T) -> T;
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchg_failacq<T>(dst: *mut T, old: T, src: T) -> T;
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchg_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> T;
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchg_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> T;
+
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+    #[cfg(not(stage0))]
+    pub fn atomic_cxchgweak_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     pub fn atomic_load<T>(src: *const T) -> T;
     pub fn atomic_load_acq<T>(src: *const T) -> T;
@@ -213,7 +240,7 @@ extern "rust-intrinsic" {
     ///
     /// This has all the same safety problems as `ptr::read` with respect to
     /// invalid pointers, types, and double drops.
-    #[unstable(feature = "drop_in_place", reason = "just exposed, needs FCP", issue = "27908")]
+    #[stable(feature = "drop_in_place", since = "1.8.0")]
     pub fn drop_in_place<T: ?Sized>(to_drop: *mut T);
 
     /// Gets a static string slice containing the name of a type.
@@ -559,8 +586,5 @@ extern "rust-intrinsic" {
     /// platforms this is a `*mut *mut T` which is filled in by the compiler and
     /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's
     /// source as well as std's catch implementation.
-    #[cfg(not(stage0))]
     pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32;
-    #[cfg(stage0)]
-    pub fn try(f: fn(*mut u8), data: *mut u8) -> *mut u8;
 }
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 3f1808a0396..d6bd9dbf4bd 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -189,7 +189,7 @@
 //! ```
 //! let values = vec![1, 2, 3, 4, 5];
 //! {
-//!     let result = match values.into_iter() {
+//!     let result = match IntoIterator::into_iter(values) {
 //!         mut iter => loop {
 //!             match iter.next() {
 //!                 Some(x) => { println!("{}", x); },
@@ -1428,7 +1428,7 @@ pub trait Iterator {
     /// assert_eq!(6, doubled[2]);
     /// ```
     ///
-    /// Using the 'turbofish' instead of annotationg `doubled`:
+    /// Using the 'turbofish' instead of annotating `doubled`:
     ///
     /// ```
     /// let a = [1, 2, 3];
@@ -1610,7 +1610,7 @@ pub trait Iterator {
     /// `true`, then so does `all()`. If any of them return `false`, it
     /// returns `false`.
     ///
-    /// `all()` is short-circuting; in other words, it will stop processing
+    /// `all()` is short-circuiting; in other words, it will stop processing
     /// as soon as it finds a `false`, given that no matter what else happens,
     /// the result will also be `false`.
     ///
@@ -1660,7 +1660,7 @@ pub trait Iterator {
     /// `true`, then so does `any()`. If they all return `false`, it
     /// returns `false`.
     ///
-    /// `any()` is short-circuting; in other words, it will stop processing
+    /// `any()` is short-circuiting; in other words, it will stop processing
     /// as soon as it finds a `true`, given that no matter what else happens,
     /// the result will also be `true`.
     ///
@@ -1711,7 +1711,7 @@ pub trait Iterator {
     /// `true`, then `find()` returns `Some(element)`. If they all return
     /// `false`, it returns `None`.
     ///
-    /// `find()` is short-circuting; in other words, it will stop processing
+    /// `find()` is short-circuiting; in other words, it will stop processing
     /// as soon as the closure returns `true`.
     ///
     /// Because `find()` takes a reference, and many iterators iterate over
@@ -1762,7 +1762,7 @@ pub trait Iterator {
     /// returns `true`, then `position()` returns `Some(index)`. If all of
     /// them return `false`, it returns `None`.
     ///
-    /// `position()` is short-circuting; in other words, it will stop
+    /// `position()` is short-circuiting; in other words, it will stop
     /// processing as soon as it finds a `true`.
     ///
     /// # Overflow Behavior
@@ -1824,7 +1824,7 @@ pub trait Iterator {
     /// and if one of them returns `true`, then `rposition()` returns
     /// `Some(index)`. If all of them return `false`, it returns `None`.
     ///
-    /// `rposition()` is short-circuting; in other words, it will stop
+    /// `rposition()` is short-circuiting; in other words, it will stop
     /// processing as soon as it finds a `true`.
     ///
     /// # Examples
@@ -2079,7 +2079,7 @@ pub trait Iterator {
         (ts, us)
     }
 
-    /// Creates an iterator which clone()s all of its elements.
+    /// Creates an iterator which `clone()`s all of its elements.
     ///
     /// This is useful when you have an iterator over `&T`, but you need an
     /// iterator over `T`.
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index a521700b84b..c36ad592ad3 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -571,9 +571,25 @@ pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize;
 /// ```
 /// use std::mem;
 ///
-/// let one = unsafe { mem::transmute_copy(&1) };
+/// #[repr(packed)]
+/// struct Foo {
+///     bar: u8,
+/// }
+///
+/// let foo_slice = [10u8];
+///
+/// unsafe {
+///     // Copy the data from 'foo_slice' and treat it as a 'Foo'
+///     let mut foo_struct: Foo = mem::transmute_copy(&foo_slice);
+///     assert_eq!(foo_struct.bar, 10);
+///
+///     // Modify the copied data
+///     foo_struct.bar = 20;
+///     assert_eq!(foo_struct.bar, 20);
+/// }
 ///
-/// assert_eq!(1, one);
+/// // The contents of 'foo_slice' should not have changed
+/// assert_eq!(foo_slice, [10]);
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs
index 9f7672a52a1..b9a7afc400d 100644
--- a/src/libcore/num/flt2dec/mod.rs
+++ b/src/libcore/num/flt2dec/mod.rs
@@ -210,7 +210,7 @@ impl<'a> Part<'a> {
                     }
                 }
                 Part::Copy(buf) => {
-                    out[..buf.len()].clone_from_slice(buf);
+                    out[..buf.len()].copy_from_slice(buf);
                 }
             }
             Some(len)
@@ -245,7 +245,7 @@ impl<'a> Formatted<'a> {
     /// (It may still leave partially written bytes in the buffer; do not rely on that.)
     pub fn write(&self, out: &mut [u8]) -> Option<usize> {
         if out.len() < self.sign.len() { return None; }
-        out[..self.sign.len()].clone_from_slice(self.sign);
+        out[..self.sign.len()].copy_from_slice(self.sign);
 
         let mut written = self.sign.len();
         for part in self.parts {
diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs
index 68e50e8a400..d7e320267c6 100644
--- a/src/libcore/num/u16.rs
+++ b/src/libcore/num/u16.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u16, i16, 16 }
+uint_module! { u16, 16 }
diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs
index c1ee96b363c..9a26a39d5b3 100644
--- a/src/libcore/num/u32.rs
+++ b/src/libcore/num/u32.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u32, i32, 32 }
+uint_module! { u32, 32 }
diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs
index c0d18d850a7..e12c2c26542 100644
--- a/src/libcore/num/u64.rs
+++ b/src/libcore/num/u64.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u64, i64, 64 }
+uint_module! { u64, 64 }
diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs
index a60c480d810..0eb63bd9f3a 100644
--- a/src/libcore/num/u8.rs
+++ b/src/libcore/num/u8.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u8, i8, 8 }
+uint_module! { u8, 8 }
diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs
index 16d84cf81e1..9539a311390 100644
--- a/src/libcore/num/uint_macros.rs
+++ b/src/libcore/num/uint_macros.rs
@@ -10,7 +10,7 @@
 
 #![doc(hidden)]
 
-macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
+macro_rules! uint_module { ($T:ty, $bits:expr) => (
 
 #[unstable(feature = "num_bits_bytes",
            reason = "may want to be an associated function",
diff --git a/src/libcore/num/usize.rs b/src/libcore/num/usize.rs
index a6a7be023eb..875ab32fa8c 100644
--- a/src/libcore/num/usize.rs
+++ b/src/libcore/num/usize.rs
@@ -15,6 +15,6 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[cfg(target_pointer_width = "32")]
-uint_module! { usize, isize, 32 }
+uint_module! { usize, 32 }
 #[cfg(target_pointer_width = "64")]
-uint_module! { usize, isize, 64 }
+uint_module! { usize, 64 }
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index a6b3dc74469..7ccc15c2112 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -156,7 +156,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl AddAssign for Wrapping<$t> {
             #[inline(always)]
             fn add_assign(&mut self, other: Wrapping<$t>) {
@@ -174,7 +174,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl SubAssign for Wrapping<$t> {
             #[inline(always)]
             fn sub_assign(&mut self, other: Wrapping<$t>) {
@@ -192,7 +192,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl MulAssign for Wrapping<$t> {
             #[inline(always)]
             fn mul_assign(&mut self, other: Wrapping<$t>) {
@@ -210,7 +210,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl DivAssign for Wrapping<$t> {
             #[inline(always)]
             fn div_assign(&mut self, other: Wrapping<$t>) {
@@ -228,7 +228,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl RemAssign for Wrapping<$t> {
             #[inline(always)]
             fn rem_assign(&mut self, other: Wrapping<$t>) {
@@ -256,7 +256,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitXorAssign for Wrapping<$t> {
             #[inline(always)]
             fn bitxor_assign(&mut self, other: Wrapping<$t>) {
@@ -274,7 +274,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitOrAssign for Wrapping<$t> {
             #[inline(always)]
             fn bitor_assign(&mut self, other: Wrapping<$t>) {
@@ -292,7 +292,7 @@ macro_rules! wrapping_impl {
             }
         }
 
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitAndAssign for Wrapping<$t> {
             #[inline(always)]
             fn bitand_assign(&mut self, other: Wrapping<$t>) {
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index d1c5b175bb0..0f5584a952f 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -891,9 +891,6 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 /// calling `add_assign`, and therefore, `main` prints `Adding!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::AddAssign;
 ///
 /// struct Foo;
@@ -911,15 +908,16 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 /// }
 /// ```
 #[lang = "add_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait AddAssign<Rhs=Self> {
     /// The method for the `+=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn add_assign(&mut self, Rhs);
 }
 
 macro_rules! add_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl AddAssign for $t {
             #[inline]
             fn add_assign(&mut self, other: $t) { *self += other }
@@ -937,9 +935,6 @@ add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// calling `sub_assign`, and therefore, `main` prints `Subtracting!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::SubAssign;
 ///
 /// struct Foo;
@@ -957,15 +952,16 @@ add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang = "sub_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait SubAssign<Rhs=Self> {
     /// The method for the `-=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn sub_assign(&mut self, Rhs);
 }
 
 macro_rules! sub_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl SubAssign for $t {
             #[inline]
             fn sub_assign(&mut self, other: $t) { *self -= other }
@@ -983,9 +979,6 @@ sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// calling `mul_assign`, and therefore, `main` prints `Multiplying!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::MulAssign;
 ///
 /// struct Foo;
@@ -1003,15 +996,16 @@ sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang = "mul_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait MulAssign<Rhs=Self> {
     /// The method for the `*=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn mul_assign(&mut self, Rhs);
 }
 
 macro_rules! mul_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl MulAssign for $t {
             #[inline]
             fn mul_assign(&mut self, other: $t) { *self *= other }
@@ -1029,9 +1023,6 @@ mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// calling `div_assign`, and therefore, `main` prints `Dividing!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::DivAssign;
 ///
 /// struct Foo;
@@ -1049,15 +1040,16 @@ mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang = "div_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait DivAssign<Rhs=Self> {
     /// The method for the `/=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn div_assign(&mut self, Rhs);
 }
 
 macro_rules! div_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl DivAssign for $t {
             #[inline]
             fn div_assign(&mut self, other: $t) { *self /= other }
@@ -1075,9 +1067,6 @@ div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::RemAssign;
 ///
 /// struct Foo;
@@ -1095,15 +1084,16 @@ div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang = "rem_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait RemAssign<Rhs=Self> {
     /// The method for the `%=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn rem_assign(&mut self, Rhs);
 }
 
 macro_rules! rem_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl RemAssign for $t {
             #[inline]
             fn rem_assign(&mut self, other: $t) { *self %= other }
@@ -1121,9 +1111,6 @@ rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// calling `bitand_assign`, and therefore, `main` prints `Bitwise And-ing!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::BitAndAssign;
 ///
 /// struct Foo;
@@ -1141,15 +1128,16 @@ rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
 /// }
 /// ```
 #[lang = "bitand_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait BitAndAssign<Rhs=Self> {
     /// The method for the `&` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn bitand_assign(&mut self, Rhs);
 }
 
 macro_rules! bitand_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitAndAssign for $t {
             #[inline]
             fn bitand_assign(&mut self, other: $t) { *self &= other }
@@ -1167,9 +1155,6 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 /// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::BitOrAssign;
 ///
 /// struct Foo;
@@ -1187,15 +1172,16 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 /// }
 /// ```
 #[lang = "bitor_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait BitOrAssign<Rhs=Self> {
     /// The method for the `|=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn bitor_assign(&mut self, Rhs);
 }
 
 macro_rules! bitor_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitOrAssign for $t {
             #[inline]
             fn bitor_assign(&mut self, other: $t) { *self |= other }
@@ -1213,9 +1199,6 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 /// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::BitXorAssign;
 ///
 /// struct Foo;
@@ -1233,15 +1216,16 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 /// }
 /// ```
 #[lang = "bitxor_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait BitXorAssign<Rhs=Self> {
     /// The method for the `^=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn bitxor_assign(&mut self, Rhs);
 }
 
 macro_rules! bitxor_assign_impl {
     ($($t:ty)+) => ($(
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl BitXorAssign for $t {
             #[inline]
             fn bitxor_assign(&mut self, other: $t) { *self ^= other }
@@ -1259,9 +1243,6 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 /// calling `shl_assign`, and therefore, `main` prints `Shifting left!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::ShlAssign;
 ///
 /// struct Foo;
@@ -1279,15 +1260,16 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 /// }
 /// ```
 #[lang = "shl_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait ShlAssign<Rhs> {
     /// The method for the `<<=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn shl_assign(&mut self, Rhs);
 }
 
 macro_rules! shl_assign_impl {
     ($t:ty, $f:ty) => (
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl ShlAssign<$f> for $t {
             #[inline]
             fn shl_assign(&mut self, other: $f) {
@@ -1323,9 +1305,6 @@ shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 /// calling `shr_assign`, and therefore, `main` prints `Shifting right!`.
 ///
 /// ```
-/// #![feature(augmented_assignments)]
-/// #![feature(op_assign_traits)]
-///
 /// use std::ops::ShrAssign;
 ///
 /// struct Foo;
@@ -1343,15 +1322,16 @@ shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 /// }
 /// ```
 #[lang = "shr_assign"]
-#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+#[stable(feature = "op_assign_traits", since = "1.8.0")]
 pub trait ShrAssign<Rhs=Self> {
     /// The method for the `>>=` operator
+    #[stable(feature = "op_assign_traits", since = "1.8.0")]
     fn shr_assign(&mut self, Rhs);
 }
 
 macro_rules! shr_assign_impl {
     ($t:ty, $f:ty) => (
-        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        #[stable(feature = "op_assign_traits", since = "1.8.0")]
         impl ShrAssign<$f> for $t {
             #[inline]
             fn shr_assign(&mut self, other: $f) {
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index eeb0c173b9b..e38cf9af010 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -169,7 +169,7 @@ pub enum Option<T> {
     None,
     /// Some value `T`
     #[stable(feature = "rust1", since = "1.0.0")]
-    Some(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T)
+    Some(#[stable(feature = "rust1", since = "1.0.0")] T)
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 3cbb2f17be7..cb109c010c7 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -40,7 +40,7 @@ pub use intrinsics::copy;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::write_bytes;
 
-#[unstable(feature = "drop_in_place", reason = "just exposed, needs FCP", issue = "27908")]
+#[stable(feature = "drop_in_place", since = "1.8.0")]
 pub use intrinsics::drop_in_place;
 
 /// Creates a null raw pointer.
@@ -161,6 +161,54 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
     intrinsics::move_val_init(&mut *dst, src)
 }
 
+/// Performs a volatile read of the value from `src` without moving it. This
+/// leaves the memory in `src` unchanged.
+///
+/// Volatile operations are intended to act on I/O memory, and are guaranteed
+/// to not be elided or reordered by the compiler across other volatile
+/// operations. See the LLVM documentation on [[volatile]].
+///
+/// [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses
+///
+/// # Safety
+///
+/// Beyond accepting a raw pointer, this is unsafe because it semantically
+/// moves the value out of `src` without preventing further usage of `src`.
+/// If `T` is not `Copy`, then care must be taken to ensure that the value at
+/// `src` is not used before the data is overwritten again (e.g. with `write`,
+/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
+/// because it will attempt to drop the value previously at `*src`.
+#[inline]
+#[unstable(feature = "volatile", reason = "recently added", issue = "31756")]
+pub unsafe fn read_volatile<T>(src: *const T) -> T {
+    intrinsics::volatile_load(src)
+}
+
+/// Performs a volatile write of a memory location with the given value without
+/// reading or dropping the old value.
+///
+/// Volatile operations are intended to act on I/O memory, and are guaranteed
+/// to not be elided or reordered by the compiler across other volatile
+/// operations. See the LLVM documentation on [[volatile]].
+///
+/// [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses
+///
+/// # Safety
+///
+/// This operation is marked unsafe because it accepts a raw pointer.
+///
+/// It does not drop the contents of `dst`. This is safe, but it could leak
+/// allocations or resources, so care must be taken not to overwrite an object
+/// that should be dropped.
+///
+/// This is appropriate for initializing uninitialized memory, or overwriting
+/// memory that has previously been `read` from.
+#[inline]
+#[unstable(feature = "volatile", reason = "recently added", issue = "31756")]
+pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
+    intrinsics::volatile_store(dst, src);
+}
+
 #[lang = "const_ptr"]
 impl<T: ?Sized> *const T {
     /// Returns true if the pointer is null.
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 9bd6ed12798..f6703d16ad9 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -250,11 +250,11 @@ use option::Option::{self, None, Some};
 pub enum Result<T, E> {
     /// Contains the success value
     #[stable(feature = "rust1", since = "1.0.0")]
-    Ok(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T),
+    Ok(#[stable(feature = "rust1", since = "1.0.0")] T),
 
     /// Contains the error value
     #[stable(feature = "rust1", since = "1.0.0")]
-    Err(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] E)
+    Err(#[stable(feature = "rust1", since = "1.0.0")] E)
 }
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 40041c748e7..afda70f4fcc 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -48,7 +48,7 @@ use result::Result;
 use result::Result::{Ok, Err};
 use ptr;
 use mem;
-use marker::{Send, Sync, self};
+use marker::{Copy, Send, Sync, self};
 use raw::Repr;
 // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
 use raw::Slice as RawSlice;
@@ -152,6 +152,8 @@ pub trait SliceExt {
 
     #[stable(feature = "clone_from_slice", since = "1.7.0")]
     fn clone_from_slice(&mut self, &[Self::Item]) where Self::Item: Clone;
+    #[unstable(feature = "copy_from_slice", issue = "31755")]
+    fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
 }
 
 // Use macros to be generic over const/mut
@@ -488,6 +490,16 @@ impl<T> SliceExt for [T] {
             self[i].clone_from(&src[i]);
         }
     }
+
+    #[inline]
+    fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
+        assert!(self.len() == src.len(),
+                "destination and source slices have different lengths");
+        unsafe {
+            ptr::copy_nonoverlapping(
+                src.as_ptr(), self.as_mut_ptr(), self.len());
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 700a577e20c..0c831bff763 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -311,10 +311,101 @@ impl AtomicBool {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
+        self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+    }
+
+    /// Stores a value into the `bool` if the current value is the same as the `current` value.
+    ///
+    /// The return value is always the previous value. If it is equal to `current`, then the value
+    /// was updated.
+    ///
+    /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
+    /// operation. The first describes the required ordering if the operation succeeds while the
+    /// second describes the required ordering when the operation fails. The failure ordering can't
+    /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicBool, Ordering};
+    ///
+    /// let some_bool = AtomicBool::new(true);
+    ///
+    /// assert_eq!(some_bool.compare_exchange(true,
+    ///                                       false,
+    ///                                       Ordering::Acquire,
+    ///                                       Ordering::Relaxed),
+    ///            true);
+    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
+    ///
+    /// assert_eq!(some_bool.compare_exchange(true, true,
+    ///                                       Ordering::SeqCst,
+    ///                                       Ordering::Acquire),
+    ///            false);
+    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange(&self,
+                            current: bool,
+                            new: bool,
+                            success: Ordering,
+                            failure: Ordering) -> bool {
         let current = if current { UINT_TRUE } else { 0 };
         let new = if new { UINT_TRUE } else { 0 };
 
-        unsafe { atomic_compare_and_swap(self.v.get(), current, new, order) > 0 }
+        unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) > 0 }
+    }
+
+    /// Stores a value into the `bool` if the current value is the same as the `current` value.
+    ///
+    /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
+    /// comparison succeeds, which can result in more efficient code on some platforms. The
+    /// returned value is a tuple of the existing value and a flag indicating whether the
+    /// new value was written.
+    ///
+    /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+    /// ordering of this operation. The first describes the required ordering if the operation
+    /// succeeds while the second describes the required ordering when the operation fails. The
+    /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the
+    /// success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicBool, Ordering};
+    ///
+    /// let val = AtomicBool::new(false);
+    ///
+    /// let new = true;
+    /// let mut old = val.load(Ordering::Relaxed);
+    /// loop {
+    ///     let result = val.compare_exchange_weak(old, new,
+    ///                                            Ordering::SeqCst,
+    ///                                            Ordering::Relaxed);
+    ///     if result.1 {
+    ///         break;
+    ///     } else {
+    ///         old = result.0;
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange_weak(&self,
+                                 current: bool,
+                                 new: bool,
+                                 success: Ordering,
+                                 failure: Ordering) -> (bool, bool) {
+        let current = if current { UINT_TRUE } else { 0 };
+        let new = if new { UINT_TRUE } else { 0 };
+
+        let result = unsafe {
+            atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
+        };
+        (result.0 > 0, result.1)
     }
 
     /// Logical "and" with a boolean value.
@@ -553,7 +644,91 @@ impl AtomicIsize {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn compare_and_swap(&self, current: isize, new: isize, order: Ordering) -> isize {
-        unsafe { atomic_compare_and_swap(self.v.get(), current, new, order) }
+        self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+    }
+
+    /// Stores a value into the `isize` if the current value is the same as the `current` value.
+    ///
+    /// The return value is always the previous value. If it is equal to `current`, then the value
+    /// was updated.
+    ///
+    /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
+    /// operation. The first describes the required ordering if the operation succeeds while the
+    /// second describes the required ordering when the operation fails. The failure ordering can't
+    /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
+    ///
+    /// let some_isize = AtomicIsize::new(5);
+    ///
+    /// assert_eq!(some_isize.compare_exchange(5, 10,
+    ///                                        Ordering::Acquire,
+    ///                                        Ordering::Relaxed),
+    ///            5);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
+    ///
+    /// assert_eq!(some_isize.compare_exchange(6, 12,
+    ///                                        Ordering::SeqCst,
+    ///                                        Ordering::Acquire),
+    ///            10);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange(&self,
+                            current: isize,
+                            new: isize,
+                            success: Ordering,
+                            failure: Ordering) -> isize {
+        unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+    }
+
+    /// Stores a value into the `isize if the current value is the same as the `current` value.
+    ///
+    /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
+    /// comparison succeeds, which can result in more efficient code on some platforms. The
+    /// returned value is a tuple of the existing value and a flag indicating whether the
+    /// new value was written.
+    ///
+    /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+    /// ordering of this operation. The first describes the required ordering if the operation
+    /// succeeds while the second describes the required ordering when the operation fails. The
+    /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the
+    /// success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
+    ///
+    /// let val = AtomicIsize::new(4);
+    ///
+    /// let mut old = val.load(Ordering::Relaxed);
+    /// loop {
+    ///     let new = old * 2;
+    ///     let result = val.compare_exchange_weak(old, new,
+    ///                                            Ordering::SeqCst,
+    ///                                            Ordering::Relaxed);
+    ///     if result.1 {
+    ///         break;
+    ///     } else {
+    ///         old = result.0;
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange_weak(&self,
+                                 current: isize,
+                                 new: isize,
+                                 success: Ordering,
+                                 failure: Ordering) -> (isize, bool) {
+        unsafe { atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) }
     }
 
     /// Add an isize to the current value, returning the previous value.
@@ -746,7 +921,91 @@ impl AtomicUsize {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn compare_and_swap(&self, current: usize, new: usize, order: Ordering) -> usize {
-        unsafe { atomic_compare_and_swap(self.v.get(), current, new, order) }
+        self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+    }
+
+    /// Stores a value into the `usize` if the current value is the same as the `current` value.
+    ///
+    /// The return value is always the previous value. If it is equal to `current`, then the value
+    /// was updated.
+    ///
+    /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
+    /// operation. The first describes the required ordering if the operation succeeds while the
+    /// second describes the required ordering when the operation fails. The failure ordering can't
+    /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
+    ///
+    /// let some_isize = AtomicUsize::new(5);
+    ///
+    /// assert_eq!(some_isize.compare_exchange(5, 10,
+    ///                                        Ordering::Acquire,
+    ///                                        Ordering::Relaxed),
+    ///            5);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
+    ///
+    /// assert_eq!(some_isize.compare_exchange(6, 12,
+    ///                                        Ordering::SeqCst,
+    ///                                        Ordering::Acquire),
+    ///            10);
+    /// assert_eq!(some_isize.load(Ordering::Relaxed), 10);
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange(&self,
+                            current: usize,
+                            new: usize,
+                            success: Ordering,
+                            failure: Ordering) -> usize {
+        unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
+    }
+
+    /// Stores a value into the `usize` if the current value is the same as the `current` value.
+    ///
+    /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
+    /// comparison succeeds, which can result in more efficient code on some platforms. The
+    /// returned value is a tuple of the existing value and a flag indicating whether the
+    /// new value was written.
+    ///
+    /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+    /// ordering of this operation. The first describes the required ordering if the operation
+    /// succeeds while the second describes the required ordering when the operation fails. The
+    /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the
+    /// success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
+    ///
+    /// let val = AtomicUsize::new(4);
+    ///
+    /// let mut old = val.load(Ordering::Relaxed);
+    /// loop {
+    ///     let new = old * 2;
+    ///     let result = val.compare_exchange_weak(old, new,
+    ///                                            Ordering::SeqCst,
+    ///                                            Ordering::Relaxed);
+    ///     if result.1 {
+    ///         break;
+    ///     } else {
+    ///         old = result.0;
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange_weak(&self,
+                                 current: usize,
+                                 new: usize,
+                                 success: Ordering,
+                                 failure: Ordering) -> (usize, bool) {
+        unsafe { atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) }
     }
 
     /// Add to the current usize, returning the previous value.
@@ -947,15 +1206,109 @@ impl<T> AtomicPtr<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
+        self.compare_exchange(current, new, order, strongest_failure_ordering(order))
+    }
+
+    /// Stores a value into the pointer if the current value is the same as the `current` value.
+    ///
+    /// The return value is always the previous value. If it is equal to `current`, then the value
+    /// was updated.
+    ///
+    /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
+    /// operation. The first describes the required ordering if the operation succeeds while the
+    /// second describes the required ordering when the operation fails. The failure ordering can't
+    /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicPtr, Ordering};
+    ///
+    /// let ptr = &mut 5;
+    /// let some_ptr  = AtomicPtr::new(ptr);
+    ///
+    /// let other_ptr   = &mut 10;
+    /// let another_ptr = &mut 10;
+    ///
+    /// let value = some_ptr.compare_exchange(other_ptr, another_ptr,
+    ///                                       Ordering::SeqCst, Ordering::Relaxed);
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange(&self,
+                            current: *mut T,
+                            new: *mut T,
+                            success: Ordering,
+                            failure: Ordering) -> *mut T {
         unsafe {
-            atomic_compare_and_swap(self.p.get() as *mut usize, current as usize,
-                                    new as usize, order) as *mut T
+            atomic_compare_exchange(self.p.get() as *mut usize, current as usize,
+                                    new as usize, success, failure) as *mut T
         }
     }
+
+    /// Stores a value into the pointer if the current value is the same as the `current` value.
+    ///
+    /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
+    /// comparison succeeds, which can result in more efficient code on some platforms. The
+    /// returned value is a tuple of the existing value and a flag indicating whether the
+    /// new value was written.
+    ///
+    /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+    /// ordering of this operation. The first describes the required ordering if the operation
+    /// succeeds while the second describes the required ordering when the operation fails. The
+    /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the
+    /// success ordering.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(extended_compare_and_swap)]
+    /// use std::sync::atomic::{AtomicPtr, Ordering};
+    ///
+    /// let some_ptr = AtomicPtr::new(&mut 5);
+    ///
+    /// let new = &mut 10;
+    /// let mut old = some_ptr.load(Ordering::Relaxed);
+    /// loop {
+    ///     let result = some_ptr.compare_exchange_weak(old, new,
+    ///                                                 Ordering::SeqCst,
+    ///                                                 Ordering::Relaxed);
+    ///     if result.1 {
+    ///         break;
+    ///     } else {
+    ///         old = result.0;
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    #[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
+    pub fn compare_exchange_weak(&self,
+                                 current: *mut T,
+                                 new: *mut T,
+                                 success: Ordering,
+                                 failure: Ordering) -> (*mut T, bool) {
+        let result = unsafe {
+            atomic_compare_exchange_weak(self.p.get() as *mut usize, current as usize,
+                                         new as usize, success, failure)
+        };
+        (result.0 as *mut T, result.1)
+    }
 }
 
 #[inline]
-unsafe fn atomic_store<T>(dst: *mut T, val: T, order:Ordering) {
+fn strongest_failure_ordering(order: Ordering) -> Ordering {
+    match order {
+        Release => Relaxed,
+        Relaxed => Relaxed,
+        SeqCst  => SeqCst,
+        Acquire => Acquire,
+        AcqRel  => Acquire,
+    }
+}
+
+#[inline]
+unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
     match order {
         Release => intrinsics::atomic_store_rel(dst, val),
         Relaxed => intrinsics::atomic_store_relaxed(dst, val),
@@ -966,7 +1319,7 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order:Ordering) {
 }
 
 #[inline]
-unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
+unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_load_acq(dst),
         Relaxed => intrinsics::atomic_load_relaxed(dst),
@@ -1012,8 +1365,36 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering) -> T {
-    match order {
+#[cfg(not(stage0))]
+unsafe fn atomic_compare_exchange<T>(dst: *mut T,
+                                     old: T,
+                                     new: T,
+                                     success: Ordering,
+                                     failure: Ordering) -> T {
+    match (success, failure) {
+        (Acquire, Acquire) => intrinsics::atomic_cxchg_acq(dst, old, new),
+        (Release, Relaxed) => intrinsics::atomic_cxchg_rel(dst, old, new),
+        (AcqRel, Acquire)  => intrinsics::atomic_cxchg_acqrel(dst, old, new),
+        (Relaxed, Relaxed) => intrinsics::atomic_cxchg_relaxed(dst, old, new),
+        (SeqCst, SeqCst)   => intrinsics::atomic_cxchg(dst, old, new),
+        (Acquire, Relaxed) => intrinsics::atomic_cxchg_acq_failrelaxed(dst, old, new),
+        (AcqRel, Relaxed)  => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
+        (SeqCst, Relaxed)  => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
+        (SeqCst, Acquire)  => intrinsics::atomic_cxchg_failacq(dst, old, new),
+        (_, Release) => panic!("there is no such thing as an acquire/release failure ordering"),
+        (_, AcqRel) => panic!("there is no such thing as a release failure ordering"),
+        _ => panic!("a failure ordering can't be stronger than a success ordering"),
+    }
+}
+
+#[inline]
+#[cfg(stage0)]
+unsafe fn atomic_compare_exchange<T>(dst: *mut T,
+                                     old: T,
+                                     new: T,
+                                     success: Ordering,
+                                     _: Ordering) -> T {
+    match success {
         Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
         Release => intrinsics::atomic_cxchg_rel(dst, old, new),
         AcqRel  => intrinsics::atomic_cxchg_acqrel(dst, old, new),
@@ -1023,6 +1404,42 @@ unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering)
 }
 
 #[inline]
+#[cfg(not(stage0))]
+unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
+                                          old: T,
+                                          new: T,
+                                          success: Ordering,
+                                          failure: Ordering) -> (T, bool) {
+    match (success, failure) {
+        (Acquire, Acquire) => intrinsics::atomic_cxchgweak_acq(dst, old, new),
+        (Release, Relaxed) => intrinsics::atomic_cxchgweak_rel(dst, old, new),
+        (AcqRel, Acquire)  => intrinsics::atomic_cxchgweak_acqrel(dst, old, new),
+        (Relaxed, Relaxed) => intrinsics::atomic_cxchgweak_relaxed(dst, old, new),
+        (SeqCst, SeqCst)   => intrinsics::atomic_cxchgweak(dst, old, new),
+        (Acquire, Relaxed) => intrinsics::atomic_cxchgweak_acq_failrelaxed(dst, old, new),
+        (AcqRel, Relaxed)  => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
+        (SeqCst, Relaxed)  => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
+        (SeqCst, Acquire)  => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
+        (_, Release) => panic!("there is no such thing as an acquire/release failure ordering"),
+        (_, AcqRel) => panic!("there is no such thing as a release failure ordering"),
+        _ => panic!("a failure ordering can't be stronger than a success ordering"),
+    }
+}
+
+#[inline]
+#[cfg(stage0)]
+unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
+                                          old: T,
+                                          new: T,
+                                          success: Ordering,
+                                          failure: Ordering) -> (T, bool)
+    where T: ::cmp::Eq + ::marker::Copy
+{
+    let result = atomic_compare_exchange(dst, old, new, success, failure);
+    (result, result == old)
+}
+
+#[inline]
 unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_and_acq(dst, val),
diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs
index 309a3d51c76..cafffb5266f 100644
--- a/src/libcoretest/cell.rs
+++ b/src/libcoretest/cell.rs
@@ -159,6 +159,7 @@ fn ref_map_accessor() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn ref_filter_map_accessor() {
     struct X(RefCell<Result<u32, ()>>);
     impl X {
@@ -189,6 +190,7 @@ fn ref_mut_map_accessor() {
 }
 
 #[test]
+#[allow(deprecated)]
 fn ref_mut_filter_map_accessor() {
     struct X(RefCell<Result<u32, ()>>);
     impl X {
diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs
index f23ddea5cc9..e4df99002c8 100644
--- a/src/libcoretest/lib.rs
+++ b/src/libcoretest/lib.rs
@@ -15,6 +15,7 @@
 #![feature(box_syntax)]
 #![feature(cell_extras)]
 #![feature(const_fn)]
+#![feature(copy_from_slice)]
 #![feature(core_float)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
diff --git a/src/libcoretest/num/flt2dec/mod.rs b/src/libcoretest/num/flt2dec/mod.rs
index 48a5501acb7..1a592f3ad42 100644
--- a/src/libcoretest/num/flt2dec/mod.rs
+++ b/src/libcoretest/num/flt2dec/mod.rs
@@ -100,7 +100,7 @@ fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16
 
     // check significant digits
     for i in 1..cut.unwrap_or(expected.len() - 1) {
-        expected_[..i].clone_from_slice(&expected[..i]);
+        expected_[..i].copy_from_slice(&expected[..i]);
         let mut expectedk_ = expectedk;
         if expected[i] >= b'5' {
             // check if this is a rounding-to-even case.
@@ -147,7 +147,7 @@ fn check_exact<F, T>(mut f: F, v: T, vstr: &str, expected: &[u8], expectedk: i16
     // check infinite zero digits
     if let Some(cut) = cut {
         for i in cut..expected.len()-1 {
-            expected_[..cut].clone_from_slice(&expected[..cut]);
+            expected_[..cut].copy_from_slice(&expected[..cut]);
             for c in &mut expected_[cut..i] { *c = b'0'; }
 
             try_exact!(f(&decoded) => &mut buf, &expected_[..i], expectedk;
diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index 57ce53e73b0..fe059076926 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -331,9 +331,8 @@ impl Matches {
     /// Returns the string argument supplied to one of several matching options or `None`.
     pub fn opts_str(&self, names: &[String]) -> Option<String> {
         for nm in names {
-            match self.opt_val(&nm[..]) {
-                Some(Val(ref s)) => return Some(s.clone()),
-                _ => (),
+            if let Some(Val(ref s)) = self.opt_val(&nm[..]) {
+                  return Some(s.clone())
             }
         }
         None
diff --git a/src/liblibc b/src/liblibc
-Subproject a64ee24718c0289b82a77d692cf56f8a1226de5
+Subproject 16f1c190afbc7605ed50a40f802189e436de68f
diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs
index 1727fa2a0d3..533f2ee3b3e 100644
--- a/src/librbml/lib.rs
+++ b/src/librbml/lib.rs
@@ -122,6 +122,7 @@
        test(attr(deny(warnings))))]
 #![cfg_attr(not(stage0), deny(warnings))]
 
+#![feature(copy_from_slice)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 
@@ -519,7 +520,7 @@ pub mod reader {
             // of the page and segfault.
 
             let mut b = [0; 8];
-            b.clone_from_slice(&d.data[d.end - 8..d.end]);
+            b.copy_from_slice(&d.data[d.end - 8..d.end]);
             let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() };
             let len = d.end - d.start;
             if len < 8 {
@@ -1043,7 +1044,7 @@ pub mod writer {
                 {
                     let last_size_pos = last_size_pos as usize;
                     let data = &self.writer.get_ref()[last_size_pos + 4..cur_pos as usize];
-                    buf[..size].clone_from_slice(data);
+                    buf[..size].copy_from_slice(data);
                 }
 
                 // overwrite the size and data and continue
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 2aefeb5fc2d..e65b4355e9d 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -17,6 +17,7 @@ graphviz = { path = "../libgraphviz" }
 log = { path = "../liblog" }
 rbml = { path = "../librbml" }
 rustc_back = { path = "../librustc_back" }
+rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_front = { path = "../librustc_front" }
 rustc_llvm = { path = "../librustc_llvm" }
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 8a9ef666b83..92db527ef98 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -20,8 +20,8 @@ This error suggests that the expression arm corresponding to the noted pattern
 will never be reached as for all possible values of the expression being
 matched, one of the preceding patterns will match.
 
-This means that perhaps some of the preceding patterns are too general, this one
-is too specific or the ordering is incorrect.
+This means that perhaps some of the preceding patterns are too general, this
+one is too specific or the ordering is incorrect.
 
 For example, the following `match` block has too many arms:
 
@@ -104,28 +104,86 @@ E0004: r##"
 This error indicates that the compiler cannot guarantee a matching pattern for
 one or more possible inputs to a match expression. Guaranteed matches are
 required in order to assign values to match expressions, or alternatively,
-determine the flow of execution.
+determine the flow of execution. Erroneous code example:
+
+```compile_fail
+enum Terminator {
+    HastaLaVistaBaby,
+    TalkToMyHand,
+}
+
+let x = Terminator::HastaLaVistaBaby;
+
+match x { // error: non-exhaustive patterns: `HastaLaVistaBaby` not covered
+    Terminator::TalkToMyHand => {}
+}
+```
 
 If you encounter this error you must alter your patterns so that every possible
 value of the input type is matched. For types with a small number of variants
 (like enums) you should probably cover all cases explicitly. Alternatively, the
 underscore `_` wildcard pattern can be added after all other patterns to match
-"anything else".
+"anything else". Example:
+
+```
+enum Terminator {
+    HastaLaVistaBaby,
+    TalkToMyHand,
+}
+
+let x = Terminator::HastaLaVistaBaby;
+
+match x {
+    Terminator::TalkToMyHand => {}
+    Terminator::HastaLaVistaBaby => {}
+}
+
+// or:
+
+match x {
+    Terminator::TalkToMyHand => {}
+    _ => {}
+}
+```
 "##,
 
 E0005: r##"
 Patterns used to bind names must be irrefutable, that is, they must guarantee
-that a name will be extracted in all cases. If you encounter this error you
-probably need to use a `match` or `if let` to deal with the possibility of
-failure.
+that a name will be extracted in all cases. Erroneous code example:
+
+```compile_fail
+let x = Some(1);
+let Some(y) = x;
+// error: refutable pattern in local binding: `None` not covered
+```
+
+If you encounter this error you probably need to use a `match` or `if let` to
+deal with the possibility of failure. Example:
+
+```compile_fail
+let x = Some(1);
+
+match x {
+    Some(y) => {
+        // do something
+    },
+    None => {}
+}
+
+// or:
+
+if let Some(y) = x {
+    // do something
+}
+```
 "##,
 
 E0007: r##"
 This error indicates that the bindings in a match arm would require a value to
-be moved into more than one location, thus violating unique ownership. Code like
-the following is invalid as it requires the entire `Option<String>` to be moved
-into a variable called `op_string` while simultaneously requiring the inner
-String to be moved into a variable called `s`.
+be moved into more than one location, thus violating unique ownership. Code
+like the following is invalid as it requires the entire `Option<String>` to be
+moved into a variable called `op_string` while simultaneously requiring the
+inner `String` to be moved into a variable called `s`.
 
 ```compile_fail
 let x = Some("s".to_string());
@@ -180,7 +238,7 @@ by-ref.
 
 This limitation may be removed in a future version of Rust.
 
-Wrong example:
+Erroneous code example:
 
 ```compile_fail
 struct X { x: (), }
@@ -264,7 +322,7 @@ trait Foo where Self: Sized {
 }
 ```
 
-we cannot create an object of type `Box<Foo>` or `&Foo` since in this case
+We cannot create an object of type `Box<Foo>` or `&Foo` since in this case
 `Self` would not be `Sized`.
 
 Generally, `Self : Sized` is used to indicate that the trait should not be used
@@ -294,7 +352,7 @@ impl Trait for u8 {
 ```
 
 (Note that `&self` and `&mut self` are okay, it's additional `Self` types which
-cause this problem)
+cause this problem.)
 
 In such a case, the compiler cannot predict the return type of `foo()` in a
 situation like the following:
@@ -573,15 +631,15 @@ type X = u32; // ok!
 "##,
 
 E0133: r##"
-Using unsafe functionality, is potentially dangerous and disallowed
-by safety checks. Examples:
+Using unsafe functionality is potentially dangerous and disallowed by safety
+checks. Examples:
 
-- Dereferencing raw pointers
-- Calling functions via FFI
-- Calling functions marked unsafe
+* Dereferencing raw pointers
+* Calling functions via FFI
+* Calling functions marked unsafe
 
-These safety checks can be relaxed for a section of the code
-by wrapping the unsafe instructions with an `unsafe` block. For instance:
+These safety checks can be relaxed for a section of the code by wrapping the
+unsafe instructions with an `unsafe` block. For instance:
 
 ```
 unsafe fn f() { return; }
@@ -1039,14 +1097,16 @@ let y = match x {
 println!("{}", y);
 ```
 
-In the previous example, the print statement was never reached when the wildcard
-match arm was hit, so we were okay with `foo()` not returning an integer that we
-could set to `y`. But in this example, `foo()` actually does return control, so
-the print statement will be executed with an uninitialized value.
+In the previous example, the print statement was never reached when the
+wildcard match arm was hit, so we were okay with `foo()` not returning an
+integer that we could set to `y`. But in this example, `foo()` actually does
+return control, so the print statement will be executed with an uninitialized
+value.
 
 Obviously we cannot have functions which are allowed to be used in such
 positions and yet can return control. So, if you are defining a function that
-returns `!`, make sure that there is no way for it to actually finish executing.
+returns `!`, make sure that there is no way for it to actually finish
+executing.
 "##,
 
 E0271: r##"
@@ -1206,19 +1266,19 @@ trait Index<Idx> { ... }
 foo(true); // `bool` does not implement `Index<u8>`
 ```
 
-there will be an error about `bool` not implementing `Index<u8>`, followed by a
+There will be an error about `bool` not implementing `Index<u8>`, followed by a
 note saying "the type `bool` cannot be indexed by `u8`".
 
-As you can see, you can specify type parameters in curly braces for substitution
-with the actual types (using the regular format string syntax) in a given
-situation. Furthermore, `{Self}` will substitute to the type (in this case,
-`bool`) that we tried to use.
+As you can see, you can specify type parameters in curly braces for
+substitution with the actual types (using the regular format string syntax) in
+a given situation. Furthermore, `{Self}` will substitute to the type (in this
+case, `bool`) that we tried to use.
 
 This error appears when the curly braces contain an identifier which doesn't
-match with any of the type parameters or the string `Self`. This might happen if
-you misspelled a type parameter, or if you intended to use literal curly braces.
-If it is the latter, escape the curly braces with a second curly brace of the
-same type; e.g. a literal `{` is `{{`
+match with any of the type parameters or the string `Self`. This might happen
+if you misspelled a type parameter, or if you intended to use literal curly
+braces. If it is the latter, escape the curly braces with a second curly brace
+of the same type; e.g. a literal `{` is `{{`.
 "##,
 
 E0273: r##"
@@ -1239,10 +1299,10 @@ foo(true); // `bool` does not implement `Index<u8>`
 there will be an error about `bool` not implementing `Index<u8>`, followed by a
 note saying "the type `bool` cannot be indexed by `u8`".
 
-As you can see, you can specify type parameters in curly braces for substitution
-with the actual types (using the regular format string syntax) in a given
-situation. Furthermore, `{Self}` will substitute to the type (in this case,
-`bool`) that we tried to use.
+As you can see, you can specify type parameters in curly braces for
+substitution with the actual types (using the regular format string syntax) in
+a given situation. Furthermore, `{Self}` will substitute to the type (in this
+case, `bool`) that we tried to use.
 
 This error appears when the curly braces do not contain an identifier. Please
 add one of the same name as a type parameter. If you intended to use literal
@@ -1274,8 +1334,8 @@ trait.
 
 E0275: r##"
 This error occurs when there was a recursive trait requirement that overflowed
-before it could be evaluated. Often this means that there is unbounded recursion
-in resolving some type bounds.
+before it could be evaluated. Often this means that there is unbounded
+recursion in resolving some type bounds.
 
 For example, in the following code:
 
@@ -1288,9 +1348,9 @@ impl<T> Foo for T where Bar<T>: Foo {}
 ```
 
 To determine if a `T` is `Foo`, we need to check if `Bar<T>` is `Foo`. However,
-to do this check, we need to determine that `Bar<Bar<T>>` is `Foo`. To determine
-this, we check if `Bar<Bar<Bar<T>>>` is `Foo`, and so on. This is clearly a
-recursive requirement that can't be resolved directly.
+to do this check, we need to determine that `Bar<Bar<T>>` is `Foo`. To
+determine this, we check if `Bar<Bar<Bar<T>>>` is `Foo`, and so on. This is
+clearly a recursive requirement that can't be resolved directly.
 
 Consider changing your trait bounds so that they're less self-referential.
 "##,
@@ -1336,7 +1396,7 @@ fn main() {
     // we now call the method with the i32 type, which doesn't implement
     // the Foo trait
     some_func(5i32); // error: the trait `Foo` is not implemented for the
-                     //     type `i32`
+                     //        type `i32`
 }
 ```
 
@@ -1564,7 +1624,9 @@ borrows were allowed:
 ```compile_fail
 match Some(()) {
     None => { },
-    option if option.take().is_none() => { /* impossible, option is `Some` */ },
+    option if option.take().is_none() => {
+        /* impossible, option is `Some` */
+    },
     Some(_) => { } // When the previous match failed, the option became `None`.
 }
 ```
@@ -1615,12 +1677,29 @@ See also https://github.com/rust-lang/rust/issues/14587
 
 E0306: r##"
 In an array literal `[x; N]`, `N` is the number of elements in the array. This
-number cannot be negative.
+must be an unsigned integer. Erroneous code example:
+
+```compile_fail
+let x = [0i32; true]; // error: expected positive integer for repeat count,
+                      //        found boolean
+```
+
+Working example:
+
+```
+let x = [0i32; 2];
+```
 "##,
 
 E0307: r##"
-The length of an array is part of its type. For this reason, this length must be
-a compile-time constant.
+The length of an array is part of its type. For this reason, this length must
+be a compile-time constant. Erroneous code example:
+
+```compile_fail
+    let len = 10;
+    let x = [0i32; len]; // error: expected constant integer for repeat count,
+                         //        found variable
+```
 "##,
 
 E0308: r##"
@@ -1713,24 +1792,22 @@ struct Foo<T: 'static> {
 "##,
 
 E0398: r##"
-In Rust 1.3, the default object lifetime bounds are expected to
-change, as described in RFC #1156 [1]. You are getting a warning
-because the compiler thinks it is possible that this change will cause
-a compilation error in your code. It is possible, though unlikely,
-that this is a false alarm.
-
-The heart of the change is that where `&'a Box<SomeTrait>` used to
-default to `&'a Box<SomeTrait+'a>`, it now defaults to `&'a
-Box<SomeTrait+'static>` (here, `SomeTrait` is the name of some trait
-type). Note that the only types which are affected are references to
-boxes, like `&Box<SomeTrait>` or `&[Box<SomeTrait>]`.  More common
-types like `&SomeTrait` or `Box<SomeTrait>` are unaffected.
-
-To silence this warning, edit your code to use an explicit bound.
-Most of the time, this means that you will want to change the
-signature of a function that you are calling. For example, if
-the error is reported on a call like `foo(x)`, and `foo` is
-defined as follows:
+In Rust 1.3, the default object lifetime bounds are expected to change, as
+described in RFC #1156 [1]. You are getting a warning because the compiler
+thinks it is possible that this change will cause a compilation error in your
+code. It is possible, though unlikely, that this is a false alarm.
+
+The heart of the change is that where `&'a Box<SomeTrait>` used to default to
+`&'a Box<SomeTrait+'a>`, it now defaults to `&'a Box<SomeTrait+'static>` (here,
+`SomeTrait` is the name of some trait type). Note that the only types which are
+affected are references to boxes, like `&Box<SomeTrait>` or
+`&[Box<SomeTrait>]`. More common types like `&SomeTrait` or `Box<SomeTrait>`
+are unaffected.
+
+To silence this warning, edit your code to use an explicit bound. Most of the
+time, this means that you will want to change the signature of a function that
+you are calling. For example, if the error is reported on a call like `foo(x)`,
+and `foo` is defined as follows:
 
 ```ignore
 fn foo(arg: &Box<SomeTrait>) { ... }
@@ -1742,8 +1819,8 @@ You might change it to:
 fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
 ```
 
-This explicitly states that you expect the trait object `SomeTrait` to
-contain references (with a maximum lifetime of `'a`).
+This explicitly states that you expect the trait object `SomeTrait` to contain
+references (with a maximum lifetime of `'a`).
 
 [1]: https://github.com/rust-lang/rfcs/pull/1156
 "##,
@@ -1812,8 +1889,8 @@ Also, for now, it is not possible to write deprecation messages either.
 "##,
 
 E0517: r##"
-This error indicates that a `#[repr(..)]` attribute was placed on an unsupported
-item.
+This error indicates that a `#[repr(..)]` attribute was placed on an
+unsupported item.
 
 Examples of erroneous code:
 
@@ -1829,29 +1906,29 @@ struct Foo {bar: bool, baz: bool}
 
 #[repr(C)]
 impl Foo {
-    ...
+    // ...
 }
 ```
 
- - The `#[repr(C)]` attribute can only be placed on structs and enums
- - The `#[repr(packed)]` and `#[repr(simd)]` attributes only work on structs
- - The `#[repr(u8)]`, `#[repr(i16)]`, etc attributes only work on enums
+* The `#[repr(C)]` attribute can only be placed on structs and enums.
+* The `#[repr(packed)]` and `#[repr(simd)]` attributes only work on structs.
+* The `#[repr(u8)]`, `#[repr(i16)]`, etc attributes only work on enums.
 
 These attributes do not work on typedefs, since typedefs are just aliases.
 
 Representations like `#[repr(u8)]`, `#[repr(i64)]` are for selecting the
-discriminant size for C-like enums (when there is no associated data, e.g. `enum
-Color {Red, Blue, Green}`), effectively setting the size of the enum to the size
-of the provided type. Such an enum can be cast to a value of the same type as
-well. In short, `#[repr(u8)]` makes the enum behave like an integer with a
-constrained set of allowed values.
+discriminant size for C-like enums (when there is no associated data, e.g.
+`enum Color {Red, Blue, Green}`), effectively setting the size of the enum to
+the size of the provided type. Such an enum can be cast to a value of the same
+type as well. In short, `#[repr(u8)]` makes the enum behave like an integer
+with a constrained set of allowed values.
 
 Only C-like enums can be cast to numerical primitives, so this attribute will
 not apply to structs.
 
 `#[repr(packed)]` reduces padding to make the struct size smaller. The
-representation of enums isn't strictly defined in Rust, and this attribute won't
-work on enums.
+representation of enums isn't strictly defined in Rust, and this attribute
+won't work on enums.
 
 `#[repr(simd)]` will give a struct consisting of a homogenous series of machine
 types (i.e. `u8`, `i32`, etc) a representation that permits vectorization via
@@ -1860,8 +1937,8 @@ single list of data.
 "##,
 
 E0518: r##"
-This error indicates that an `#[inline(..)]` attribute was incorrectly placed on
-something other than a function or method.
+This error indicates that an `#[inline(..)]` attribute was incorrectly placed
+on something other than a function or method.
 
 Examples of erroneous code:
 
@@ -1871,7 +1948,7 @@ struct Foo;
 
 #[inline(never)]
 impl Foo {
-    ...
+    // ...
 }
 ```
 
diff --git a/src/librustc/front/check_attr.rs b/src/librustc/front/check_attr.rs
index cfd9d5bdaa7..085acc198d1 100644
--- a/src/librustc/front/check_attr.rs
+++ b/src/librustc/front/check_attr.rs
@@ -101,6 +101,7 @@ impl<'a, 'v> Visitor<'v> for CheckAttrVisitor<'a> {
         for attr in &item.attrs {
             self.check_attribute(attr, target);
         }
+        visit::walk_item(self, item);
     }
 }
 
diff --git a/src/librustc/front/map/collector.rs b/src/librustc/front/map/collector.rs
index 8ffc343c8f4..3c4f682ad95 100644
--- a/src/librustc/front/map/collector.rs
+++ b/src/librustc/front/map/collector.rs
@@ -262,7 +262,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
 
     fn visit_pat(&mut self, pat: &'ast Pat) {
         let maybe_binding = match pat.node {
-            PatIdent(_, id, _) => Some(id.node),
+            PatKind::Ident(_, id, _) => Some(id.node),
             _ => None
         };
 
diff --git a/src/librustc/front/map/mod.rs b/src/librustc/front/map/mod.rs
index 310e3417493..adf14d0d89c 100644
--- a/src/librustc/front/map/mod.rs
+++ b/src/librustc/front/map/mod.rs
@@ -325,7 +325,17 @@ impl<'ast> Map<'ast> {
                     return DepNode::Krate,
 
                 NotPresent =>
-                    panic!("Walking parents from `{}` led to `NotPresent` at `{}`", id0, id),
+                    // Some nodes, notably struct fields, are not
+                    // present in the map for whatever reason, but
+                    // they *do* have def-ids. So if we encounter an
+                    // empty hole, check for that case.
+                    return self.opt_local_def_id(id)
+                               .map(|def_id| DepNode::Hir(def_id))
+                               .unwrap_or_else(|| {
+                                   panic!("Walking parents from `{}` \
+                                           led to `NotPresent` at `{}`",
+                                          id0, id)
+                               }),
             }
         }
     }
@@ -615,7 +625,7 @@ impl<'ast> Map<'ast> {
             NodeVariant(v) => PathName(v.node.name),
             NodeLifetime(lt) => PathName(lt.name),
             NodeTyParam(tp) => PathName(tp.name),
-            NodeLocal(&Pat { node: PatIdent(_,l,_), .. }) => {
+            NodeLocal(&Pat { node: PatKind::Ident(_,l,_), .. }) => {
                 PathName(l.node.name)
             },
             _ => panic!("no path elem for {:?}", node)
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 53fd867e7fd..4ff3b21dc83 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -26,9 +26,9 @@
 #![feature(associated_consts)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(cell_extras)]
 #![feature(collections)]
 #![feature(const_fn)]
+#![feature(copy_from_slice)]
 #![feature(enumset)]
 #![feature(iter_arith)]
 #![feature(libc)]
@@ -36,11 +36,9 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(scoped_tls)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(str_char)]
-#![feature(time2)]
 #![cfg_attr(test, feature(test))]
 
 extern crate arena;
@@ -51,7 +49,7 @@ extern crate getopts;
 extern crate graphviz;
 extern crate libc;
 extern crate rbml;
-extern crate rustc_llvm;
+pub extern crate rustc_llvm as llvm;
 extern crate rustc_back;
 extern crate rustc_front;
 extern crate rustc_data_structures;
@@ -66,8 +64,6 @@ extern crate serialize as rustc_serialize; // used by deriving
 #[cfg(test)]
 extern crate test;
 
-pub use rustc_llvm as llvm;
-
 #[macro_use]
 mod macros;
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 3676e230646..4bb69a2688a 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -125,6 +125,12 @@ declare_lint! {
 }
 
 declare_lint! {
+    pub INACCESSIBLE_EXTERN_CRATE,
+    Warn,
+    "use of inaccessible extern crate erroneously allowed"
+}
+
+declare_lint! {
     pub INVALID_TYPE_PARAM_DEFAULT,
     Warn,
     "type parameter default erroneously allowed in invalid location"
@@ -132,7 +138,7 @@ declare_lint! {
 
 declare_lint! {
     pub MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
-    Warn,
+    Deny,
     "unit struct or enum variant erroneously allowed to match via path::ident(..)"
 }
 
@@ -167,6 +173,7 @@ impl LintPass for HardwiredLints {
             TRIVIAL_CASTS,
             TRIVIAL_NUMERIC_CASTS,
             PRIVATE_IN_PUBLIC,
+            INACCESSIBLE_EXTERN_CRATE,
             INVALID_TYPE_PARAM_DEFAULT,
             MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT,
             CONST_ERR,
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index ea74e74a863..d138ab101b5 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -766,6 +766,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
         self.with_lint_attrs(&it.attrs, |cx| {
             run_lints!(cx, check_foreign_item, late_passes, it);
             hir_visit::walk_foreign_item(cx, it);
+            run_lints!(cx, check_foreign_item_post, late_passes, it);
         })
     }
 
@@ -795,6 +796,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
                 body: &'v hir::Block, span: Span, id: ast::NodeId) {
         run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
         hir_visit::walk_fn(self, fk, decl, body, span);
+        run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id);
     }
 
     fn visit_variant_data(&mut self,
@@ -835,6 +837,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
     fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) {
         run_lints!(self, check_mod, late_passes, m, s, n);
         hir_visit::walk_mod(self, m);
+        run_lints!(self, check_mod_post, late_passes, m, s, n);
     }
 
     fn visit_local(&mut self, l: &hir::Local) {
@@ -874,6 +877,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
             run_lints!(cx, check_trait_item, late_passes, trait_item);
             cx.visit_ids(|v| v.visit_trait_item(trait_item));
             hir_visit::walk_trait_item(cx, trait_item);
+            run_lints!(cx, check_trait_item_post, late_passes, trait_item);
         });
     }
 
@@ -882,6 +886,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
             run_lints!(cx, check_impl_item, late_passes, impl_item);
             cx.visit_ids(|v| v.visit_impl_item(impl_item));
             hir_visit::walk_impl_item(cx, impl_item);
+            run_lints!(cx, check_impl_item_post, late_passes, impl_item);
         });
     }
 
@@ -928,6 +933,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
         self.with_lint_attrs(&it.attrs, |cx| {
             run_lints!(cx, check_foreign_item, early_passes, it);
             ast_visit::walk_foreign_item(cx, it);
+            run_lints!(cx, check_foreign_item_post, early_passes, it);
         })
     }
 
@@ -952,6 +958,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
                 body: &'v ast::Block, span: Span, id: ast::NodeId) {
         run_lints!(self, check_fn, early_passes, fk, decl, body, span, id);
         ast_visit::walk_fn(self, fk, decl, body, span);
+        run_lints!(self, check_fn_post, early_passes, fk, decl, body, span, id);
     }
 
     fn visit_variant_data(&mut self,
@@ -992,6 +999,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
     fn visit_mod(&mut self, m: &ast::Mod, s: Span, n: ast::NodeId) {
         run_lints!(self, check_mod, early_passes, m, s, n);
         ast_visit::walk_mod(self, m);
+        run_lints!(self, check_mod_post, early_passes, m, s, n);
     }
 
     fn visit_local(&mut self, l: &ast::Local) {
@@ -1031,6 +1039,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
             run_lints!(cx, check_trait_item, early_passes, trait_item);
             cx.visit_ids(|v| v.visit_trait_item(trait_item));
             ast_visit::walk_trait_item(cx, trait_item);
+            run_lints!(cx, check_trait_item_post, early_passes, trait_item);
         });
     }
 
@@ -1039,6 +1048,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
             run_lints!(cx, check_impl_item, early_passes, impl_item);
             cx.visit_ids(|v| v.visit_impl_item(impl_item));
             ast_visit::walk_impl_item(cx, impl_item);
+            run_lints!(cx, check_impl_item_post, early_passes, impl_item);
         });
     }
 
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 5e2e8c4c6d5..133d0163a8c 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -134,7 +134,9 @@ pub trait LateLintPass: LintPass {
     fn check_crate(&mut self, _: &LateContext, _: &hir::Crate) { }
     fn check_crate_post(&mut self, _: &LateContext, _: &hir::Crate) { }
     fn check_mod(&mut self, _: &LateContext, _: &hir::Mod, _: Span, _: ast::NodeId) { }
+    fn check_mod_post(&mut self, _: &LateContext, _: &hir::Mod, _: Span, _: ast::NodeId) { }
     fn check_foreign_item(&mut self, _: &LateContext, _: &hir::ForeignItem) { }
+    fn check_foreign_item_post(&mut self, _: &LateContext, _: &hir::ForeignItem) { }
     fn check_item(&mut self, _: &LateContext, _: &hir::Item) { }
     fn check_item_post(&mut self, _: &LateContext, _: &hir::Item) { }
     fn check_local(&mut self, _: &LateContext, _: &hir::Local) { }
@@ -150,8 +152,12 @@ pub trait LateLintPass: LintPass {
     fn check_generics(&mut self, _: &LateContext, _: &hir::Generics) { }
     fn check_fn(&mut self, _: &LateContext,
         _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { }
+    fn check_fn_post(&mut self, _: &LateContext,
+        _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { }
     fn check_trait_item(&mut self, _: &LateContext, _: &hir::TraitItem) { }
+    fn check_trait_item_post(&mut self, _: &LateContext, _: &hir::TraitItem) { }
     fn check_impl_item(&mut self, _: &LateContext, _: &hir::ImplItem) { }
+    fn check_impl_item_post(&mut self, _: &LateContext, _: &hir::ImplItem) { }
     fn check_struct_def(&mut self, _: &LateContext,
         _: &hir::VariantData, _: ast::Name, _: &hir::Generics, _: ast::NodeId) { }
     fn check_struct_def_post(&mut self, _: &LateContext,
@@ -179,7 +185,9 @@ pub trait EarlyLintPass: LintPass {
     fn check_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { }
     fn check_crate_post(&mut self, _: &EarlyContext, _: &ast::Crate) { }
     fn check_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { }
+    fn check_mod_post(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { }
     fn check_foreign_item(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { }
+    fn check_foreign_item_post(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { }
     fn check_item(&mut self, _: &EarlyContext, _: &ast::Item) { }
     fn check_item_post(&mut self, _: &EarlyContext, _: &ast::Item) { }
     fn check_local(&mut self, _: &EarlyContext, _: &ast::Local) { }
@@ -195,8 +203,12 @@ pub trait EarlyLintPass: LintPass {
     fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { }
     fn check_fn(&mut self, _: &EarlyContext,
         _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
+    fn check_fn_post(&mut self, _: &EarlyContext,
+        _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
     fn check_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { }
+    fn check_trait_item_post(&mut self, _: &EarlyContext, _: &ast::TraitItem) { }
     fn check_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { }
+    fn check_impl_item_post(&mut self, _: &EarlyContext, _: &ast::ImplItem) { }
     fn check_struct_def(&mut self, _: &EarlyContext,
         _: &ast::VariantData, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
     fn check_struct_def_post(&mut self, _: &EarlyContext,
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 6142f14db3e..701a4596908 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -16,7 +16,7 @@ use middle::ty;
 use syntax::ast;
 use syntax::ptr::P;
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 
 struct CFGBuilder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
@@ -99,35 +99,36 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
 
     fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
         match pat.node {
-            hir::PatIdent(_, _, None) |
-            hir::PatEnum(_, None) |
-            hir::PatQPath(..) |
-            hir::PatLit(..) |
-            hir::PatRange(..) |
-            hir::PatWild => {
+            PatKind::Ident(_, _, None) |
+            PatKind::TupleStruct(_, None) |
+            PatKind::Path(..) |
+            PatKind::QPath(..) |
+            PatKind::Lit(..) |
+            PatKind::Range(..) |
+            PatKind::Wild => {
                 self.add_ast_node(pat.id, &[pred])
             }
 
-            hir::PatBox(ref subpat) |
-            hir::PatRegion(ref subpat, _) |
-            hir::PatIdent(_, _, Some(ref subpat)) => {
+            PatKind::Box(ref subpat) |
+            PatKind::Ref(ref subpat, _) |
+            PatKind::Ident(_, _, Some(ref subpat)) => {
                 let subpat_exit = self.pat(&subpat, pred);
                 self.add_ast_node(pat.id, &[subpat_exit])
             }
 
-            hir::PatEnum(_, Some(ref subpats)) |
-            hir::PatTup(ref subpats) => {
+            PatKind::TupleStruct(_, Some(ref subpats)) |
+            PatKind::Tup(ref subpats) => {
                 let pats_exit = self.pats_all(subpats.iter(), pred);
                 self.add_ast_node(pat.id, &[pats_exit])
             }
 
-            hir::PatStruct(_, ref subpats, _) => {
+            PatKind::Struct(_, ref subpats, _) => {
                 let pats_exit =
                     self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
                 self.add_ast_node(pat.id, &[pats_exit])
             }
 
-            hir::PatVec(ref pre, ref vec, ref post) => {
+            PatKind::Vec(ref pre, ref vec, ref post) => {
                 let pre_exit = self.pats_all(pre.iter(), pred);
                 let vec_exit = self.pats_all(vec.iter(), pre_exit);
                 let post_exit = self.pats_all(post.iter(), vec_exit);
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index a32f5b8797d..246a4e9f28f 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -32,7 +32,7 @@ use std::fmt;
 use std::iter::{FromIterator, IntoIterator, repeat};
 
 use rustc_front::hir;
-use rustc_front::hir::Pat;
+use rustc_front::hir::{Pat, PatKind};
 use rustc_front::intravisit::{self, Visitor, FnKind};
 use rustc_front::util as front_util;
 use rustc_back::slice;
@@ -47,7 +47,7 @@ use util::nodemap::FnvHashMap;
 
 pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
     id: DUMMY_NODE_ID,
-    node: hir::PatWild,
+    node: PatKind::Wild,
     span: DUMMY_SP
 };
 
@@ -242,7 +242,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
 fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) {
     front_util::walk_pat(pat, |p| {
         match p.node {
-            hir::PatIdent(hir::BindByValue(hir::MutImmutable), ident, None) => {
+            PatKind::Ident(hir::BindByValue(hir::MutImmutable), ident, None) => {
                 let pat_ty = cx.tcx.pat_ty(p);
                 if let ty::TyEnum(edef, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
@@ -274,7 +274,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
 // Check that we do not match against a static NaN (#6804)
 fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
     front_util::walk_pat(pat, |p| {
-        if let hir::PatLit(ref expr) = p.node {
+        if let PatKind::Lit(ref expr) = p.node {
             match eval_const_expr_partial(cx.tcx, &expr, ExprTypeChecked, None) {
                 Ok(ConstVal::Float(f)) if f.is_nan() => {
                     span_warn!(cx.tcx.sess, p.span, E0003,
@@ -360,7 +360,7 @@ fn check_arms(cx: &MatchCheckCtxt,
 
 fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
     match p.node {
-        hir::PatIdent(_, _, Some(ref s)) => raw_pat(&s),
+        PatKind::Ident(_, _, Some(ref s)) => raw_pat(&s),
         _ => p
     }
 }
@@ -377,7 +377,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir:
                 hir::MatchSource::ForLoopDesugar => {
                     // `witnesses[0]` has the form `Some(<head>)`, peel off the `Some`
                     let witness = match witnesses[0].node {
-                        hir::PatEnum(_, Some(ref pats)) => match &pats[..] {
+                        PatKind::TupleStruct(_, Some(ref pats)) => match &pats[..] {
                             [ref pat] => &**pat,
                             _ => unreachable!(),
                         },
@@ -466,7 +466,7 @@ impl<'map> ast_util::IdVisitingOperation for RenamingRecorder<'map> {
 impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
     fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
         return match pat.node {
-            hir::PatIdent(..) | hir::PatEnum(..) | hir::PatQPath(..) => {
+            PatKind::Ident(..) | PatKind::Path(..) | PatKind::QPath(..) => {
                 let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
                     Some(Def::AssociatedConst(did)) |
@@ -530,26 +530,32 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
     let pats_len = pats.len();
     let mut pats = pats.into_iter().map(|p| P((*p).clone()));
     let pat = match left_ty.sty {
-        ty::TyTuple(_) => hir::PatTup(pats.collect()),
+        ty::TyTuple(_) => PatKind::Tup(pats.collect()),
 
         ty::TyEnum(adt, _) | ty::TyStruct(adt, _)  => {
             let v = adt.variant_of_ctor(ctor);
-            if let VariantKind::Struct = v.kind() {
-                let field_pats: hir::HirVec<_> = v.fields.iter()
-                    .zip(pats)
-                    .filter(|&(_, ref pat)| pat.node != hir::PatWild)
-                    .map(|(field, pat)| Spanned {
-                        span: DUMMY_SP,
-                        node: hir::FieldPat {
-                            name: field.name,
-                            pat: pat,
-                            is_shorthand: false,
-                        }
-                    }).collect();
-                let has_more_fields = field_pats.len() < pats_len;
-                hir::PatStruct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
-            } else {
-                hir::PatEnum(def_to_path(cx.tcx, v.did), Some(pats.collect()))
+            match v.kind() {
+                VariantKind::Struct => {
+                    let field_pats: hir::HirVec<_> = v.fields.iter()
+                        .zip(pats)
+                        .filter(|&(_, ref pat)| pat.node != PatKind::Wild)
+                        .map(|(field, pat)| Spanned {
+                            span: DUMMY_SP,
+                            node: hir::FieldPat {
+                                name: field.name,
+                                pat: pat,
+                                is_shorthand: false,
+                            }
+                        }).collect();
+                    let has_more_fields = field_pats.len() < pats_len;
+                    PatKind::Struct(def_to_path(cx.tcx, v.did), field_pats, has_more_fields)
+                }
+                VariantKind::Tuple => {
+                    PatKind::TupleStruct(def_to_path(cx.tcx, v.did), Some(pats.collect()))
+                }
+                VariantKind::Unit => {
+                    PatKind::Path(def_to_path(cx.tcx, v.did))
+                }
             }
         }
 
@@ -558,35 +564,35 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
                ty::TyArray(_, n) => match ctor {
                     &Single => {
                         assert_eq!(pats_len, n);
-                        hir::PatVec(pats.collect(), None, hir::HirVec::new())
+                        PatKind::Vec(pats.collect(), None, hir::HirVec::new())
                     },
                     _ => unreachable!()
                 },
                 ty::TySlice(_) => match ctor {
                     &Slice(n) => {
                         assert_eq!(pats_len, n);
-                        hir::PatVec(pats.collect(), None, hir::HirVec::new())
+                        PatKind::Vec(pats.collect(), None, hir::HirVec::new())
                     },
                     _ => unreachable!()
                 },
-                ty::TyStr => hir::PatWild,
+                ty::TyStr => PatKind::Wild,
 
                 _ => {
                     assert_eq!(pats_len, 1);
-                    hir::PatRegion(pats.nth(0).unwrap(), mutbl)
+                    PatKind::Ref(pats.nth(0).unwrap(), mutbl)
                 }
             }
         }
 
         ty::TyArray(_, len) => {
             assert_eq!(pats_len, len);
-            hir::PatVec(pats.collect(), None, hir::HirVec::new())
+            PatKind::Vec(pats.collect(), None, hir::HirVec::new())
         }
 
         _ => {
             match *ctor {
-                ConstantValue(ref v) => hir::PatLit(const_val_to_expr(v)),
-                _ => hir::PatWild,
+                ConstantValue(ref v) => PatKind::Lit(const_val_to_expr(v)),
+                _ => PatKind::Wild,
             }
         }
     };
@@ -682,7 +688,7 @@ fn is_useful(cx: &MatchCheckCtxt,
         let left_ty = cx.tcx.pat_ty(&real_pat);
 
         match real_pat.node {
-            hir::PatIdent(hir::BindByRef(..), _, _) => {
+            PatKind::Ident(hir::BindByRef(..), _, _) => {
                 left_ty.builtin_deref(false, NoPreference).unwrap().ty
             }
             _ => left_ty,
@@ -690,7 +696,7 @@ fn is_useful(cx: &MatchCheckCtxt,
     };
 
     let max_slice_length = rows.iter().filter_map(|row| match row[0].node {
-        hir::PatVec(ref before, _, ref after) => Some(before.len() + after.len()),
+        PatKind::Vec(ref before, _, ref after) => Some(before.len() + after.len()),
         _ => None
     }).max().map_or(0, |v| v + 1);
 
@@ -769,39 +775,25 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                     left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
     let pat = raw_pat(p);
     match pat.node {
-        hir::PatIdent(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
-                    cx.tcx.sess.span_bug(pat.span, "const pattern should've \
-                                                    been rewritten"),
-                Some(Def::Struct(..)) => vec!(Single),
-                Some(Def::Variant(_, id)) => vec!(Variant(id)),
-                _ => vec!()
-            },
-        hir::PatEnum(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
+        PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::Ident(..) =>
+            match cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def() {
+                Def::Const(..) | Def::AssociatedConst(..) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(Def::Variant(_, id)) => vec!(Variant(id)),
-                _ => vec!(Single)
+                Def::Struct(..) | Def::TyAlias(..) => vec![Single],
+                Def::Variant(_, id) => vec![Variant(id)],
+                Def::Local(..) => vec![],
+                def => cx.tcx.sess.span_bug(pat.span, &format!("pat_constructors: unexpected \
+                                                                definition {:?}", def)),
             },
-        hir::PatQPath(..) =>
+        PatKind::QPath(..) =>
             cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                             been rewritten"),
-        hir::PatStruct(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
-                    cx.tcx.sess.span_bug(pat.span, "const pattern should've \
-                                                    been rewritten"),
-                Some(Def::Variant(_, id)) => vec!(Variant(id)),
-                _ => vec!(Single)
-            },
-        hir::PatLit(ref expr) =>
+        PatKind::Lit(ref expr) =>
             vec!(ConstantValue(eval_const_expr(cx.tcx, &expr))),
-        hir::PatRange(ref lo, ref hi) =>
+        PatKind::Range(ref lo, ref hi) =>
             vec!(ConstantRange(eval_const_expr(cx.tcx, &lo), eval_const_expr(cx.tcx, &hi))),
-        hir::PatVec(ref before, ref slice, ref after) =>
+        PatKind::Vec(ref before, ref slice, ref after) =>
             match left_ty.sty {
                 ty::TyArray(_, _) => vec!(Single),
                 _                      => if slice.is_some() {
@@ -812,9 +804,9 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                     vec!(Slice(before.len() + after.len()))
                 }
             },
-        hir::PatBox(_) | hir::PatTup(_) | hir::PatRegion(..) =>
+        PatKind::Box(_) | PatKind::Tup(_) | PatKind::Ref(..) =>
             vec!(Single),
-        hir::PatWild =>
+        PatKind::Wild =>
             vec!(),
     }
 }
@@ -877,25 +869,24 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         id: pat_id, ref node, span: pat_span
     } = raw_pat(r[col]);
     let head: Option<Vec<&Pat>> = match *node {
-        hir::PatWild =>
+        PatKind::Wild =>
             Some(vec![DUMMY_WILD_PAT; arity]),
 
-        hir::PatIdent(_, _, _) => {
-            let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
-            match opt_def {
-                Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) =>
+        PatKind::Path(..) | PatKind::Ident(..) => {
+            let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
+            match def {
+                Def::Const(..) | Def::AssociatedConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
-                Some(Def::Variant(_, id)) => if *constructor == Variant(id) {
-                    Some(vec!())
-                } else {
-                    None
-                },
-                _ => Some(vec![DUMMY_WILD_PAT; arity])
+                Def::Variant(_, id) if *constructor != Variant(id) => None,
+                Def::Variant(..) | Def::Struct(..) => Some(Vec::new()),
+                Def::Local(..) => Some(vec![DUMMY_WILD_PAT; arity]),
+                _ => cx.tcx.sess.span_bug(pat_span, &format!("specialize: unexpected \
+                                                              definition {:?}", def)),
             }
         }
 
-        hir::PatEnum(_, ref args) => {
+        PatKind::TupleStruct(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
                 Def::Const(..) | Def::AssociatedConst(..) =>
@@ -912,12 +903,12 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        hir::PatQPath(_, _) => {
+        PatKind::QPath(_, _) => {
             cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                             been rewritten")
         }
 
-        hir::PatStruct(_, ref pattern_fields, _) => {
+        PatKind::Struct(_, ref pattern_fields, _) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
             let variant = adt.variant_of_ctor(constructor);
@@ -934,13 +925,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        hir::PatTup(ref args) =>
+        PatKind::Tup(ref args) =>
             Some(args.iter().map(|p| &**p).collect()),
 
-        hir::PatBox(ref inner) | hir::PatRegion(ref inner, _) =>
+        PatKind::Box(ref inner) | PatKind::Ref(ref inner, _) =>
             Some(vec![&**inner]),
 
-        hir::PatLit(ref expr) => {
+        PatKind::Lit(ref expr) => {
             let expr_value = eval_const_expr(cx.tcx, &expr);
             match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
                 Some(true) => Some(vec![]),
@@ -952,7 +943,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        hir::PatRange(ref from, ref to) => {
+        PatKind::Range(ref from, ref to) => {
             let from_value = eval_const_expr(cx.tcx, &from);
             let to_value = eval_const_expr(cx.tcx, &to);
             match range_covered_by_constructor(constructor, &from_value, &to_value) {
@@ -965,7 +956,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
-        hir::PatVec(ref before, ref slice, ref after) => {
+        PatKind::Vec(ref before, ref slice, ref after) => {
             match *constructor {
                 // Fixed-length vectors.
                 Single => {
@@ -1104,7 +1095,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
         front_util::walk_pat(&pat, |p| {
             if pat_is_binding(&def_map.borrow(), &p) {
                 match p.node {
-                    hir::PatIdent(hir::BindByValue(_), _, ref sub) => {
+                    PatKind::Ident(hir::BindByValue(_), _, ref sub) => {
                         let pat_ty = tcx.node_id_to_type(p.id);
                         //FIXME: (@jroesch) this code should be floated up as well
                         let infcx = infer::new_infer_ctxt(cx.tcx,
@@ -1114,7 +1105,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
                     }
-                    hir::PatIdent(hir::BindByRef(_), _, _) => {
+                    PatKind::Ident(hir::BindByRef(_), _, _) => {
                     }
                     _ => {
                         cx.tcx.sess.span_bug(
@@ -1202,7 +1193,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
         }
 
         match pat.node {
-            hir::PatIdent(_, _, Some(_)) => {
+            PatKind::Ident(_, _, Some(_)) => {
                 let bindings_were_allowed = self.bindings_allowed;
                 self.bindings_allowed = false;
                 intravisit::walk_pat(self, pat);
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index f9922f725c6..9ec79c84afb 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -30,7 +30,7 @@ use session::Session;
 
 use graphviz::IntoCow;
 use syntax::ast;
-use rustc_front::hir::Expr;
+use rustc_front::hir::{Expr, PatKind};
 use rustc_front::hir;
 use rustc_front::intravisit::FnKind;
 use syntax::codemap::Span;
@@ -325,7 +325,7 @@ impl ConstVal {
 pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat> {
     let pat = match expr.node {
         hir::ExprTup(ref exprs) =>
-            hir::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &expr, span)).collect()),
+            PatKind::Tup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &expr, span)).collect()),
 
         hir::ExprCall(ref callee, ref args) => {
             let def = *tcx.def_map.borrow().get(&callee.id).unwrap();
@@ -337,13 +337,13 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
                 Def::Variant(_, variant_did) => def_to_path(tcx, variant_did),
                 Def::Fn(..) => return P(hir::Pat {
                     id: expr.id,
-                    node: hir::PatLit(P(expr.clone())),
+                    node: PatKind::Lit(P(expr.clone())),
                     span: span,
                 }),
                 _ => unreachable!()
             };
             let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &expr, span)).collect();
-            hir::PatEnum(path, Some(pats))
+            PatKind::TupleStruct(path, Some(pats))
         }
 
         hir::ExprStruct(ref path, ref fields, None) => {
@@ -355,21 +355,19 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
                     is_shorthand: false,
                 },
             }).collect();
-            hir::PatStruct(path.clone(), field_pats, false)
+            PatKind::Struct(path.clone(), field_pats, false)
         }
 
         hir::ExprVec(ref exprs) => {
             let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &expr, span)).collect();
-            hir::PatVec(pats, None, hir::HirVec::new())
+            PatKind::Vec(pats, None, hir::HirVec::new())
         }
 
         hir::ExprPath(_, ref path) => {
             let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
             match opt_def {
-                Some(Def::Struct(..)) =>
-                    hir::PatStruct(path.clone(), hir::HirVec::new(), false),
-                Some(Def::Variant(..)) =>
-                    hir::PatEnum(path.clone(), None),
+                Some(Def::Struct(..)) | Some(Def::Variant(..)) =>
+                    PatKind::Path(path.clone()),
                 Some(Def::Const(def_id)) |
                 Some(Def::AssociatedConst(def_id)) => {
                     let expr = lookup_const_by_id(tcx, def_id, Some(expr.id), None).unwrap();
@@ -379,7 +377,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
             }
         }
 
-        _ => hir::PatLit(P(expr.clone()))
+        _ => PatKind::Lit(P(expr.clone()))
     };
     P(hir::Pat { id: expr.id, node: pat, span: span })
 }
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 5de192ca4eb..3b72685eca3 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -448,6 +448,7 @@ pub mod tls {
     use rbml::opaque::Encoder as OpaqueEncoder;
     use rbml::opaque::Decoder as OpaqueDecoder;
     use serialize;
+    use std::cell::Cell;
     use std::mem;
     use middle::ty::{self, Ty};
     use middle::subst::Substs;
@@ -459,12 +460,14 @@ pub mod tls {
         fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>);
     }
 
-    /// Marker type used for the scoped TLS slot.
-    /// The type context cannot be used directly because the scoped TLS
+    /// Marker type used for the TLS slot.
+    /// The type context cannot be used directly because the TLS
     /// in libstd doesn't allow types generic over lifetimes.
     struct TlsPayload;
 
-    scoped_thread_local!(static TLS_ENCODING: TlsPayload);
+    thread_local! {
+        static TLS_ENCODING: Cell<Option<*const TlsPayload>> = Cell::new(None)
+    }
 
     /// Execute f after pushing the given EncodingContext onto the TLS stack.
     pub fn enter_encoding_context<'tcx, F, R>(ecx: &EncodingContext<'tcx>,
@@ -474,7 +477,13 @@ pub mod tls {
     {
         let tls_payload = (ecx as *const _, encoder as *mut _);
         let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
-        TLS_ENCODING.set(unsafe { &*tls_ptr }, || f(ecx, encoder))
+        TLS_ENCODING.with(|tls| {
+            let prev = tls.get();
+            tls.set(Some(tls_ptr));
+            let ret = f(ecx, encoder);
+            tls.set(prev);
+            return ret
+        })
     }
 
     /// Execute f with access to the thread-local encoding context and
@@ -506,8 +515,8 @@ pub mod tls {
         where F: FnOnce(&EncodingContext, &mut OpaqueEncoder) -> R
     {
         TLS_ENCODING.with(|tls| {
-            let tls_payload = (tls as *const TlsPayload)
-                                   as *mut (&EncodingContext, &mut OpaqueEncoder);
+            let tls = tls.get().unwrap();
+            let tls_payload = tls as *mut (&EncodingContext, &mut OpaqueEncoder);
             f((*tls_payload).0, (*tls_payload).1)
         })
     }
@@ -519,7 +528,9 @@ pub mod tls {
         fn translate_def_id(&self, def_id: DefId) -> DefId;
     }
 
-    scoped_thread_local!(static TLS_DECODING: TlsPayload);
+    thread_local! {
+        static TLS_DECODING: Cell<Option<*const TlsPayload>> = Cell::new(None)
+    }
 
     /// Execute f after pushing the given DecodingContext onto the TLS stack.
     pub fn enter_decoding_context<'tcx, F, R>(dcx: &DecodingContext<'tcx>,
@@ -529,7 +540,13 @@ pub mod tls {
     {
         let tls_payload = (dcx as *const _, decoder as *mut _);
         let tls_ptr = &tls_payload as *const _ as *const TlsPayload;
-        TLS_DECODING.set(unsafe { &*tls_ptr }, || f(dcx, decoder))
+        TLS_DECODING.with(|tls| {
+            let prev = tls.get();
+            tls.set(Some(tls_ptr));
+            let ret = f(dcx, decoder);
+            tls.set(prev);
+            return ret
+        })
     }
 
     /// Execute f with access to the thread-local decoding context and
@@ -563,8 +580,8 @@ pub mod tls {
         where F: FnOnce(&DecodingContext, &mut OpaqueDecoder) -> R
     {
         TLS_DECODING.with(|tls| {
-            let tls_payload = (tls as *const TlsPayload)
-                                   as *mut (&DecodingContext, &mut OpaqueDecoder);
+            let tls = tls.get().unwrap();
+            let tls_payload = tls as *mut (&DecodingContext, &mut OpaqueDecoder);
             f((*tls_payload).0, (*tls_payload).1)
         })
     }
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 933857269cb..3fc45c575f0 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -489,7 +489,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
                 let bits = &mut self.scope_kills[start.. end];
                 debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [before]",
                        self.analysis_name, flow_exit, mut_bits_to_string(bits));
-                bits.clone_from_slice(&orig_kills[..]);
+                bits.copy_from_slice(&orig_kills[..]);
                 debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [after]",
                        self.analysis_name, flow_exit, mut_bits_to_string(bits));
             }
@@ -556,7 +556,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> {
             let (start, end) = self.dfcx.compute_id_range(node_index);
 
             // Initialize local bitvector with state on-entry.
-            in_out.clone_from_slice(&self.dfcx.on_entry[start.. end]);
+            in_out.copy_from_slice(&self.dfcx.on_entry[start.. end]);
 
             // Compute state on-exit by applying transfer function to
             // state on-entry.
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index ae2252b6df6..92372870cd1 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -14,7 +14,7 @@
 
 use dep_graph::DepNode;
 use front::map as ast_map;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::intravisit::{self, Visitor};
 
 use middle::{pat_util, privacy, ty};
@@ -143,7 +143,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             _ => self.tcx.sess.span_bug(lhs.span, "non-ADT in struct pattern")
         };
         for pat in pats {
-            if let hir::PatWild = pat.node.pat.node {
+            if let PatKind::Wild = pat.node.pat.node {
                 continue;
             }
             self.insert_def_id(variant.field_named(pat.node.name).did);
@@ -268,7 +268,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
     fn visit_pat(&mut self, pat: &hir::Pat) {
         let def_map = &self.tcx.def_map;
         match pat.node {
-            hir::PatStruct(_, ref fields, _) => {
+            PatKind::Struct(_, ref fields, _) => {
                 self.handle_field_pattern_match(pat, fields);
             }
             _ if pat_util::pat_is_const(&def_map.borrow(), pat) => {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 5bdb553a2fe..93cc158cd12 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -27,7 +27,7 @@ use middle::mem_categorization as mc;
 use middle::ty;
 use middle::ty::adjustment;
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 
 use syntax::ast;
 use syntax::ptr::P;
@@ -721,10 +721,11 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         if let Some(adjustment) = adj {
             match adjustment {
                 adjustment::AdjustReifyFnPointer |
-                adjustment::AdjustUnsafeFnPointer => {
+                adjustment::AdjustUnsafeFnPointer |
+                adjustment::AdjustMutToConstPointer => {
                     // Creating a closure/fn-pointer or unsizing consumes
                     // the input and stores it into the resulting rvalue.
-                    debug!("walk_adjustment(AdjustReifyFnPointer|AdjustUnsafeFnPointer)");
+                    debug!("walk_adjustment: trivial adjustment");
                     let cmt_unadjusted =
                         return_if_err!(self.mc.cat_expr_unadjusted(expr));
                     self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
@@ -946,9 +947,9 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
             let def_map = &self.tcx().def_map;
             if pat_util::pat_is_binding(&def_map.borrow(), pat) {
                 match pat.node {
-                    hir::PatIdent(hir::BindByRef(_), _, _) =>
+                    PatKind::Ident(hir::BindByRef(_), _, _) =>
                         mode.lub(BorrowingMatch),
-                    hir::PatIdent(hir::BindByValue(_), _, _) => {
+                    PatKind::Ident(hir::BindByValue(_), _, _) => {
                         match copy_or_move(self.typer, &cmt_pat, PatBindingMove) {
                             Copy => mode.lub(CopyingMatch),
                             Move(_) => mode.lub(MovingMatch),
@@ -1002,14 +1003,14 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
 
                 // It is also a borrow or copy/move of the value being matched.
                 match pat.node {
-                    hir::PatIdent(hir::BindByRef(m), _, _) => {
+                    PatKind::Ident(hir::BindByRef(m), _, _) => {
                         if let ty::TyRef(&r, _) = pat_ty.sty {
                             let bk = ty::BorrowKind::from_mutbl(m);
                             delegate.borrow(pat.id, pat.span, cmt_pat,
                                             r, bk, RefBinding);
                         }
                     }
-                    hir::PatIdent(hir::BindByValue(_), _, _) => {
+                    PatKind::Ident(hir::BindByValue(_), _, _) => {
                         let mode = copy_or_move(typer, &cmt_pat, PatBindingMove);
                         debug!("walk_pat binding consuming pat");
                         delegate.consume_pat(pat, cmt_pat, mode);
@@ -1022,7 +1023,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
             } else {
                 match pat.node {
-                    hir::PatVec(_, Some(ref slice_pat), _) => {
+                    PatKind::Vec(_, Some(ref slice_pat), _) => {
                         // The `slice_pat` here creates a slice into
                         // the original vector.  This is effectively a
                         // borrow of the elements of the vector being
@@ -1070,8 +1071,8 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
             let tcx = typer.tcx;
 
             match pat.node {
-                hir::PatEnum(_, _) | hir::PatQPath(..) |
-                hir::PatIdent(_, _, None) | hir::PatStruct(..) => {
+                PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(..) |
+                PatKind::Ident(_, _, None) | PatKind::Struct(..) => {
                     match def_map.get(&pat.id).map(|d| d.full_def()) {
                         None => {
                             // no definition found: pat is not a
@@ -1134,15 +1135,15 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                     }
                 }
 
-                hir::PatIdent(_, _, Some(_)) => {
+                PatKind::Ident(_, _, Some(_)) => {
                     // Do nothing; this is a binding (not an enum
                     // variant or struct), and the cat_pattern call
                     // will visit the substructure recursively.
                 }
 
-                hir::PatWild | hir::PatTup(..) | hir::PatBox(..) |
-                hir::PatRegion(..) | hir::PatLit(..) | hir::PatRange(..) |
-                hir::PatVec(..) => {
+                PatKind::Wild | PatKind::Tup(..) | PatKind::Box(..) |
+                PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) |
+                PatKind::Vec(..) => {
                     // Similarly, each of these cases does not
                     // correspond to an enum variant or struct, so we
                     // do not do any `matched_pat` calls for these
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index a22ad7a0707..6cbb90627ea 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -184,10 +184,13 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
         // Check for duplicates.
         match self.items.items[item_index] {
             Some(original_def_id) if original_def_id != item_def_id => {
+                let cstore = &self.session.cstore;
                 span_err!(self.session, span, E0152,
-                    "duplicate entry for `{}`", LanguageItems::item_name(item_index));
+                          "duplicate entry for `{}`, first definition found in `{}`",
+                          LanguageItems::item_name(item_index),
+                          cstore.crate_name(item_def_id.krate));
             }
-            Some(_) | None => {
+            _ => {
                 // OK.
             }
         }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 71af07c21cf..fef35764e1c 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -79,7 +79,7 @@ use middle::def::Def;
 use middle::ty::adjustment;
 use middle::ty::{self, Ty};
 
-use rustc_front::hir::{MutImmutable, MutMutable};
+use rustc_front::hir::{MutImmutable, MutMutable, PatKind};
 use rustc_front::hir;
 use syntax::ast;
 use syntax::codemap::Span;
@@ -305,7 +305,7 @@ impl MutabilityCategory {
     fn from_local(tcx: &ty::ctxt, id: ast::NodeId) -> MutabilityCategory {
         let ret = match tcx.map.get(id) {
             ast_map::NodeLocal(p) => match p.node {
-                hir::PatIdent(bind_mode, _, _) => {
+                PatKind::Ident(bind_mode, _, _) => {
                     if bind_mode == hir::BindByValue(hir::MutMutable) {
                         McDeclared
                     } else {
@@ -396,7 +396,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         // *being borrowed* is.  But ideally we would put in a more
         // fundamental fix to this conflated use of the node id.
         let ret_ty = match pat.node {
-            hir::PatIdent(hir::BindByRef(_), _, _) => {
+            PatKind::Ident(hir::BindByRef(_), _, _) => {
                 // a bind-by-ref means that the base_ty will be the type of the ident itself,
                 // but what we want here is the type of the underlying value being borrowed.
                 // So peel off one-level, turning the &T into T.
@@ -430,6 +430,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
 
                     adjustment::AdjustReifyFnPointer |
                     adjustment::AdjustUnsafeFnPointer |
+                    adjustment::AdjustMutToConstPointer |
                     adjustment::AdjustDerefRef(_) => {
                         debug!("cat_expr({:?}): {:?}",
                                adjustment,
@@ -1209,7 +1210,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             None
         };
 
-        // Note: This goes up here (rather than within the PatEnum arm
+        // Note: This goes up here (rather than within the PatKind::TupleStruct arm
         // alone) because struct patterns can refer to struct types or
         // to struct variants within enums.
         let cmt = match opt_def {
@@ -1222,14 +1223,14 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         };
 
         match pat.node {
-          hir::PatWild => {
+          PatKind::Wild => {
             // _
           }
 
-          hir::PatEnum(_, None) => {
+          PatKind::TupleStruct(_, None) => {
             // variant(..)
           }
-          hir::PatEnum(_, Some(ref subpats)) => {
+          PatKind::TupleStruct(_, Some(ref subpats)) => {
             match opt_def {
                 Some(Def::Variant(..)) => {
                     // variant(x, y, z)
@@ -1267,19 +1268,15 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }
           }
 
-          hir::PatQPath(..) => {
-              // Lone constant: ignore
+          PatKind::Path(..) | PatKind::QPath(..) | PatKind::Ident(_, _, None) => {
+              // Lone constant, or unit variant or identifier: ignore
           }
 
-          hir::PatIdent(_, _, Some(ref subpat)) => {
+          PatKind::Ident(_, _, Some(ref subpat)) => {
               try!(self.cat_pattern_(cmt, &subpat, op));
           }
 
-          hir::PatIdent(_, _, None) => {
-              // nullary variant or identifier: ignore
-          }
-
-          hir::PatStruct(_, ref field_pats, _) => {
+          PatKind::Struct(_, ref field_pats, _) => {
             // {f1: p1, ..., fN: pN}
             for fp in field_pats {
                 let field_ty = try!(self.pat_ty(&fp.node.pat)); // see (*2)
@@ -1288,7 +1285,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }
           }
 
-          hir::PatTup(ref subpats) => {
+          PatKind::Tup(ref subpats) => {
             // (p1, ..., pN)
             for (i, subpat) in subpats.iter().enumerate() {
                 let subpat_ty = try!(self.pat_ty(&subpat)); // see (*2)
@@ -1300,15 +1297,15 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }
           }
 
-          hir::PatBox(ref subpat) | hir::PatRegion(ref subpat, _) => {
+          PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => {
             // box p1, &p1, &mut p1.  we can ignore the mutability of
-            // PatRegion since that information is already contained
+            // PatKind::Ref since that information is already contained
             // in the type.
             let subcmt = try!(self.cat_deref(pat, cmt, 0, None));
               try!(self.cat_pattern_(subcmt, &subpat, op));
           }
 
-          hir::PatVec(ref before, ref slice, ref after) => {
+          PatKind::Vec(ref before, ref slice, ref after) => {
               let context = InteriorOffsetKind::Pattern;
               let vec_cmt = try!(self.deref_vec(pat, cmt, context));
               let elt_cmt = try!(self.cat_index(pat, vec_cmt, context));
@@ -1325,7 +1322,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
               }
           }
 
-          hir::PatLit(_) | hir::PatRange(_, _) => {
+          PatKind::Lit(_) | PatKind::Range(_, _) => {
               /*always ok*/
           }
         }
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 8181e7d798c..a1a3c194efe 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -14,7 +14,7 @@ use middle::ty;
 use util::nodemap::FnvHashMap;
 
 use syntax::ast;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::util::walk_pat;
 use syntax::codemap::{respan, Span, Spanned, DUMMY_SP};
 
@@ -34,27 +34,29 @@ pub fn pat_id_map(dm: &RefCell<DefMap>, pat: &hir::Pat) -> PatIdMap {
 
 pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        hir::PatLit(_) | hir::PatRange(_, _) | hir::PatQPath(..) => true,
-        hir::PatEnum(_, _) |
-        hir::PatIdent(_, _, None) |
-        hir::PatStruct(..) => {
+        PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true,
+        PatKind::TupleStruct(..) |
+        PatKind::Path(..) |
+        PatKind::Ident(_, _, None) |
+        PatKind::Struct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
                 Some(Def::Variant(..)) => true,
                 _ => false
             }
         }
-        hir::PatVec(_, _, _) => true,
+        PatKind::Vec(_, _, _) => true,
         _ => false
     }
 }
 
 pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        hir::PatEnum(_, _) |
-        hir::PatIdent(_, _, None) |
-        hir::PatStruct(..) => {
+        PatKind::TupleStruct(..) |
+        PatKind::Path(..) |
+        PatKind::Ident(_, _, None) |
+        PatKind::Struct(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
-                Some(Def::Variant(..)) | Some(Def::Struct(..)) => true,
+                Some(Def::Variant(..)) | Some(Def::Struct(..)) | Some(Def::TyAlias(..)) => true,
                 _ => false
             }
         }
@@ -64,7 +66,7 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
 
 pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => {
+        PatKind::Ident(_, _, None) | PatKind::Path(..) | PatKind::QPath(..) => {
             match dm.get(&pat.id).map(|d| d.full_def()) {
                 Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
                 _ => false
@@ -78,7 +80,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
 // returned instead of a panic.
 pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        hir::PatIdent(_, _, None) | hir::PatEnum(..) | hir::PatQPath(..) => {
+        PatKind::Ident(_, _, None) | PatKind::Path(..) | PatKind::QPath(..) => {
             match dm.get(&pat.id)
                     .and_then(|d| if d.depth == 0 { Some(d.base_def) }
                                   else { None } ) {
@@ -92,7 +94,7 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
 
 pub fn pat_is_binding(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        hir::PatIdent(..) => {
+        PatKind::Ident(..) => {
             !pat_is_variant_or_struct(dm, pat) &&
             !pat_is_const(dm, pat)
         }
@@ -102,8 +104,8 @@ pub fn pat_is_binding(dm: &DefMap, pat: &hir::Pat) -> bool {
 
 pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
     match pat.node {
-        hir::PatIdent(..) => pat_is_binding(dm, pat),
-        hir::PatWild => true,
+        PatKind::Ident(..) => pat_is_binding(dm, pat),
+        PatKind::Wild => true,
         _ => false
     }
 }
@@ -115,7 +117,7 @@ pub fn pat_bindings<I>(dm: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) where
 {
     walk_pat(pat, |p| {
         match p.node {
-          hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => {
+          PatKind::Ident(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => {
             it(binding_mode, p.id, p.span, &respan(pth.span, pth.node.name));
           }
           _ => {}
@@ -128,7 +130,7 @@ pub fn pat_bindings_ident<I>(dm: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) wh
 {
     walk_pat(pat, |p| {
         match p.node {
-          hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => {
+          PatKind::Ident(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => {
             it(binding_mode, p.id, p.span, &respan(pth.span, pth.node));
           }
           _ => {}
@@ -199,7 +201,7 @@ pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
 
 pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
     match pat.node {
-        hir::PatIdent(hir::BindByValue(_), ref path1, None) => {
+        PatKind::Ident(hir::BindByValue(_), ref path1, None) => {
             Some(path1.node.name)
         }
         _ => {
@@ -224,9 +226,10 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
     let mut variants = vec![];
     walk_pat(pat, |p| {
         match p.node {
-            hir::PatEnum(_, _) |
-            hir::PatIdent(_, _, None) |
-            hir::PatStruct(..) => {
+            PatKind::TupleStruct(..) |
+            PatKind::Path(..) |
+            PatKind::Ident(_, _, None) |
+            PatKind::Struct(..) => {
                 match dm.get(&p.id) {
                     Some(&PathResolution { base_def: Def::Variant(_, id), .. }) => {
                         variants.push(id);
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 81d2f37bfd9..b39964e2861 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -32,7 +32,7 @@ use syntax::ast::{self, NodeId};
 
 use rustc_front::hir;
 use rustc_front::intravisit::{self, Visitor, FnKind};
-use rustc_front::hir::{Block, Item, FnDecl, Arm, Pat, Stmt, Expr, Local};
+use rustc_front::hir::{Block, Item, FnDecl, Arm, Pat, PatKind, Stmt, Expr, Local};
 use rustc_front::util::stmt_id;
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable,
@@ -755,7 +755,7 @@ fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &hir::Pat) {
     // If this is a binding (or maybe a binding, I'm too lazy to check
     // the def map) then record the lifetime of that binding.
     match pat.node {
-        hir::PatIdent(..) => {
+        PatKind::Ident(..) => {
             record_var_lifetime(visitor, pat.id, pat.span);
         }
         _ => { }
@@ -958,24 +958,24 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) {
     ///        | box P&
     fn is_binding_pat(pat: &hir::Pat) -> bool {
         match pat.node {
-            hir::PatIdent(hir::BindByRef(_), _, _) => true,
+            PatKind::Ident(hir::BindByRef(_), _, _) => true,
 
-            hir::PatStruct(_, ref field_pats, _) => {
+            PatKind::Struct(_, ref field_pats, _) => {
                 field_pats.iter().any(|fp| is_binding_pat(&fp.node.pat))
             }
 
-            hir::PatVec(ref pats1, ref pats2, ref pats3) => {
+            PatKind::Vec(ref pats1, ref pats2, ref pats3) => {
                 pats1.iter().any(|p| is_binding_pat(&p)) ||
                 pats2.iter().any(|p| is_binding_pat(&p)) ||
                 pats3.iter().any(|p| is_binding_pat(&p))
             }
 
-            hir::PatEnum(_, Some(ref subpats)) |
-            hir::PatTup(ref subpats) => {
+            PatKind::TupleStruct(_, Some(ref subpats)) |
+            PatKind::Tup(ref subpats) => {
                 subpats.iter().any(|p| is_binding_pat(&p))
             }
 
-            hir::PatBox(ref subpat) => {
+            PatKind::Box(ref subpat) => {
                 is_binding_pat(&subpat)
             }
 
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 7835f333f19..fbb84c3cd7e 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -31,7 +31,7 @@ use syntax::attr::{self, Stability, Deprecation, AttrMetaMethods};
 use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
 
 use rustc_front::hir;
-use rustc_front::hir::{Item, Generics, StructField, Variant};
+use rustc_front::hir::{Item, Generics, StructField, Variant, PatKind};
 use rustc_front::intravisit::{self, Visitor};
 
 use std::mem::replace;
@@ -598,14 +598,14 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
     };
     match pat.node {
         // Foo(a, b, c)
-        // A Variant(..) pattern `hir::PatEnum(_, None)` doesn't have to be recursed into.
-        hir::PatEnum(_, Some(ref pat_fields)) => {
+        // A Variant(..) pattern `PatKind::TupleStruct(_, None)` doesn't have to be recursed into.
+        PatKind::TupleStruct(_, Some(ref pat_fields)) => {
             for (field, struct_field) in pat_fields.iter().zip(&v.fields) {
                 maybe_do_stability_check(tcx, struct_field.did, field.span, cb)
             }
         }
         // Foo { a, b, c }
-        hir::PatStruct(_, ref pat_fields, _) => {
+        PatKind::Struct(_, ref pat_fields, _) => {
             for field in pat_fields {
                 let did = v.field_named(field.node.name).did;
                 maybe_do_stability_check(tcx, did, field.span, cb);
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index ddc817ffc02..f8c6d3d9341 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -555,6 +555,11 @@ impl<'a,T> Iterator for EnumeratedItems<'a,T> {
             None
         }
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let size = self.vec.as_slice().len();
+        (size, Some(size))
+    }
 }
 
 impl<T> IntoIterator for VecPerParamSpace<T> {
diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs
index c89aa4c1833..de70cdbd29a 100644
--- a/src/librustc/middle/traits/fulfill.rs
+++ b/src/librustc/middle/traits/fulfill.rs
@@ -10,7 +10,7 @@
 
 use dep_graph::DepGraph;
 use middle::infer::InferCtxt;
-use middle::ty::{self, Ty, TypeFoldable};
+use middle::ty::{self, Ty, TypeFoldable, ToPolyTraitRef};
 use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error};
 use std::iter;
 use syntax::ast;
@@ -417,6 +417,21 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
     }
 }
 
+
+/// Return the set of type variables contained in a trait ref
+fn trait_ref_type_vars<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx>,
+                                 t: ty::PolyTraitRef<'tcx>) -> Vec<Ty<'tcx>>
+{
+    t.skip_binder() // ok b/c this check doesn't care about regions
+     .input_types()
+     .iter()
+     .map(|t| selcx.infcx().resolve_type_vars_if_possible(t))
+     .filter(|t| t.has_infer_types())
+     .flat_map(|t| t.walk())
+     .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false })
+     .collect()
+}
+
 /// Processes a predicate obligation and returns either:
 /// - `Ok(Some(v))` if the predicate is true, presuming that `v` are also true
 /// - `Ok(None)` if we don't have enough info to be sure
@@ -433,7 +448,7 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
     // doing more work yet
     if !pending_obligation.stalled_on.is_empty() {
         if pending_obligation.stalled_on.iter().all(|&ty| {
-            let resolved_ty = selcx.infcx().resolve_type_vars_if_possible(&ty);
+            let resolved_ty = selcx.infcx().shallow_resolve(&ty);
             resolved_ty == ty // nothing changed here
         }) {
             debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
@@ -493,14 +508,7 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                     // of its type, and those types are resolved at
                     // the same time.
                     pending_obligation.stalled_on =
-                        data.skip_binder() // ok b/c this check doesn't care about regions
-                        .input_types()
-                        .iter()
-                        .map(|t| selcx.infcx().resolve_type_vars_if_possible(t))
-                        .filter(|t| t.has_infer_types())
-                        .flat_map(|t| t.walk())
-                        .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false })
-                        .collect();
+                        trait_ref_type_vars(selcx, data.to_poly_trait_ref());
 
                     debug!("process_predicate: pending obligation {:?} now stalled on {:?}",
                            selcx.infcx().resolve_type_vars_if_possible(obligation),
@@ -568,6 +576,11 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         ty::Predicate::Projection(ref data) => {
             let project_obligation = obligation.with(data.clone());
             match project::poly_project_and_unify_type(selcx, &project_obligation) {
+                Ok(None) => {
+                    pending_obligation.stalled_on =
+                        trait_ref_type_vars(selcx, data.to_poly_trait_ref());
+                    Ok(None)
+                }
                 Ok(v) => Ok(v),
                 Err(e) => Err(CodeProjectionError(e))
             }
@@ -582,8 +595,14 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         }
 
         ty::Predicate::WellFormed(ty) => {
-            Ok(ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
-                                   ty, obligation.cause.span))
+            match ty::wf::obligations(selcx.infcx(), obligation.cause.body_id,
+                                      ty, obligation.cause.span) {
+                None => {
+                    pending_obligation.stalled_on = vec![ty];
+                    Ok(None)
+                }
+                s => Ok(s)
+            }
         }
     }
 }
diff --git a/src/librustc/middle/ty/adjustment.rs b/src/librustc/middle/ty/adjustment.rs
index 6cab0baa553..afe177fbdcd 100644
--- a/src/librustc/middle/ty/adjustment.rs
+++ b/src/librustc/middle/ty/adjustment.rs
@@ -21,8 +21,9 @@ use rustc_front::hir;
 
 #[derive(Copy, Clone)]
 pub enum AutoAdjustment<'tcx> {
-    AdjustReifyFnPointer,   // go from a fn-item type to a fn-pointer type
-    AdjustUnsafeFnPointer,  // go from a safe fn pointer to an unsafe fn pointer
+    AdjustReifyFnPointer,    // go from a fn-item type to a fn-pointer type
+    AdjustUnsafeFnPointer,   // go from a safe fn pointer to an unsafe fn pointer
+    AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer
     AdjustDerefRef(AutoDerefRef<'tcx>),
 }
 
@@ -106,7 +107,8 @@ impl<'tcx> AutoAdjustment<'tcx> {
     pub fn is_identity(&self) -> bool {
         match *self {
             AdjustReifyFnPointer |
-            AdjustUnsafeFnPointer => false,
+            AdjustUnsafeFnPointer |
+            AdjustMutToConstPointer => false,
             AdjustDerefRef(ref r) => r.is_identity(),
         }
     }
@@ -151,7 +153,7 @@ impl<'tcx> ty::TyS<'tcx> {
         return match adjustment {
             Some(adjustment) => {
                 match *adjustment {
-                   AdjustReifyFnPointer => {
+                    AdjustReifyFnPointer => {
                         match self.sty {
                             ty::TyBareFn(Some(_), b) => {
                                 cx.mk_fn(None, b)
@@ -164,17 +166,32 @@ impl<'tcx> ty::TyS<'tcx> {
                         }
                     }
 
-                   AdjustUnsafeFnPointer => {
+                    AdjustUnsafeFnPointer => {
                         match self.sty {
                             ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
                             ref b => {
                                 cx.sess.bug(
-                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
+                                    &format!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: \
                                              {:?}",
                                             b));
                             }
                         }
-                   }
+                    }
+
+                    AdjustMutToConstPointer => {
+                        match self.sty {
+                            ty::TyRawPtr(mt) => cx.mk_ptr(ty::TypeAndMut {
+                                ty: mt.ty,
+                                mutbl: hir::MutImmutable
+                            }),
+                            ref b => {
+                                cx.sess.bug(
+                                    &format!("AdjustMutToConstPointer on non-raw-ptr: \
+                                             {:?}",
+                                            b));
+                            }
+                        }
+                    }
 
                     AdjustDerefRef(ref adj) => {
                         let mut adjusted_ty = self;
diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs
index 1d071cd604d..a014c63f0a2 100644
--- a/src/librustc/middle/ty/context.rs
+++ b/src/librustc/middle/ty/context.rs
@@ -131,6 +131,12 @@ pub struct Tables<'tcx> {
     /// equivalents. This table is not used in trans (since regions
     /// are erased there) and hence is not serialized to metadata.
     pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>,
+
+    /// For each FRU expression, record the normalized types of the fields
+    /// of the struct - this is needed because it is non-trivial to
+    /// normalize while preserving regions. This table is used only in
+    /// MIR construction and hence is not serialized to metadata.
+    pub fru_field_types: NodeMap<Vec<Ty<'tcx>>>
 }
 
 impl<'tcx> Tables<'tcx> {
@@ -144,6 +150,7 @@ impl<'tcx> Tables<'tcx> {
             closure_tys: DefIdMap(),
             closure_kinds: DefIdMap(),
             liberated_fn_sigs: NodeMap(),
+            fru_field_types: NodeMap()
         }
     }
 
@@ -612,6 +619,7 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
 pub mod tls {
     use middle::ty;
 
+    use std::cell::Cell;
     use std::fmt;
     use syntax::codemap;
 
@@ -620,7 +628,9 @@ pub mod tls {
     /// in libstd doesn't allow types generic over lifetimes.
     struct ThreadLocalTyCx;
 
-    scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx);
+    thread_local! {
+        static TLS_TCX: Cell<Option<*const ThreadLocalTyCx>> = Cell::new(None)
+    }
 
     fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result {
         with(|tcx| {
@@ -633,18 +643,27 @@ pub mod tls {
             let original_span_debug = span_dbg.get();
             span_dbg.set(span_debug);
             let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx;
-            let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx));
+            let result = TLS_TCX.with(|tls| {
+                let prev = tls.get();
+                tls.set(Some(tls_ptr));
+                let ret = f(&tcx);
+                tls.set(prev);
+                ret
+            });
             span_dbg.set(original_span_debug);
             result
         })
     }
 
     pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {
-        TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) }))
+        TLS_TCX.with(|tcx| {
+            let tcx = tcx.get().unwrap();
+            f(unsafe { &*(tcx as *const ty::ctxt) })
+        })
     }
 
     pub fn with_opt<F: FnOnce(Option<&ty::ctxt>) -> R, R>(f: F) -> R {
-        if TLS_TCX.is_set() {
+        if TLS_TCX.with(|tcx| tcx.get().is_some()) {
             with(|v| f(Some(v)))
         } else {
             f(None)
diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs
index e3357aabd5d..00a011c6b5d 100644
--- a/src/librustc/middle/ty/mod.rs
+++ b/src/librustc/middle/ty/mod.rs
@@ -52,7 +52,7 @@ use syntax::codemap::{DUMMY_SP, Span};
 use syntax::parse::token::InternedString;
 
 use rustc_front::hir;
-use rustc_front::hir::{ItemImpl, ItemTrait};
+use rustc_front::hir::{ItemImpl, ItemTrait, PatKind};
 use rustc_front::intravisit::Visitor;
 
 pub use self::sty::{Binder, DebruijnIndex};
@@ -917,7 +917,7 @@ impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> {
 
 impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
     fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
-        self.map_bound_ref(|trait_pred| trait_pred.trait_ref.clone())
+        self.map_bound_ref(|trait_pred| trait_pred.trait_ref)
     }
 }
 
@@ -928,7 +928,7 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> {
         // This is because here `self` has a `Binder` and so does our
         // return value, so we are preserving the number of binding
         // levels.
-        ty::Binder(self.0.projection_ty.trait_ref.clone())
+        ty::Binder(self.0.projection_ty.trait_ref)
     }
 }
 
@@ -1945,7 +1945,7 @@ impl<'tcx> ctxt<'tcx> {
         match self.map.find(id) {
             Some(ast_map::NodeLocal(pat)) => {
                 match pat.node {
-                    hir::PatIdent(_, ref path1, _) => path1.node.name.as_str(),
+                    PatKind::Ident(_, ref path1, _) => path1.node.name.as_str(),
                     _ => {
                         self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, pat));
                     },
diff --git a/src/librustc/mir/mir_map.rs b/src/librustc/mir/mir_map.rs
index aa24f6d8979..32e78b04676 100644
--- a/src/librustc/mir/mir_map.rs
+++ b/src/librustc/mir/mir_map.rs
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use dep_graph::DepNode;
 use util::nodemap::NodeMap;
 use mir::repr::Mir;
 use mir::transform::MirPass;
 use middle::ty;
+use middle::infer;
 
 pub struct MirMap<'tcx> {
     pub map: NodeMap<Mir<'tcx>>,
@@ -19,9 +21,17 @@ pub struct MirMap<'tcx> {
 
 impl<'tcx> MirMap<'tcx> {
     pub fn run_passes(&mut self, passes: &mut [Box<MirPass>], tcx: &ty::ctxt<'tcx>) {
-        for (_, ref mut mir) in &mut self.map {
+        if passes.is_empty() { return; }
+
+        for (&id, mir) in &mut self.map {
+            let did = tcx.map.local_def_id(id);
+            let _task = tcx.dep_graph.in_task(DepNode::MirMapConstruction(did));
+
+            let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+            let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
+
             for pass in &mut *passes {
-                pass.run_on_mir(mir, tcx)
+                pass.run_on_mir(mir, &infcx)
             }
         }
     }
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index 783c58469a1..ce7b1ceb355 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -45,6 +45,9 @@ pub struct Mir<'tcx> {
     /// values in that it is possible to borrow them and mutate them
     /// through the resulting reference.
     pub temp_decls: Vec<TempDecl<'tcx>>,
+
+    /// A span representing this MIR, for error reporting
+    pub span: Span,
 }
 
 /// where execution begins
@@ -145,7 +148,7 @@ pub enum BorrowKind {
 
 /// A "variable" is a binding declared by the user as part of the fn
 /// decl, a let, etc.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct VarDecl<'tcx> {
     pub mutability: Mutability,
     pub name: Name,
@@ -154,7 +157,7 @@ pub struct VarDecl<'tcx> {
 
 /// A "temp" is a temporary that we place on the stack. They are
 /// anonymous, always mutable, and have only a type.
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct TempDecl<'tcx> {
     pub ty: Ty<'tcx>,
 }
@@ -170,7 +173,7 @@ pub struct TempDecl<'tcx> {
 ///
 /// there is only one argument, of type `(i32, u32)`, but two bindings
 /// (`x` and `y`).
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct ArgDecl<'tcx> {
     pub ty: Ty<'tcx>,
 }
@@ -499,7 +502,7 @@ pub struct Projection<'tcx, B, V> {
 #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum ProjectionElem<'tcx, V> {
     Deref,
-    Field(Field),
+    Field(Field, Ty<'tcx>),
     Index(V),
 
     /// These indices are generated by slice patterns. Easiest to explain
@@ -550,8 +553,8 @@ impl Field {
 }
 
 impl<'tcx> Lvalue<'tcx> {
-    pub fn field(self, f: Field) -> Lvalue<'tcx> {
-        self.elem(ProjectionElem::Field(f))
+    pub fn field(self, f: Field, ty: Ty<'tcx>) -> Lvalue<'tcx> {
+        self.elem(ProjectionElem::Field(f, ty))
     }
 
     pub fn deref(self) -> Lvalue<'tcx> {
@@ -591,8 +594,8 @@ impl<'tcx> Debug for Lvalue<'tcx> {
                         write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].name),
                     ProjectionElem::Deref =>
                         write!(fmt, "(*{:?})", data.base),
-                    ProjectionElem::Field(field) =>
-                        write!(fmt, "{:?}.{:?}", data.base, field.index()),
+                    ProjectionElem::Field(field, ty) =>
+                        write!(fmt, "({:?}.{:?}: {:?})", data.base, field.index(), ty),
                     ProjectionElem::Index(ref index) =>
                         write!(fmt, "{:?}[{:?}]", data.base, index),
                     ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 45cc0b8b413..20e083f840f 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -14,7 +14,8 @@
  */
 
 use mir::repr::*;
-use middle::subst::Substs;
+use middle::const_eval::ConstVal;
+use middle::subst::{Subst, Substs};
 use middle::ty::{self, AdtDef, Ty};
 use rustc_front::hir;
 
@@ -72,23 +73,7 @@ impl<'tcx> LvalueTy<'tcx> {
                         tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
                     }
                 },
-            ProjectionElem::Field(field) => {
-                let field_ty = match self {
-                    LvalueTy::Ty { ty } => match ty.sty {
-                        ty::TyStruct(adt_def, substs) =>
-                            adt_def.struct_variant().fields[field.index()].ty(tcx, substs),
-                        ty::TyTuple(ref tys) =>
-                            tys[field.index()],
-                        ty::TyClosure(_, ref closure_substs) =>
-                            closure_substs.upvar_tys[field.index()],
-                        _ =>
-                            tcx.sess.bug(&format!("cannot get field of type: `{:?}`", ty)),
-                    },
-                    LvalueTy::Downcast { adt_def, substs, variant_index } =>
-                        adt_def.variants[variant_index].fields[field.index()].ty(tcx, substs),
-                };
-                LvalueTy::Ty { ty: field_ty }
-            }
+            ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
         }
     }
 }
@@ -150,6 +135,73 @@ impl<'tcx> Mir<'tcx> {
                 self.lvalue_ty(tcx, &proj.base).projection_ty(tcx, &proj.elem)
         }
     }
+
+    pub fn rvalue_ty(&self,
+                     tcx: &ty::ctxt<'tcx>,
+                     rvalue: &Rvalue<'tcx>)
+                     -> Option<Ty<'tcx>>
+    {
+        match *rvalue {
+            Rvalue::Use(ref operand) => Some(self.operand_ty(tcx, operand)),
+            Rvalue::Repeat(ref operand, ref count) => {
+                if let ConstVal::Uint(u) = count.value {
+                    let op_ty = self.operand_ty(tcx, operand);
+                    Some(tcx.mk_array(op_ty, u as usize))
+                } else {
+                    None
+                }
+            }
+            Rvalue::Ref(reg, bk, ref lv) => {
+                let lv_ty = self.lvalue_ty(tcx, lv).to_ty(tcx);
+                Some(tcx.mk_ref(
+                    tcx.mk_region(reg),
+                    ty::TypeAndMut {
+                        ty: lv_ty,
+                        mutbl: bk.to_mutbl_lossy()
+                    }
+                ))
+            }
+            Rvalue::Len(..) => Some(tcx.types.usize),
+            Rvalue::Cast(_, _, ty) => Some(ty),
+            Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
+                let lhs_ty = self.operand_ty(tcx, lhs);
+                let rhs_ty = self.operand_ty(tcx, rhs);
+                Some(self.binop_ty(tcx, op, lhs_ty, rhs_ty))
+            }
+            Rvalue::UnaryOp(_, ref operand) => {
+                Some(self.operand_ty(tcx, operand))
+            }
+            Rvalue::Box(t) => {
+                Some(tcx.mk_box(t))
+            }
+            Rvalue::Aggregate(ref ak, ref ops) => {
+                match *ak {
+                    AggregateKind::Vec => {
+                        if let Some(operand) = ops.get(0) {
+                            let ty = self.operand_ty(tcx, operand);
+                            Some(tcx.mk_array(ty, ops.len()))
+                        } else {
+                            None
+                        }
+                    }
+                    AggregateKind::Tuple => {
+                        Some(tcx.mk_tup(
+                            ops.iter().map(|op| self.operand_ty(tcx, op)).collect()
+                        ))
+                    }
+                    AggregateKind::Adt(def, _, substs) => {
+                        Some(def.type_scheme(tcx).ty.subst(tcx, substs))
+                    }
+                    AggregateKind::Closure(did, substs) => {
+                        Some(tcx.mk_closure_from_closure_substs(
+                            did, Box::new(substs.clone())))
+                    }
+                }
+            }
+            Rvalue::Slice { .. } => None,
+            Rvalue::InlineAsm(..) => None
+        }
+    }
 }
 
 impl BorrowKind {
diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs
index 0f18d8d2821..cc417f5a99e 100644
--- a/src/librustc/mir/transform.rs
+++ b/src/librustc/mir/transform.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 use mir::repr::Mir;
-use middle::ty::ctxt;
+use middle::infer::InferCtxt;
 
 pub trait MirPass {
-    fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ctxt<'tcx>);
+    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, infcx: &InferCtxt<'a, 'tcx>);
 }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index c96713a7285..ea08bf021fb 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -28,6 +28,7 @@ use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::errors::{ColorConfig, Handler};
 use syntax::parse;
+use syntax::parse::lexer::Reader;
 use syntax::parse::token::InternedString;
 use syntax::feature_gate::UnstableFeatures;
 
@@ -137,6 +138,7 @@ pub struct Options {
     pub no_trans: bool,
     pub error_format: ErrorOutputType,
     pub treat_err_as_bug: bool,
+    pub mir_opt_level: usize,
 
     /// if true, build up the dep-graph
     pub build_dep_graph: bool,
@@ -253,6 +255,7 @@ pub fn basic_options() -> Options {
         parse_only: false,
         no_trans: false,
         treat_err_as_bug: false,
+        mir_opt_level: 1,
         build_dep_graph: false,
         dump_dep_graph: false,
         no_analysis: false,
@@ -509,7 +512,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
     link_args: Option<Vec<String>> = (None, parse_opt_list,
         "extra arguments to pass to the linker (space separated)"),
     link_dead_code: bool = (false, parse_bool,
-        "let the linker strip dead coded (turning it on can be used for code coverage)"),
+        "don't let linker strip dead code (turning it on can be used for code coverage)"),
     lto: bool = (false, parse_bool,
         "perform LLVM link-time optimizations"),
     target_cpu: Option<String> = (None, parse_opt_string,
@@ -654,6 +657,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
           "show spans for compiler debugging (expr|pat|ty)"),
     print_trans_items: Option<String> = (None, parse_opt_string,
           "print the result of the translation item collection pass"),
+    mir_opt_level: Option<usize> = (None, parse_opt_uint,
+          "set the MIR optimization level (0-3)"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -744,24 +749,20 @@ pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
     }
 }
 
-/// Returns the "short" subset of the stable rustc command line options.
-pub fn short_optgroups() -> Vec<getopts::OptGroup> {
-    rustc_short_optgroups().into_iter()
-        .filter(|g|g.is_stable())
-        .map(|g|g.opt_group)
-        .collect()
-}
-
-/// Returns all of the stable rustc command line options.
-pub fn optgroups() -> Vec<getopts::OptGroup> {
-    rustc_optgroups().into_iter()
-        .filter(|g|g.is_stable())
-        .map(|g|g.opt_group)
-        .collect()
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum OptionStability { Stable, Unstable }
+pub enum OptionStability {
+    Stable,
+
+    // FIXME: historically there were some options which were either `-Z` or
+    //        required the `-Z unstable-options` flag, which were all intended
+    //        to be unstable. Unfortunately we didn't actually gate usage of
+    //        these options on the stable compiler, so we still allow them there
+    //        today. There are some warnings printed out about this in the
+    //        driver.
+    UnstableButNotReally,
+
+    Unstable,
+}
 
 #[derive(Clone, PartialEq, Eq)]
 pub struct RustcOptGroup {
@@ -778,9 +779,17 @@ impl RustcOptGroup {
         RustcOptGroup { opt_group: g, stability: OptionStability::Stable }
     }
 
+    #[allow(dead_code)] // currently we have no "truly unstable" options
     fn unstable(g: getopts::OptGroup) -> RustcOptGroup {
         RustcOptGroup { opt_group: g, stability: OptionStability::Unstable }
     }
+
+    fn unstable_bnr(g: getopts::OptGroup) -> RustcOptGroup {
+        RustcOptGroup {
+            opt_group: g,
+            stability: OptionStability::UnstableButNotReally,
+        }
+    }
 }
 
 // The `opt` local module holds wrappers around the `getopts` API that
@@ -802,24 +811,57 @@ mod opt {
 
     fn stable(g: getopts::OptGroup) -> R { RustcOptGroup::stable(g) }
     fn unstable(g: getopts::OptGroup) -> R { RustcOptGroup::unstable(g) }
+    fn unstable_bnr(g: getopts::OptGroup) -> R { RustcOptGroup::unstable_bnr(g) }
 
-    // FIXME (pnkfelix): We default to stable since the current set of
-    // options is defacto stable.  However, it would be good to revise the
-    // code so that a stable option is the thing that takes extra effort
-    // to encode.
-
-    pub fn     opt(a: S, b: S, c: S, d: S) -> R { stable(getopts::optopt(a, b, c, d)) }
-    pub fn   multi(a: S, b: S, c: S, d: S) -> R { stable(getopts::optmulti(a, b, c, d)) }
-    pub fn    flag(a: S, b: S, c: S)       -> R { stable(getopts::optflag(a, b, c)) }
-    pub fn flagopt(a: S, b: S, c: S, d: S) -> R { stable(getopts::optflagopt(a, b, c, d)) }
-    pub fn flagmulti(a: S, b: S, c: S)     -> R { stable(getopts::optflagmulti(a, b, c)) }
+    pub fn opt_s(a: S, b: S, c: S, d: S) -> R {
+        stable(getopts::optopt(a, b, c, d))
+    }
+    pub fn multi_s(a: S, b: S, c: S, d: S) -> R {
+        stable(getopts::optmulti(a, b, c, d))
+    }
+    pub fn flag_s(a: S, b: S, c: S) -> R {
+        stable(getopts::optflag(a, b, c))
+    }
+    pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R {
+        stable(getopts::optflagopt(a, b, c, d))
+    }
+    pub fn flagmulti_s(a: S, b: S, c: S) -> R {
+        stable(getopts::optflagmulti(a, b, c))
+    }
 
+    pub fn opt(a: S, b: S, c: S, d: S) -> R {
+        unstable(getopts::optopt(a, b, c, d))
+    }
+    pub fn multi(a: S, b: S, c: S, d: S) -> R {
+        unstable(getopts::optmulti(a, b, c, d))
+    }
+    pub fn flag(a: S, b: S, c: S) -> R {
+        unstable(getopts::optflag(a, b, c))
+    }
+    pub fn flagopt(a: S, b: S, c: S, d: S) -> R {
+        unstable(getopts::optflagopt(a, b, c, d))
+    }
+    pub fn flagmulti(a: S, b: S, c: S) -> R {
+        unstable(getopts::optflagmulti(a, b, c))
+    }
 
-    pub fn     opt_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optopt(a, b, c, d)) }
-    pub fn   multi_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optmulti(a, b, c, d)) }
-    pub fn    flag_u(a: S, b: S, c: S)       -> R { unstable(getopts::optflag(a, b, c)) }
-    pub fn flagopt_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optflagopt(a, b, c, d)) }
-    pub fn flagmulti_u(a: S, b: S, c: S)     -> R { unstable(getopts::optflagmulti(a, b, c)) }
+    // Do not use these functions for any new options added to the compiler, all
+    // new options should use the `*_u` variants above to be truly unstable.
+    pub fn opt_ubnr(a: S, b: S, c: S, d: S) -> R {
+        unstable_bnr(getopts::optopt(a, b, c, d))
+    }
+    pub fn multi_ubnr(a: S, b: S, c: S, d: S) -> R {
+        unstable_bnr(getopts::optmulti(a, b, c, d))
+    }
+    pub fn flag_ubnr(a: S, b: S, c: S) -> R {
+        unstable_bnr(getopts::optflag(a, b, c))
+    }
+    pub fn flagopt_ubnr(a: S, b: S, c: S, d: S) -> R {
+        unstable_bnr(getopts::optflagopt(a, b, c, d))
+    }
+    pub fn flagmulti_ubnr(a: S, b: S, c: S) -> R {
+        unstable_bnr(getopts::optflagmulti(a, b, c))
+    }
 }
 
 /// Returns the "short" subset of the rustc command line options,
@@ -827,44 +869,44 @@ mod opt {
 /// part of the stable long-term interface for rustc.
 pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
     vec![
-        opt::flag("h", "help", "Display this message"),
-        opt::multi("", "cfg", "Configure the compilation environment", "SPEC"),
-        opt::multi("L", "",   "Add a directory to the library search path",
+        opt::flag_s("h", "help", "Display this message"),
+        opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
+        opt::multi_s("L", "",   "Add a directory to the library search path",
                    "[KIND=]PATH"),
-        opt::multi("l", "",   "Link the generated crate(s) to the specified native
+        opt::multi_s("l", "",   "Link the generated crate(s) to the specified native
                              library NAME. The optional KIND can be one of,
                              static, dylib, or framework. If omitted, dylib is
                              assumed.", "[KIND=]NAME"),
-        opt::multi("", "crate-type", "Comma separated list of types of crates
+        opt::multi_s("", "crate-type", "Comma separated list of types of crates
                                     for the compiler to emit",
                    "[bin|lib|rlib|dylib|staticlib]"),
-        opt::opt("", "crate-name", "Specify the name of the crate being built",
+        opt::opt_s("", "crate-name", "Specify the name of the crate being built",
                "NAME"),
-        opt::multi("", "emit", "Comma separated list of types of output for \
+        opt::multi_s("", "emit", "Comma separated list of types of output for \
                               the compiler to emit",
                  "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
-        opt::multi("", "print", "Comma separated list of compiler information to \
+        opt::multi_s("", "print", "Comma separated list of compiler information to \
                                print on stdout",
                  "[crate-name|file-names|sysroot|target-list]"),
-        opt::flagmulti("g",  "",  "Equivalent to -C debuginfo=2"),
-        opt::flagmulti("O", "", "Equivalent to -C opt-level=2"),
-        opt::opt("o", "", "Write output to <filename>", "FILENAME"),
-        opt::opt("",  "out-dir", "Write output to compiler-chosen filename \
+        opt::flagmulti_s("g",  "",  "Equivalent to -C debuginfo=2"),
+        opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
+        opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
+        opt::opt_s("",  "out-dir", "Write output to compiler-chosen filename \
                                 in <dir>", "DIR"),
-        opt::opt("", "explain", "Provide a detailed explanation of an error \
+        opt::opt_s("", "explain", "Provide a detailed explanation of an error \
                                message", "OPT"),
-        opt::flag("", "test", "Build a test harness"),
-        opt::opt("", "target", "Target triple for which the code is compiled", "TARGET"),
-        opt::multi("W", "warn", "Set lint warnings", "OPT"),
-        opt::multi("A", "allow", "Set lint allowed", "OPT"),
-        opt::multi("D", "deny", "Set lint denied", "OPT"),
-        opt::multi("F", "forbid", "Set lint forbidden", "OPT"),
-        opt::multi("", "cap-lints", "Set the most restrictive lint level. \
+        opt::flag_s("", "test", "Build a test harness"),
+        opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
+        opt::multi_s("W", "warn", "Set lint warnings", "OPT"),
+        opt::multi_s("A", "allow", "Set lint allowed", "OPT"),
+        opt::multi_s("D", "deny", "Set lint denied", "OPT"),
+        opt::multi_s("F", "forbid", "Set lint forbidden", "OPT"),
+        opt::multi_s("", "cap-lints", "Set the most restrictive lint level. \
                                      More restrictive lints are capped at this \
                                      level", "LEVEL"),
-        opt::multi("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
-        opt::flag("V", "version", "Print version info and exit"),
-        opt::flag("v", "verbose", "Use verbose output"),
+        opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
+        opt::flag_s("V", "version", "Print version info and exit"),
+        opt::flag_s("v", "verbose", "Use verbose output"),
     ]
 }
 
@@ -874,24 +916,26 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
 pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
     let mut opts = rustc_short_optgroups();
     opts.extend_from_slice(&[
-        opt::multi("", "extern", "Specify where an external rust library is \
+        opt::multi_s("", "extern", "Specify where an external rust library is \
                                 located",
                  "NAME=PATH"),
-        opt::opt("", "sysroot", "Override the system root", "PATH"),
-        opt::multi("Z", "", "Set internal debugging options", "FLAG"),
-        opt::opt_u("", "error-format", "How errors and other messages are produced", "human|json"),
-        opt::opt("", "color", "Configure coloring of output:
+        opt::opt_s("", "sysroot", "Override the system root", "PATH"),
+        opt::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"),
+        opt::opt_ubnr("", "error-format",
+                      "How errors and other messages are produced",
+                      "human|json"),
+        opt::opt_s("", "color", "Configure coloring of output:
             auto   = colorize, if output goes to a tty (default);
             always = always colorize output;
             never  = never colorize output", "auto|always|never"),
 
-        opt::flagopt_u("", "pretty",
+        opt::flagopt_ubnr("", "pretty",
                    "Pretty-print the input instead of compiling;
                    valid types are: `normal` (un-annotated source),
                    `expanded` (crates expanded), or
                    `expanded,identified` (fully parenthesized, AST nodes with IDs).",
                  "TYPE"),
-        opt::flagopt_u("", "unpretty",
+        opt::flagopt_ubnr("", "unpretty",
                      "Present the input source, unstable (and less-pretty) variants;
                       valid types are any of the types for `--pretty`, as well as:
                       `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
@@ -899,6 +943,14 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
                       `hir` (the HIR), `hir,identified`, or
                       `hir,typed` (HIR with types for each node).",
                      "TYPE"),
+
+        // new options here should **not** use the `_ubnr` functions, all new
+        // unstable options should use the short variants to indicate that they
+        // are truly unstable. All `_ubnr` flags are just that way because they
+        // were so historically.
+        //
+        // You may also wish to keep this comment at the bottom of this list to
+        // ensure that others see it.
     ]);
     opts
 }
@@ -906,10 +958,19 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
 pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
     cfgspecs.into_iter().map(|s| {
-        parse::parse_meta_from_source_str("cfgspec".to_string(),
-                                          s.to_string(),
-                                          Vec::new(),
-                                          &parse::ParseSess::new())
+        let sess = parse::ParseSess::new();
+        let mut parser = parse::new_parser_from_source_str(&sess,
+                                                           Vec::new(),
+                                                           "cfgspec".to_string(),
+                                                           s.to_string());
+        let meta_item = panictry!(parser.parse_meta_item());
+
+        if !parser.reader.is_eof() {
+            early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}",
+                                                             s))
+        }
+
+        meta_item
     }).collect::<ast::CrateConfig>()
 }
 
@@ -978,6 +1039,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     let parse_only = debugging_opts.parse_only;
     let no_trans = debugging_opts.no_trans;
     let treat_err_as_bug = debugging_opts.treat_err_as_bug;
+    let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1);
     let incremental_compilation = debugging_opts.incr_comp;
     let dump_dep_graph = debugging_opts.dump_dep_graph;
     let no_analysis = debugging_opts.no_analysis;
@@ -1156,6 +1218,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         parse_only: parse_only,
         no_trans: no_trans,
         treat_err_as_bug: treat_err_as_bug,
+        mir_opt_level: mir_opt_level,
         build_dep_graph: incremental_compilation || dump_dep_graph,
         dump_dep_graph: dump_dep_graph,
         no_analysis: no_analysis,
@@ -1226,15 +1289,21 @@ impl fmt::Display for CrateType {
 #[cfg(test)]
 mod tests {
     use middle::cstore::DummyCrateStore;
-    use session::config::{build_configuration, optgroups, build_session_options};
+    use session::config::{build_configuration, build_session_options};
     use session::build_session;
 
     use std::rc::Rc;
-    use getopts::getopts;
+    use getopts::{getopts, OptGroup};
     use syntax::attr;
     use syntax::attr::AttrMetaMethods;
     use syntax::diagnostics;
 
+    fn optgroups() -> Vec<OptGroup> {
+        super::rustc_optgroups().into_iter()
+                                .map(|a| a.opt_group)
+                                .collect()
+    }
+
     // When the user supplies --test we should implicitly supply --cfg test
     #[test]
     fn test_switch_implies_cfg_test() {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index a0939dc53df..5868f233776 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -396,6 +396,9 @@ impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
             ty::adjustment::AdjustUnsafeFnPointer => {
                 write!(f, "AdjustUnsafeFnPointer")
             }
+            ty::adjustment::AdjustMutToConstPointer => {
+                write!(f, "AdjustMutToConstPointer")
+            }
             ty::adjustment::AdjustDerefRef(ref data) => {
                 write!(f, "{:?}", data)
             }
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index 4d8cfc23804..364c2977bfb 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -31,6 +31,7 @@
 #![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(box_syntax)]
+#![feature(copy_from_slice)]
 #![feature(libc)]
 #![feature(rand)]
 #![feature(rustc_private)]
diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs
index 840f9abce93..ba8107e03c9 100644
--- a/src/librustc_back/sha2.rs
+++ b/src/librustc_back/sha2.rs
@@ -134,13 +134,13 @@ impl FixedBuffer for FixedBuffer64 {
             let buffer_remaining = size - self.buffer_idx;
             if input.len() >= buffer_remaining {
                 self.buffer[self.buffer_idx..size]
-                    .clone_from_slice(&input[..buffer_remaining]);
+                    .copy_from_slice(&input[..buffer_remaining]);
                 self.buffer_idx = 0;
                 func(&self.buffer);
                 i += buffer_remaining;
             } else {
                 self.buffer[self.buffer_idx..self.buffer_idx + input.len()]
-                    .clone_from_slice(input);
+                    .copy_from_slice(input);
                 self.buffer_idx += input.len();
                 return;
             }
@@ -157,7 +157,7 @@ impl FixedBuffer for FixedBuffer64 {
         // data left in the input vector will be less than the buffer size and the buffer will
         // be empty.
         let input_remaining = input.len() - i;
-        self.buffer[..input_remaining].clone_from_slice(&input[i..]);
+        self.buffer[..input_remaining].copy_from_slice(&input[i..]);
         self.buffer_idx += input_remaining;
     }
 
diff --git a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
index dd61bd87573..d7dcd714a10 100644
--- a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
+++ b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
@@ -22,7 +22,7 @@ pub fn target() -> Target {
         target_vendor: "unknown".to_string(),
 
         options: TargetOptions {
-            features: "+v7,+vfp2,+neon".to_string(),
+            features: "+v7,+vfp3,+neon".to_string(),
             cpu: "cortex-a8".to_string(),
             .. base
         }
diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs
index 651c2a3760a..f05319a0cbe 100644
--- a/src/librustc_back/target/freebsd_base.rs
+++ b/src/librustc_back/target/freebsd_base.rs
@@ -16,13 +16,20 @@ pub fn opts() -> TargetOptions {
         linker: "cc".to_string(),
         dynamic_linking: true,
         executables: true,
+        linker_is_gnu: true,
         has_rpath: true,
-        pre_link_args: vec![
+        pre_link_args: vec!(
+            // GNU-style linkers will use this to omit linking to libraries
+            // which don't actually fulfill any relocations, but only for
+            // libraries which follow this flag.  Thus, use it before
+            // specifying libraries to link to.
+            "-Wl,--as-needed".to_string(),
+
             // Always enable NX protection when it is available
             "-Wl,-z,noexecstack".to_string(),
-        ],
+        ),
+        position_independent_executables: true,
         exe_allocation_crate: super::maybe_jemalloc(),
-
         .. Default::default()
     }
 }
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index a868178b14f..e0743c339ce 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -65,12 +65,13 @@ mod windows_msvc_base;
 
 macro_rules! supported_targets {
     ( $(($triple:expr, $module:ident)),+ ) => (
+        $(mod $module;)*
+
         /// List of supported targets
         pub const TARGETS: &'static [&'static str] = &[$($triple),*];
 
         // this would use a match if stringify! were allowed in pattern position
         fn load_specific(target: &str) -> Option<Target> {
-            $(mod $module;)*
             let target = target.replace("-", "_");
             if false { }
             $(
diff --git a/src/librustc_back/target/x86_64_sun_solaris.rs b/src/librustc_back/target/x86_64_sun_solaris.rs
index fbe3f5abc90..541c1306b33 100644
--- a/src/librustc_back/target/x86_64_sun_solaris.rs
+++ b/src/librustc_back/target/x86_64_sun_solaris.rs
@@ -13,6 +13,7 @@ use target::Target;
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
     base.pre_link_args.push("-m64".to_string());
+    base.cpu = "x86-64".to_string();
 
     Target {
         llvm_target: "x86_64-pc-solaris".to_string(),
diff --git a/src/librustc_back/target/x86_64_unknown_openbsd.rs b/src/librustc_back/target/x86_64_unknown_openbsd.rs
index 07a1e137b41..8c995113c21 100644
--- a/src/librustc_back/target/x86_64_unknown_openbsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_openbsd.rs
@@ -12,6 +12,7 @@ use target::Target;
 
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
diff --git a/src/librustc_bitflags/Cargo.toml b/src/librustc_bitflags/Cargo.toml
index e82c6ec05c8..926ed5960d6 100644
--- a/src/librustc_bitflags/Cargo.toml
+++ b/src/librustc_bitflags/Cargo.toml
@@ -7,6 +7,3 @@ version = "0.0.0"
 name = "rustc_bitflags"
 path = "lib.rs"
 test = false
-
-[dependencies]
-core = { path = "../libcore" }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 90c93616232..4e507284a1b 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -23,7 +23,7 @@ use rustc::middle::ty;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::Span;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 
 struct GatherMoveInfo<'tcx> {
     id: ast::NodeId,
@@ -98,7 +98,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       move_pat: &hir::Pat,
                                       cmt: mc::cmt<'tcx>) {
     let pat_span_path_opt = match move_pat.node {
-        hir::PatIdent(_, ref path1, _) => {
+        PatKind::Ident(_, ref path1, _) => {
             Some(MoveSpanAndPath{span: move_pat.span,
                                  name: path1.node.name})
         },
diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs
index 29944aaf367..7f6fd9de3d2 100644
--- a/src/librustc_borrowck/diagnostics.rs
+++ b/src/librustc_borrowck/diagnostics.rs
@@ -26,7 +26,8 @@ fn foo() -> Box<Fn(u32) -> u32> {
 
 Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
 closed-over data by reference. This means that once `foo()` returns, `x` no
-longer exists. An attempt to access `x` within the closure would thus be unsafe.
+longer exists. An attempt to access `x` within the closure would thus be
+unsafe.
 
 Another situation where this might be encountered is when spawning threads:
 
@@ -73,7 +74,14 @@ fn main() {
 ```
 
 To fix this, ensure that any declared variables are initialized before being
-used.
+used. Example:
+
+```
+fn main() {
+    let x: i32 = 0;
+    let y = x; // ok!
+}
+```
 "##,
 
 E0382: r##"
@@ -210,8 +218,8 @@ let mut y: Box<_> = Box::new(&mut x);
 **y = 2;
 ```
 
-It can also be fixed by using a type with interior mutability, such as `Cell` or
-`RefCell`:
+It can also be fixed by using a type with interior mutability, such as `Cell`
+or `RefCell`:
 
 ```
 use std::cell::Cell;
@@ -259,8 +267,8 @@ fn foo<F: FnMut()>(f: F) { }
 ```
 
 Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
-interior mutability through a shared reference. Our example's `mutable` function
-could be redefined as below:
+interior mutability through a shared reference. Our example's `mutable`
+function could be redefined as below:
 
 ```
 use std::cell::Cell;
diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs
index 70f50b4c042..7b5dacece8c 100644
--- a/src/librustc_data_structures/bitvec.rs
+++ b/src/librustc_data_structures/bitvec.rs
@@ -50,6 +50,45 @@ impl BitVector {
         let extra_words = self.data.len() - num_words;
         self.data.extend((0..extra_words).map(|_| 0));
     }
+
+    /// Iterates over indexes of set bits in a sorted order
+    pub fn iter<'a>(&'a self) -> BitVectorIter<'a> {
+        BitVectorIter {
+            iter: self.data.iter(),
+            current: 0,
+            idx: 0
+        }
+    }
+}
+
+pub struct BitVectorIter<'a> {
+    iter: ::std::slice::Iter<'a, u64>,
+    current: u64,
+    idx: usize
+}
+
+impl<'a> Iterator for BitVectorIter<'a> {
+    type Item = usize;
+    fn next(&mut self) -> Option<usize> {
+        while self.current == 0 {
+            self.current = if let Some(&i) = self.iter.next() {
+                if i == 0 {
+                    self.idx += 64;
+                    continue;
+                } else {
+                    self.idx = u64s(self.idx) * 64;
+                    i
+                }
+            } else {
+                return None;
+            }
+        }
+        let offset = self.current.trailing_zeros() as usize;
+        self.current >>= offset;
+        self.current >>= 1; // shift otherwise overflows for 0b1000_0000_…_0000
+        self.idx += offset + 1;
+        return Some(self.idx - 1);
+    }
 }
 
 /// A "bit matrix" is basically a square matrix of booleans
@@ -154,6 +193,46 @@ fn word_mask(index: usize) -> (usize, u64) {
 }
 
 #[test]
+fn bitvec_iter_works() {
+    let mut bitvec = BitVector::new(100);
+    bitvec.insert(1);
+    bitvec.insert(10);
+    bitvec.insert(19);
+    bitvec.insert(62);
+    bitvec.insert(63);
+    bitvec.insert(64);
+    bitvec.insert(65);
+    bitvec.insert(66);
+    bitvec.insert(99);
+    assert_eq!(bitvec.iter().collect::<Vec<_>>(), [1, 10, 19, 62, 63, 64, 65, 66, 99]);
+}
+
+#[test]
+fn bitvec_iter_works_2() {
+    let mut bitvec = BitVector::new(300);
+    bitvec.insert(1);
+    bitvec.insert(10);
+    bitvec.insert(19);
+    bitvec.insert(62);
+    bitvec.insert(66);
+    bitvec.insert(99);
+    bitvec.insert(299);
+    assert_eq!(bitvec.iter().collect::<Vec<_>>(), [1, 10, 19, 62, 66, 99, 299]);
+
+}
+
+#[test]
+fn bitvec_iter_works_3() {
+    let mut bitvec = BitVector::new(319);
+    bitvec.insert(0);
+    bitvec.insert(127);
+    bitvec.insert(191);
+    bitvec.insert(255);
+    bitvec.insert(319);
+    assert_eq!(bitvec.iter().collect::<Vec<_>>(), [0, 127, 191, 255, 319]);
+}
+
+#[test]
 fn union_two_vecs() {
     let mut vec1 = BitVector::new(65);
     let mut vec2 = BitVector::new(65);
diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs
index 1ea09490aed..f11856d7513 100644
--- a/src/librustc_data_structures/graph/mod.rs
+++ b/src/librustc_data_structures/graph/mod.rs
@@ -115,7 +115,7 @@ impl<N:Debug,E:Debug> Graph<N,E> {
     // Simple accessors
 
     #[inline]
-    pub fn all_nodes<'a>(&'a self) -> &'a [Node<N>] {
+    pub fn all_nodes(&self) -> &[Node<N>] {
         &self.nodes
     }
 
@@ -125,7 +125,7 @@ impl<N:Debug,E:Debug> Graph<N,E> {
     }
 
     #[inline]
-    pub fn all_edges<'a>(&'a self) -> &'a [Edge<E>] {
+    pub fn all_edges(&self) -> &[Edge<E>] {
         &self.edges
     }
 
@@ -150,15 +150,15 @@ impl<N:Debug,E:Debug> Graph<N,E> {
         idx
     }
 
-    pub fn mut_node_data<'a>(&'a mut self, idx: NodeIndex) -> &'a mut N {
+    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
         &mut self.nodes[idx.0].data
     }
 
-    pub fn node_data<'a>(&'a self, idx: NodeIndex) -> &'a N {
+    pub fn node_data(&self, idx: NodeIndex) -> &N {
         &self.nodes[idx.0].data
     }
 
-    pub fn node<'a>(&'a self, idx: NodeIndex) -> &'a Node<N> {
+    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
         &self.nodes[idx.0]
     }
 
@@ -199,15 +199,15 @@ impl<N:Debug,E:Debug> Graph<N,E> {
         return idx;
     }
 
-    pub fn mut_edge_data<'a>(&'a mut self, idx: EdgeIndex) -> &'a mut E {
+    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
         &mut self.edges[idx.0].data
     }
 
-    pub fn edge_data<'a>(&'a self, idx: EdgeIndex) -> &'a E {
+    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
         &self.edges[idx.0].data
     }
 
-    pub fn edge<'a>(&'a self, idx: EdgeIndex) -> &'a Edge<E> {
+    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
         &self.edges[idx.0]
     }
 
@@ -257,11 +257,11 @@ impl<N:Debug,E:Debug> Graph<N,E> {
         AdjacentEdges { graph: self, direction: direction, next: first_edge }
     }
 
-    pub fn successor_nodes<'a>(&'a self, source: NodeIndex) -> AdjacentTargets<N,E> {
+    pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N,E> {
         self.outgoing_edges(source).targets()
     }
 
-    pub fn predecessor_nodes<'a>(&'a self, target: NodeIndex) -> AdjacentSources<N,E> {
+    pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N,E> {
         self.incoming_edges(target).sources()
     }
 
diff --git a/src/librustc_data_structures/snapshot_vec.rs b/src/librustc_data_structures/snapshot_vec.rs
index 5ab740f3629..5f89856afdb 100644
--- a/src/librustc_data_structures/snapshot_vec.rs
+++ b/src/librustc_data_structures/snapshot_vec.rs
@@ -91,14 +91,14 @@ impl<D:SnapshotVecDelegate> SnapshotVec<D> {
         len
     }
 
-    pub fn get<'a>(&'a self, index: usize) -> &'a D::Value {
+    pub fn get(&self, index: usize) -> &D::Value {
         &self.values[index]
     }
 
     /// Returns a mutable pointer into the vec; whatever changes you make here cannot be undone
     /// automatically, so you should be sure call `record()` with some sort of suitable undo
     /// action.
-    pub fn get_mut<'a>(&'a mut self, index: usize) -> &'a mut D::Value {
+    pub fn get_mut(&mut self, index: usize) -> &mut D::Value {
         &mut self.values[index]
     }
 
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 6eede3070b2..b446dec96fb 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -844,6 +844,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              "match checking",
              || middle::check_match::check_crate(tcx));
 
+        // this must run before MIR dump, because
+        // "not all control paths return a value" is reported here.
+        //
+        // maybe move the check to a MIR pass?
+        time(time_passes,
+             "liveness checking",
+             || middle::liveness::check_crate(tcx));
+
+        time(time_passes,
+             "rvalue checking",
+             || rvalues::check_crate(tcx));
+
         let mut mir_map =
             time(time_passes,
                  "MIR dump",
@@ -854,17 +866,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              || mir_map.run_passes(&mut sess.plugin_mir_passes.borrow_mut(), tcx));
 
         time(time_passes,
-             "liveness checking",
-             || middle::liveness::check_crate(tcx));
-
-        time(time_passes,
              "borrow checking",
              || borrowck::check_crate(tcx));
 
-        time(time_passes,
-             "rvalue checking",
-             || rvalues::check_crate(tcx));
-
         // Avoid overwhelming user with errors if type checking failed.
         // I'm not sure how helpful this is, to be honest, but it avoids
         // a
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index e7766309110..d0f86cfcb46 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -65,6 +65,7 @@ use rustc_trans::back::link;
 use rustc_trans::save;
 use rustc::session::{config, Session, build_session, CompileResult};
 use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
+use rustc::session::config::{get_unstable_features_setting, OptionStability};
 use rustc::middle::cstore::CrateStore;
 use rustc::lint::Lint;
 use rustc::lint;
@@ -85,7 +86,7 @@ use std::str;
 use std::sync::{Arc, Mutex};
 use std::thread;
 
-use rustc::session::early_error;
+use rustc::session::{early_error, early_warn};
 
 use syntax::ast;
 use syntax::parse;
@@ -93,6 +94,7 @@ use syntax::errors;
 use syntax::errors::emitter::Emitter;
 use syntax::diagnostics;
 use syntax::parse::token;
+use syntax::feature_gate::UnstableFeatures;
 
 #[cfg(test)]
 pub mod test;
@@ -819,8 +821,31 @@ fn print_flag_list<T>(cmdline_opt: &str,
 }
 
 /// Process command line options. Emits messages as appropriate. If compilation
-/// should continue, returns a getopts::Matches object parsed from args, otherwise
-/// returns None.
+/// should continue, returns a getopts::Matches object parsed from args,
+/// otherwise returns None.
+///
+/// The compiler's handling of options is a little complication as it ties into
+/// our stability story, and it's even *more* complicated by historical
+/// accidents. The current intention of each compiler option is to have one of
+/// three modes:
+///
+/// 1. An option is stable and can be used everywhere.
+/// 2. An option is unstable, but was historically allowed on the stable
+///    channel.
+/// 3. An option is unstable, and can only be used on nightly.
+///
+/// Like unstable library and language features, however, unstable options have
+/// always required a form of "opt in" to indicate that you're using them. This
+/// provides the easy ability to scan a code base to check to see if anything
+/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
+///
+/// All options behind `-Z` are considered unstable by default. Other top-level
+/// options can also be considered unstable, and they were unlocked through the
+/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
+/// instability in both cases, though.
+///
+/// So with all that in mind, the comments below have some more detail about the
+/// contortions done here to get things to work out correctly.
 pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
     // Throw away the first argument, the name of the binary
     let _binary = args.remove(0);
@@ -832,62 +857,83 @@ pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
         return None;
     }
 
-    fn allows_unstable_options(matches: &getopts::Matches) -> bool {
-        let r = matches.opt_strs("Z");
-        r.iter().any(|x| *x == "unstable-options")
-    }
+    // Parse with *all* options defined in the compiler, we don't worry about
+    // option stability here we just want to parse as much as possible.
+    let all_groups: Vec<getopts::OptGroup> = config::rustc_optgroups()
+                                                 .into_iter()
+                                                 .map(|x| x.opt_group)
+                                                 .collect();
+    let matches = match getopts::getopts(&args[..], &all_groups) {
+        Ok(m) => m,
+        Err(f) => early_error(ErrorOutputType::default(), &f.to_string()),
+    };
 
-    fn parse_all_options(args: &Vec<String>) -> getopts::Matches {
-        let all_groups: Vec<getopts::OptGroup> = config::rustc_optgroups()
-                                                     .into_iter()
-                                                     .map(|x| x.opt_group)
-                                                     .collect();
-        match getopts::getopts(&args[..], &all_groups) {
-            Ok(m) => {
-                if !allows_unstable_options(&m) {
-                    // If -Z unstable-options was not specified, verify that
-                    // no unstable options were present.
-                    for opt in config::rustc_optgroups().into_iter().filter(|x| !x.is_stable()) {
-                        let opt_name = if !opt.opt_group.long_name.is_empty() {
-                            &opt.opt_group.long_name
-                        } else {
-                            &opt.opt_group.short_name
-                        };
-                        if m.opt_present(opt_name) {
-                            early_error(ErrorOutputType::default(),
-                                        &format!("use of unstable option '{}' requires -Z \
-                                                  unstable-options",
-                                                 opt_name));
-                        }
-                    }
-                }
-                m
-            }
-            Err(f) => early_error(ErrorOutputType::default(), &f.to_string()),
+    // For all options we just parsed, we check a few aspects:
+    //
+    // * If the option is stable, we're all good
+    // * If the option wasn't passed, we're all good
+    // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
+    //   ourselves), then we require the `-Z unstable-options` flag to unlock
+    //   this option that was passed.
+    // * If we're a nightly compiler, then unstable options are now unlocked, so
+    //   we're good to go.
+    // * Otherwise, if we're a truly unstable option then we generate an error
+    //   (unstable option being used on stable)
+    // * If we're a historically stable-but-should-be-unstable option then we
+    //   emit a warning that we're going to turn this into an error soon.
+    let has_z_unstable_options = matches.opt_strs("Z")
+                                        .iter()
+                                        .any(|x| *x == "unstable-options");
+    let really_allows_unstable_options = match get_unstable_features_setting() {
+        UnstableFeatures::Disallow => false,
+        _ => true,
+    };
+    for opt in config::rustc_optgroups() {
+        if opt.stability == OptionStability::Stable {
+            continue
         }
-    }
-
-    // As a speed optimization, first try to parse the command-line using just
-    // the stable options.
-    let matches = match getopts::getopts(&args[..], &config::optgroups()) {
-        Ok(ref m) if allows_unstable_options(m) => {
-            // If -Z unstable-options was specified, redo parsing with the
-            // unstable options to ensure that unstable options are defined
-            // in the returned getopts::Matches.
-            parse_all_options(&args)
+        let opt_name = if !opt.opt_group.long_name.is_empty() {
+            &opt.opt_group.long_name
+        } else {
+            &opt.opt_group.short_name
+        };
+        if !matches.opt_present(opt_name) {
+            continue
         }
-        Ok(m) => m,
-        Err(_) => {
-            // redo option parsing, including unstable options this time,
-            // in anticipation that the mishandled option was one of the
-            // unstable ones.
-            parse_all_options(&args)
+        if opt_name != "Z" && !has_z_unstable_options {
+            let msg = format!("the `-Z unstable-options` flag must also be \
+                               passed to enable the flag `{}`", opt_name);
+            early_error(ErrorOutputType::default(), &msg);
         }
-    };
+        if really_allows_unstable_options {
+            continue
+        }
+        match opt.stability {
+            OptionStability::Unstable => {
+                let msg = format!("the option `{}` is only accepted on the \
+                                   nightly compiler", opt_name);
+                early_error(ErrorOutputType::default(), &msg);
+            }
+            OptionStability::UnstableButNotReally => {
+                let msg = format!("the option `{}` is is unstable and should \
+                                   only be used on the nightly compiler, but \
+                                   it is currently accepted for backwards \
+                                   compatibility; this will soon change, \
+                                   see issue #31847 for more details",
+                                  opt_name);
+                early_warn(ErrorOutputType::default(), &msg);
+            }
+            OptionStability::Stable => {}
+        }
+    }
 
     if matches.opt_present("h") || matches.opt_present("help") {
+        // Only show unstable options in --help if we *really* accept unstable
+        // options, which catches the case where we got `-Z unstable-options` on
+        // the stable channel of Rust which was accidentally allowed
+        // historically.
         usage(matches.opt_present("verbose"),
-              allows_unstable_options(&matches));
+              has_z_unstable_options && really_allows_unstable_options);
         return None;
     }
 
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 05173578921..e9db30f3cb2 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -817,13 +817,12 @@ pub fn pretty_print_input(sess: Session,
                                                              &id,
                                                              resolve::MakeGlobMap::No,
                                                              |tcx, mir_map, _, _| {
-                let mir_map = mir_map.unwrap();
-
-                for (nodeid, mir) in &mir_map.map {
-                    try!(writeln!(out, "MIR for {}", tcx.map.node_to_string(*nodeid)));
-                    try!(write_mir_pretty(mir, &mut out));
+                if let Some(mir_map) = mir_map {
+                    for (nodeid, mir) in &mir_map.map {
+                        try!(writeln!(out, "MIR for {}", tcx.map.node_to_string(*nodeid)));
+                        try!(write_mir_pretty(mir, &mut out));
+                    }
                 }
-
                 Ok(())
             }), &sess)
         }
@@ -840,12 +839,14 @@ pub fn pretty_print_input(sess: Session,
                                                              &id,
                                                              resolve::MakeGlobMap::No,
                                                              |tcx, mir_map, _, _| {
-                let mir_map = mir_map.unwrap();
-                try!(writeln!(out, "MIR for {}", tcx.map.node_to_string(nodeid)));
-                let mir = mir_map.map.get(&nodeid).unwrap_or_else(|| {
-                    sess.fatal(&format!("no MIR map entry for node {}", nodeid))
-                });
-                write_mir_pretty(mir, &mut out)
+                if let Some(mir_map) = mir_map {
+                    try!(writeln!(out, "MIR for {}", tcx.map.node_to_string(nodeid)));
+                    let mir = mir_map.map.get(&nodeid).unwrap_or_else(|| {
+                        sess.fatal(&format!("no MIR map entry for node {}", nodeid))
+                    });
+                    try!(write_mir_pretty(mir, &mut out));
+                }
+                Ok(())
             }), &sess)
         }
 
diff --git a/src/librustc_front/Cargo.toml b/src/librustc_front/Cargo.toml
index eae0b0646a3..bf40cdbd330 100644
--- a/src/librustc_front/Cargo.toml
+++ b/src/librustc_front/Cargo.toml
@@ -12,3 +12,4 @@ crate-type = ["dylib"]
 log = { path = "../liblog" }
 syntax = { path = "../libsyntax" }
 serialize = { path = "../libserialize" }
+rustc_bitflags = { path = "../librustc_bitflags" }
diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs
index 4e2729f3dab..b5e56edb6e4 100644
--- a/src/librustc_front/fold.rs
+++ b/src/librustc_front/fold.rs
@@ -962,25 +962,28 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
         Pat {
             id: folder.new_id(id),
             node: match node {
-                PatWild => PatWild,
-                PatIdent(binding_mode, pth1, sub) => {
-                    PatIdent(binding_mode,
+                PatKind::Wild => PatKind::Wild,
+                PatKind::Ident(binding_mode, pth1, sub) => {
+                    PatKind::Ident(binding_mode,
                              Spanned {
                                  span: folder.new_span(pth1.span),
                                  node: folder.fold_ident(pth1.node),
                              },
                              sub.map(|x| folder.fold_pat(x)))
                 }
-                PatLit(e) => PatLit(folder.fold_expr(e)),
-                PatEnum(pth, pats) => {
-                    PatEnum(folder.fold_path(pth),
+                PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)),
+                PatKind::TupleStruct(pth, pats) => {
+                    PatKind::TupleStruct(folder.fold_path(pth),
                             pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
                 }
-                PatQPath(qself, pth) => {
+                PatKind::Path(pth) => {
+                    PatKind::Path(folder.fold_path(pth))
+                }
+                PatKind::QPath(qself, pth) => {
                     let qself = QSelf { ty: folder.fold_ty(qself.ty), ..qself };
-                    PatQPath(qself, folder.fold_path(pth))
+                    PatKind::QPath(qself, folder.fold_path(pth))
                 }
-                PatStruct(pth, fields, etc) => {
+                PatKind::Struct(pth, fields, etc) => {
                     let pth = folder.fold_path(pth);
                     let fs = fields.move_map(|f| {
                         Spanned {
@@ -992,16 +995,16 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
                             },
                         }
                     });
-                    PatStruct(pth, fs, etc)
+                    PatKind::Struct(pth, fs, etc)
                 }
-                PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
-                PatBox(inner) => PatBox(folder.fold_pat(inner)),
-                PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
-                PatRange(e1, e2) => {
-                    PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
+                PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))),
+                PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)),
+                PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl),
+                PatKind::Range(e1, e2) => {
+                    PatKind::Range(folder.fold_expr(e1), folder.fold_expr(e2))
                 }
-                PatVec(before, slice, after) => {
-                    PatVec(before.move_map(|x| folder.fold_pat(x)),
+                PatKind::Vec(before, slice, after) => {
+                    PatKind::Vec(before.move_map(|x| folder.fold_pat(x)),
                            slice.map(|x| folder.fold_pat(x)),
                            after.move_map(|x| folder.fold_pat(x)))
                 }
diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs
index 2625e34c820..dbc1d71517b 100644
--- a/src/librustc_front/hir.rs
+++ b/src/librustc_front/hir.rs
@@ -21,7 +21,6 @@ pub use self::FunctionRetTy::*;
 pub use self::ForeignItem_::*;
 pub use self::Item_::*;
 pub use self::Mutability::*;
-pub use self::Pat_::*;
 pub use self::PathListItem_::*;
 pub use self::PrimTy::*;
 pub use self::Stmt_::*;
@@ -475,7 +474,7 @@ pub struct Block {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Pat {
     pub id: NodeId,
-    pub node: Pat_,
+    pub node: PatKind,
     pub span: Span,
 }
 
@@ -506,45 +505,51 @@ pub enum BindingMode {
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum Pat_ {
+pub enum PatKind {
     /// Represents a wildcard pattern (`_`)
-    PatWild,
+    Wild,
 
-    /// A PatIdent may either be a new bound variable,
-    /// or a nullary enum (in which case the third field
-    /// is None).
+    /// A `PatKind::Ident` may either be a new bound variable,
+    /// or a unit struct/variant pattern, or a const pattern (in the last two cases
+    /// the third field must be `None`).
     ///
-    /// In the nullary enum case, the parser can't determine
+    /// In the unit or const pattern case, the parser can't determine
     /// which it is. The resolver determines this, and
-    /// records this pattern's NodeId in an auxiliary
-    /// set (of "PatIdents that refer to nullary enums")
-    PatIdent(BindingMode, Spanned<Ident>, Option<P<Pat>>),
+    /// records this pattern's `NodeId` in an auxiliary
+    /// set (of "PatIdents that refer to unit patterns or constants").
+    Ident(BindingMode, Spanned<Ident>, Option<P<Pat>>),
 
+    /// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
+    /// The `bool` is `true` in the presence of a `..`.
+    Struct(Path, HirVec<Spanned<FieldPat>>, bool),
+
+    /// A tuple struct/variant pattern `Variant(x, y, z)`.
     /// "None" means a `Variant(..)` pattern where we don't bind the fields to names.
-    PatEnum(Path, Option<HirVec<P<Pat>>>),
+    TupleStruct(Path, Option<HirVec<P<Pat>>>),
+
+    /// A path pattern.
+    /// Such pattern can be resolved to a unit struct/variant or a constant.
+    Path(Path),
 
     /// An associated const named using the qualified path `<T>::CONST` or
     /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
     /// referred to as simply `T::CONST`, in which case they will end up as
-    /// PatEnum, and the resolver will have to sort that out.
-    PatQPath(QSelf, Path),
+    /// PatKind::Path, and the resolver will have to sort that out.
+    QPath(QSelf, Path),
 
-    /// Destructuring of a struct, e.g. `Foo {x, y, ..}`
-    /// The `bool` is `true` in the presence of a `..`
-    PatStruct(Path, HirVec<Spanned<FieldPat>>, bool),
     /// A tuple pattern `(a, b)`
-    PatTup(HirVec<P<Pat>>),
+    Tup(HirVec<P<Pat>>),
     /// A `box` pattern
-    PatBox(P<Pat>),
+    Box(P<Pat>),
     /// A reference pattern, e.g. `&mut (a, b)`
-    PatRegion(P<Pat>, Mutability),
+    Ref(P<Pat>, Mutability),
     /// A literal
-    PatLit(P<Expr>),
+    Lit(P<Expr>),
     /// A range pattern, e.g. `1...2`
-    PatRange(P<Expr>, P<Expr>),
+    Range(P<Expr>, P<Expr>),
     /// `[a, b, ..i, y, z]` is represented as:
-    ///     `PatVec(box [a, b], Some(i), box [y, z])`
-    PatVec(HirVec<P<Pat>>, Option<P<Pat>>, HirVec<P<Pat>>),
+    ///     `PatKind::Vec(box [a, b], Some(i), box [y, z])`
+    Vec(HirVec<P<Pat>>, Option<P<Pat>>, HirVec<P<Pat>>),
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1015,7 +1020,7 @@ impl Arg {
             }),
             pat: P(Pat {
                 id: DUMMY_NODE_ID,
-                node: PatIdent(BindByValue(mutability), path, None),
+                node: PatKind::Ident(BindByValue(mutability), path, None),
                 span: span,
             }),
             id: DUMMY_NODE_ID,
diff --git a/src/librustc_front/intravisit.rs b/src/librustc_front/intravisit.rs
index 03b021cfa63..c1bcaab9d68 100644
--- a/src/librustc_front/intravisit.rs
+++ b/src/librustc_front/intravisit.rs
@@ -468,41 +468,44 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
 
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
     match pattern.node {
-        PatEnum(ref path, ref opt_children) => {
+        PatKind::TupleStruct(ref path, ref opt_children) => {
             visitor.visit_path(path, pattern.id);
             if let Some(ref children) = *opt_children {
                 walk_list!(visitor, visit_pat, children);
             }
         }
-        PatQPath(ref qself, ref path) => {
+        PatKind::Path(ref path) => {
+            visitor.visit_path(path, pattern.id);
+        }
+        PatKind::QPath(ref qself, ref path) => {
             visitor.visit_ty(&qself.ty);
             visitor.visit_path(path, pattern.id)
         }
-        PatStruct(ref path, ref fields, _) => {
+        PatKind::Struct(ref path, ref fields, _) => {
             visitor.visit_path(path, pattern.id);
             for field in fields {
                 visitor.visit_name(field.span, field.node.name);
                 visitor.visit_pat(&field.node.pat)
             }
         }
-        PatTup(ref tuple_elements) => {
+        PatKind::Tup(ref tuple_elements) => {
             walk_list!(visitor, visit_pat, tuple_elements);
         }
-        PatBox(ref subpattern) |
-        PatRegion(ref subpattern, _) => {
+        PatKind::Box(ref subpattern) |
+        PatKind::Ref(ref subpattern, _) => {
             visitor.visit_pat(subpattern)
         }
-        PatIdent(_, ref pth1, ref optional_subpattern) => {
+        PatKind::Ident(_, ref pth1, ref optional_subpattern) => {
             visitor.visit_ident(pth1.span, pth1.node);
             walk_list!(visitor, visit_pat, optional_subpattern);
         }
-        PatLit(ref expression) => visitor.visit_expr(expression),
-        PatRange(ref lower_bound, ref upper_bound) => {
+        PatKind::Lit(ref expression) => visitor.visit_expr(expression),
+        PatKind::Range(ref lower_bound, ref upper_bound) => {
             visitor.visit_expr(lower_bound);
             visitor.visit_expr(upper_bound)
         }
-        PatWild => (),
-        PatVec(ref prepatterns, ref slice_pattern, ref postpatterns) => {
+        PatKind::Wild => (),
+        PatKind::Vec(ref prepatterns, ref slice_pattern, ref postpatterns) => {
             walk_list!(visitor, visit_pat, prepatterns);
             walk_list!(visitor, visit_pat, slice_pattern);
             walk_list!(visitor, visit_pat, postpatterns);
diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs
index bb113a7ad6a..0e7d9db37fd 100644
--- a/src/librustc_front/lowering.rs
+++ b/src/librustc_front/lowering.rs
@@ -913,27 +913,27 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
     P(hir::Pat {
         id: p.id,
         node: match p.node {
-            PatKind::Wild => hir::PatWild,
+            PatKind::Wild => hir::PatKind::Wild,
             PatKind::Ident(ref binding_mode, pth1, ref sub) => {
-                hir::PatIdent(lower_binding_mode(lctx, binding_mode),
+                hir::PatKind::Ident(lower_binding_mode(lctx, binding_mode),
                               respan(pth1.span, lower_ident(lctx, pth1.node)),
                               sub.as_ref().map(|x| lower_pat(lctx, x)))
             }
-            PatKind::Lit(ref e) => hir::PatLit(lower_expr(lctx, e)),
+            PatKind::Lit(ref e) => hir::PatKind::Lit(lower_expr(lctx, e)),
             PatKind::TupleStruct(ref pth, ref pats) => {
-                hir::PatEnum(lower_path(lctx, pth),
+                hir::PatKind::TupleStruct(lower_path(lctx, pth),
                              pats.as_ref()
                                  .map(|pats| pats.iter().map(|x| lower_pat(lctx, x)).collect()))
             }
             PatKind::Path(ref pth) => {
-                hir::PatEnum(lower_path(lctx, pth), Some(hir::HirVec::new()))
+                hir::PatKind::Path(lower_path(lctx, pth))
             }
             PatKind::QPath(ref qself, ref pth) => {
                 let qself = hir::QSelf {
                     ty: lower_ty(lctx, &qself.ty),
                     position: qself.position,
                 };
-                hir::PatQPath(qself, lower_path(lctx, pth))
+                hir::PatKind::QPath(qself, lower_path(lctx, pth))
             }
             PatKind::Struct(ref pth, ref fields, etc) => {
                 let pth = lower_path(lctx, pth);
@@ -949,20 +949,20 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
                                    }
                                })
                                .collect();
-                hir::PatStruct(pth, fs, etc)
+                hir::PatKind::Struct(pth, fs, etc)
             }
             PatKind::Tup(ref elts) => {
-                hir::PatTup(elts.iter().map(|x| lower_pat(lctx, x)).collect())
+                hir::PatKind::Tup(elts.iter().map(|x| lower_pat(lctx, x)).collect())
             }
-            PatKind::Box(ref inner) => hir::PatBox(lower_pat(lctx, inner)),
+            PatKind::Box(ref inner) => hir::PatKind::Box(lower_pat(lctx, inner)),
             PatKind::Ref(ref inner, mutbl) => {
-                hir::PatRegion(lower_pat(lctx, inner), lower_mutability(lctx, mutbl))
+                hir::PatKind::Ref(lower_pat(lctx, inner), lower_mutability(lctx, mutbl))
             }
             PatKind::Range(ref e1, ref e2) => {
-                hir::PatRange(lower_expr(lctx, e1), lower_expr(lctx, e2))
+                hir::PatKind::Range(lower_expr(lctx, e1), lower_expr(lctx, e2))
             }
             PatKind::Vec(ref before, ref slice, ref after) => {
-                hir::PatVec(before.iter().map(|x| lower_pat(lctx, x)).collect(),
+                hir::PatKind::Vec(before.iter().map(|x| lower_pat(lctx, x)).collect(),
                             slice.as_ref().map(|x| lower_pat(lctx, x)),
                             after.iter().map(|x| lower_pat(lctx, x)).collect())
             }
@@ -1750,7 +1750,11 @@ fn pat_enum(lctx: &LoweringContext,
             path: hir::Path,
             subpats: hir::HirVec<P<hir::Pat>>)
             -> P<hir::Pat> {
-    let pt = hir::PatEnum(path, Some(subpats));
+    let pt = if subpats.is_empty() {
+        hir::PatKind::Path(path)
+    } else {
+        hir::PatKind::TupleStruct(path, Some(subpats))
+    };
     pat(lctx, span, pt)
 }
 
@@ -1763,7 +1767,7 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
                           ident: hir::Ident,
                           bm: hir::BindingMode)
                           -> P<hir::Pat> {
-    let pat_ident = hir::PatIdent(bm,
+    let pat_ident = hir::PatKind::Ident(bm,
                                   Spanned {
                                       span: span,
                                       node: ident,
@@ -1773,10 +1777,10 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
 }
 
 fn pat_wild(lctx: &LoweringContext, span: Span) -> P<hir::Pat> {
-    pat(lctx, span, hir::PatWild)
+    pat(lctx, span, hir::PatKind::Wild)
 }
 
-fn pat(lctx: &LoweringContext, span: Span, pat: hir::Pat_) -> P<hir::Pat> {
+fn pat(lctx: &LoweringContext, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
     P(hir::Pat {
         id: lctx.next_id(),
         node: pat,
diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs
index 1425fbe9511..d837ab0f8f6 100644
--- a/src/librustc_front/print/pprust.rs
+++ b/src/librustc_front/print/pprust.rs
@@ -24,7 +24,7 @@ use syntax::print::pprust::{self as ast_pp, PrintState};
 use syntax::ptr::P;
 
 use hir;
-use hir::{Crate, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
+use hir::{Crate, PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 
 use std::io::{self, Write, Read};
 
@@ -1727,8 +1727,8 @@ impl<'a> State<'a> {
         // Pat isn't normalized, but the beauty of it
         // is that it doesn't matter
         match pat.node {
-            hir::PatWild => try!(word(&mut self.s, "_")),
-            hir::PatIdent(binding_mode, ref path1, ref sub) => {
+            PatKind::Wild => try!(word(&mut self.s, "_")),
+            PatKind::Ident(binding_mode, ref path1, ref sub) => {
                 match binding_mode {
                     hir::BindByRef(mutbl) => {
                         try!(self.word_nbsp("ref"));
@@ -1748,23 +1748,24 @@ impl<'a> State<'a> {
                     None => (),
                 }
             }
-            hir::PatEnum(ref path, ref args_) => {
+            PatKind::TupleStruct(ref path, ref args_) => {
                 try!(self.print_path(path, true, 0));
                 match *args_ {
                     None => try!(word(&mut self.s, "(..)")),
                     Some(ref args) => {
-                        if !args.is_empty() {
-                            try!(self.popen());
-                            try!(self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&p)));
-                            try!(self.pclose());
-                        }
+                        try!(self.popen());
+                        try!(self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&p)));
+                        try!(self.pclose());
                     }
                 }
             }
-            hir::PatQPath(ref qself, ref path) => {
+            PatKind::Path(ref path) => {
+                try!(self.print_path(path, true, 0));
+            }
+            PatKind::QPath(ref qself, ref path) => {
                 try!(self.print_qpath(path, qself, false));
             }
-            hir::PatStruct(ref path, ref fields, etc) => {
+            PatKind::Struct(ref path, ref fields, etc) => {
                 try!(self.print_path(path, true, 0));
                 try!(self.nbsp());
                 try!(self.word_space("{"));
@@ -1789,7 +1790,7 @@ impl<'a> State<'a> {
                 try!(space(&mut self.s));
                 try!(word(&mut self.s, "}"));
             }
-            hir::PatTup(ref elts) => {
+            PatKind::Tup(ref elts) => {
                 try!(self.popen());
                 try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
                 if elts.len() == 1 {
@@ -1797,32 +1798,32 @@ impl<'a> State<'a> {
                 }
                 try!(self.pclose());
             }
-            hir::PatBox(ref inner) => {
+            PatKind::Box(ref inner) => {
                 try!(word(&mut self.s, "box "));
                 try!(self.print_pat(&inner));
             }
-            hir::PatRegion(ref inner, mutbl) => {
+            PatKind::Ref(ref inner, mutbl) => {
                 try!(word(&mut self.s, "&"));
                 if mutbl == hir::MutMutable {
                     try!(word(&mut self.s, "mut "));
                 }
                 try!(self.print_pat(&inner));
             }
-            hir::PatLit(ref e) => try!(self.print_expr(&e)),
-            hir::PatRange(ref begin, ref end) => {
+            PatKind::Lit(ref e) => try!(self.print_expr(&e)),
+            PatKind::Range(ref begin, ref end) => {
                 try!(self.print_expr(&begin));
                 try!(space(&mut self.s));
                 try!(word(&mut self.s, "..."));
                 try!(self.print_expr(&end));
             }
-            hir::PatVec(ref before, ref slice, ref after) => {
+            PatKind::Vec(ref before, ref slice, ref after) => {
                 try!(word(&mut self.s, "["));
                 try!(self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p)));
                 if let Some(ref p) = *slice {
                     if !before.is_empty() {
                         try!(self.word_space(","));
                     }
-                    if p.node != hir::PatWild {
+                    if p.node != PatKind::Wild {
                         try!(self.print_pat(&p));
                     }
                     try!(word(&mut self.s, ".."));
@@ -1945,7 +1946,7 @@ impl<'a> State<'a> {
             let m = match explicit_self {
                 &hir::SelfStatic => hir::MutImmutable,
                 _ => match decl.inputs[0].pat.node {
-                    hir::PatIdent(hir::BindByValue(m), _, _) => m,
+                    PatKind::Ident(hir::BindByValue(m), _, _) => m,
                     _ => hir::MutImmutable,
                 },
             };
@@ -2210,7 +2211,7 @@ impl<'a> State<'a> {
             hir::TyInfer if is_closure => try!(self.print_pat(&input.pat)),
             _ => {
                 match input.pat.node {
-                    hir::PatIdent(_, ref path1, _) if
+                    PatKind::Ident(_, ref path1, _) if
                         path1.node.name ==
                             parse::token::special_idents::invalid.name => {
                         // Do nothing.
diff --git a/src/librustc_front/util.rs b/src/librustc_front/util.rs
index 5d936fae6ec..8140ea1f167 100644
--- a/src/librustc_front/util.rs
+++ b/src/librustc_front/util.rs
@@ -28,27 +28,28 @@ pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool
         }
 
         match pat.node {
-            PatIdent(_, _, Some(ref p)) => walk_pat_(&p, it),
-            PatStruct(_, ref fields, _) => {
+            PatKind::Ident(_, _, Some(ref p)) => walk_pat_(&p, it),
+            PatKind::Struct(_, ref fields, _) => {
                 fields.iter().all(|field| walk_pat_(&field.node.pat, it))
             }
-            PatEnum(_, Some(ref s)) | PatTup(ref s) => {
+            PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => {
                 s.iter().all(|p| walk_pat_(&p, it))
             }
-            PatBox(ref s) | PatRegion(ref s, _) => {
+            PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
                 walk_pat_(&s, it)
             }
-            PatVec(ref before, ref slice, ref after) => {
+            PatKind::Vec(ref before, ref slice, ref after) => {
                 before.iter().all(|p| walk_pat_(&p, it)) &&
                 slice.iter().all(|p| walk_pat_(&p, it)) &&
                 after.iter().all(|p| walk_pat_(&p, it))
             }
-            PatWild |
-            PatLit(_) |
-            PatRange(_, _) |
-            PatIdent(_, _, _) |
-            PatEnum(_, _) |
-            PatQPath(_, _) => {
+            PatKind::Wild |
+            PatKind::Lit(_) |
+            PatKind::Range(_, _) |
+            PatKind::Ident(_, _, _) |
+            PatKind::TupleStruct(..) |
+            PatKind::Path(..) |
+            PatKind::QPath(_, _) => {
                 true
             }
         }
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index 367475a14a2..16ef6e001dd 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -17,7 +17,7 @@ use syntax::ast;
 use syntax::attr::{self, AttrMetaMethods};
 use syntax::codemap::Span;
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::intravisit::FnKind;
 
 #[derive(PartialEq)]
@@ -272,7 +272,7 @@ impl LateLintPass for NonSnakeCase {
     }
 
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
-        if let &hir::PatIdent(_, ref path1, _) = &p.node {
+        if let &PatKind::Ident(_, ref path1, _) = &p.node {
             let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
             if let Some(Def::Local(..)) = def {
                 self.check_snake_case(cx, "variable", &path1.node.name.as_str(), Some(p.span));
@@ -362,7 +362,7 @@ impl LateLintPass for NonUpperCaseGlobals {
     fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
-            (&hir::PatIdent(_, ref path1, _), Some(Def::Const(..))) => {
+            (&PatKind::Ident(_, ref path1, _), Some(Def::Const(..))) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
                                                       path1.node.name, p.span);
             }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index ed16a11f550..2780baa6de3 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -46,7 +46,7 @@ use syntax::{ast};
 use syntax::attr::{self, AttrMetaMethods};
 use syntax::codemap::{self, Span};
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::intravisit::FnKind;
 
 use bad_style::{MethodLateContext, method_context};
@@ -157,7 +157,7 @@ impl LintPass for NonShorthandFieldPatterns {
 impl LateLintPass for NonShorthandFieldPatterns {
     fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
         let def_map = cx.tcx.def_map.borrow();
-        if let hir::PatStruct(_, ref v, _) = pat.node {
+        if let PatKind::Struct(_, ref v, _) = pat.node {
             let field_pats = v.iter().filter(|fieldpat| {
                 if fieldpat.node.is_shorthand {
                     return false;
@@ -170,7 +170,7 @@ impl LateLintPass for NonShorthandFieldPatterns {
                 }
             });
             for fieldpat in field_pats {
-                if let hir::PatIdent(_, ident, None) = fieldpat.node.pat.node {
+                if let PatKind::Ident(_, ident, None) = fieldpat.node.pat.node {
                     if ident.node.unhygienic_name == fieldpat.node.name {
                         cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant and can \
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 6868b4f2ab7..1cf0339c086 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -159,6 +159,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
             reference: "the explanation for E0446 (`--explain E0446`)",
         },
         FutureIncompatibleInfo {
+            id: LintId::of(INACCESSIBLE_EXTERN_CRATE),
+            reference: "PR 31362 <https://github.com/rust-lang/rust/pull/31362>",
+        },
+        FutureIncompatibleInfo {
             id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
             reference: "PR 30742 <https://github.com/rust-lang/rust/pull/30724>",
         },
diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml
index 62e1a71d196..05d20911a5d 100644
--- a/src/librustc_llvm/Cargo.toml
+++ b/src/librustc_llvm/Cargo.toml
@@ -12,6 +12,9 @@ crate-type = ["dylib"]
 [features]
 static-libstdcpp = []
 
+[dependencies]
+rustc_bitflags = { path = "../librustc_bitflags" }
+
 [build-dependencies]
 build_helper = { path = "../build_helper" }
 gcc = "0.3"
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index 1c9982790cf..59164161b3d 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -38,6 +38,25 @@ fn main() {
 
     println!("cargo:rerun-if-changed={}", llvm_config.display());
 
+    // 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
+    // what this build script is currently running on.
+    //
+    // In that case, there's no guarantee that we can actually run the target,
+    // so the build system works around this by giving us the LLVM_CONFIG for
+    // the host platform. This only really works if the host LLVM and target
+    // LLVM are compiled the same way, but for us that's typically the case.
+    //
+    // We detect this cross compiling situation by asking llvm-config what it's
+    // host-target is. If that's not the TARGET, then we're cross compiling.
+    // This generally just means that we can't trust all the output of
+    // llvm-config becaues it might be targeted for the host rather than the
+    // target.
+    let target = env::var("TARGET").unwrap();
+    let host = output(Command::new(&llvm_config).arg("--host-target"));
+    let host = host.trim();
+    let is_crossed = target != host;
+
     let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc",
                                "pnacl"];
 
@@ -69,6 +88,10 @@ fn main() {
     let cxxflags = output(&mut cmd);
     let mut cfg = gcc::Config::new();
     for flag in cxxflags.split_whitespace() {
+        // Ignore flags like `-m64` when we're doing a cross build
+        if is_crossed && flag.starts_with("-m") {
+            continue
+        }
         cfg.flag(flag);
     }
     cfg.file("../rustllvm/ExecutionEngineWrapper.cpp")
@@ -79,9 +102,16 @@ fn main() {
        .cpp_link_stdlib(None) // we handle this below
        .compile("librustllvm.a");
 
-    // Link in all LLVM libraries
+    // Link in all LLVM libraries, if we're uwring the "wrong" llvm-config then
+    // we don't pick up system libs because unfortunately they're for the host
+    // of llvm-config, not the target that we're attempting to link.
     let mut cmd = Command::new(&llvm_config);
-    cmd.arg("--libs").arg("--system-libs").args(&components[..]);
+    cmd.arg("--libs");
+    if !is_crossed {
+        cmd.arg("--system-libs");
+    }
+    cmd.args(&components[..]);
+
     for lib in output(&mut cmd).split_whitespace() {
         let name = if lib.starts_with("-l") {
             &lib[2..]
@@ -105,10 +135,20 @@ fn main() {
     }
 
     // LLVM ldflags
+    //
+    // If we're a cross-compile of LLVM then unfortunately we can't trust these
+    // ldflags (largely where all the LLVM libs are located). Currently just
+    // hack around this by replacing the host triple with the target and pray
+    // that those -L directories are the same!
     let mut cmd = Command::new(&llvm_config);
     cmd.arg("--ldflags");
     for lib in output(&mut cmd).split_whitespace() {
-        if lib.starts_with("-l") {
+        if is_crossed {
+            if lib.starts_with("-L") {
+                println!("cargo:rustc-link-search=native={}",
+                         lib[2..].replace(&host, &target));
+            }
+        } else if lib.starts_with("-l") {
             println!("cargo:rustc-link-lib={}", &lib[2..]);
         } else if lib.starts_with("-L") {
             println!("cargo:rustc-link-search=native={}", &lib[2..]);
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 1933c926e30..13acf79a0f1 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -261,12 +261,12 @@ impl AttrBuilder {
         }
     }
 
-    pub fn arg<'a, T: AttrHelper + 'static>(&'a mut self, idx: usize, a: T) -> &'a mut AttrBuilder {
+    pub fn arg<T: AttrHelper + 'static>(&mut self, idx: usize, a: T) -> &mut AttrBuilder {
         self.attrs.push((idx, box a as Box<AttrHelper+'static>));
         self
     }
 
-    pub fn ret<'a, T: AttrHelper + 'static>(&'a mut self, a: T) -> &'a mut AttrBuilder {
+    pub fn ret<T: AttrHelper + 'static>(&mut self, a: T) -> &mut AttrBuilder {
         self.attrs.push((ReturnIndex as usize, box a as Box<AttrHelper+'static>));
         self
     }
@@ -1584,7 +1584,8 @@ extern {
                                   CMP: ValueRef,
                                   RHS: ValueRef,
                                   Order: AtomicOrdering,
-                                  FailureOrder: AtomicOrdering)
+                                  FailureOrder: AtomicOrdering,
+                                  Weak: Bool)
                                   -> ValueRef;
     pub fn LLVMBuildAtomicRMW(B: BuilderRef,
                               Op: AtomicBinOp,
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index 3f8249aabf9..d6bb4b157a6 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -14,6 +14,7 @@ log = { path = "../liblog" }
 rbml = { path = "../librbml" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
+rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_front = { path = "../librustc_front" }
 rustc_llvm = { path = "../librustc_llvm" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 3a0bd3aa205..fe4df865a0e 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -610,7 +610,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
 
         self.emit_enum("AutoAdjustment", |this| {
             match *adj {
-                adjustment::AdjustReifyFnPointer=> {
+                adjustment::AdjustReifyFnPointer => {
                     this.emit_enum_variant("AdjustReifyFnPointer", 1, 0, |_| Ok(()))
                 }
 
@@ -620,8 +620,14 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
                     })
                 }
 
+                adjustment::AdjustMutToConstPointer => {
+                    this.emit_enum_variant("AdjustMutToConstPointer", 3, 0, |_| {
+                        Ok(())
+                    })
+                }
+
                 adjustment::AdjustDerefRef(ref auto_deref_ref) => {
-                    this.emit_enum_variant("AdjustDerefRef", 3, 2, |this| {
+                    this.emit_enum_variant("AdjustDerefRef", 4, 2, |this| {
                         this.emit_enum_variant_arg(0,
                             |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
                     })
@@ -1002,12 +1008,14 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     fn read_auto_adjustment<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                     -> adjustment::AutoAdjustment<'tcx> {
         self.read_enum("AutoAdjustment", |this| {
-            let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", "AdjustDerefRef"];
+            let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer",
+                            "AdjustMutToConstPointer", "AdjustDerefRef"];
             this.read_enum_variant(&variants, |this, i| {
                 Ok(match i {
                     1 => adjustment::AdjustReifyFnPointer,
                     2 => adjustment::AdjustUnsafeFnPointer,
-                    3 => {
+                    3 => adjustment::AdjustMutToConstPointer,
+                    4 => {
                         let auto_deref_ref: adjustment::AutoDerefRef =
                             this.read_enum_variant_arg(0,
                                 |this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 207a680a13d..d707c61cbb4 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -50,7 +50,7 @@ use syntax::parse::token::special_idents;
 use syntax;
 use rbml::writer::Encoder;
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::intravisit::Visitor;
 use rustc_front::intravisit;
 
@@ -783,7 +783,7 @@ fn encode_method_argument_names(rbml_w: &mut Encoder,
     rbml_w.start_tag(tag_method_argument_names);
     for arg in &decl.inputs {
         let tag = tag_method_argument_name;
-        if let hir::PatIdent(_, ref path1, _) = arg.pat.node {
+        if let PatKind::Ident(_, ref path1, _) = arg.pat.node {
             let name = path1.node.name.as_str();
             rbml_w.wr_tagged_bytes(tag, name.as_bytes());
         } else {
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index f416ec75010..5386c5b77c2 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -23,7 +23,6 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(time2)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs
index 4e03ed489eb..b2c7507ed7b 100644
--- a/src/librustc_mir/build/expr/as_lvalue.rs
+++ b/src/librustc_mir/build/expr/as_lvalue.rs
@@ -41,7 +41,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             }
             ExprKind::Field { lhs, name } => {
                 let lvalue = unpack!(block = this.as_lvalue(block, lhs));
-                let lvalue = lvalue.field(name);
+                let lvalue = lvalue.field(name, expr.ty);
                 block.and(lvalue)
             }
             ExprKind::Deref { arg } => {
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index dea2d750b98..2338d7df01a 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -139,7 +139,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                           .collect();
                 block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars))
             }
-            ExprKind::Adt { adt_def, variant_index, substs, fields, base } => { // see (*) above
+            ExprKind::Adt {
+                adt_def, variant_index, substs, fields, base
+            } => { // see (*) above
                 // first process the set of fields that were provided
                 // (evaluating them in order given by user)
                 let fields_map: FnvHashMap<_, _> =
@@ -147,25 +149,24 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                           .map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr))))
                           .collect();
 
-                // if base expression is given, evaluate it now
-                let base = base.map(|base| unpack!(block = this.as_lvalue(block, base)));
-
-                // get list of all fields that we will need
                 let field_names = this.hir.all_fields(adt_def, variant_index);
 
-                // for the actual values we use, take either the
-                // expr the user specified or, if they didn't
-                // specify something for this field name, create a
-                // path relative to the base (which must have been
-                // supplied, or the IR is internally
-                // inconsistent).
-                let fields: Vec<_> =
+                let fields = if let Some(FruInfo { base, field_types }) = base {
+                    let base = unpack!(block = this.as_lvalue(block, base));
+
+                    // MIR does not natively support FRU, so for each
+                    // base-supplied field, generate an operand that
+                    // reads it from the base.
                     field_names.into_iter()
-                               .map(|n| match fields_map.get(&n) {
-                                   Some(v) => v.clone(),
-                                   None => Operand::Consume(base.clone().unwrap().field(n)),
-                               })
-                               .collect();
+                        .zip(field_types.into_iter())
+                        .map(|(n, ty)| match fields_map.get(&n) {
+                            Some(v) => v.clone(),
+                            None => Operand::Consume(base.clone().field(n, ty))
+                        })
+                        .collect()
+                } else {
+                    field_names.iter().map(|n| fields_map[n].clone()).collect()
+                };
 
                 block.and(Rvalue::Aggregate(AggregateKind::Adt(adt_def, variant_index, substs),
                                             fields))
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index ec67429379f..02f32da2b83 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -404,7 +404,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             subpatterns.iter()
                        .map(|subpattern| {
                            // e.g., `(x as Variant).0`
-                           let lvalue = downcast_lvalue.clone().field(subpattern.field);
+                           let lvalue = downcast_lvalue.clone().field(subpattern.field,
+                                                                      subpattern.field_ty());
                            // e.g., `(x as Variant).0 @ P1`
                            MatchPair::new(lvalue, &subpattern.pattern)
                        });
diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs
index dbb00a13cd3..c295ed168ba 100644
--- a/src/librustc_mir/build/matches/util.rs
+++ b/src/librustc_mir/build/matches/util.rs
@@ -21,7 +21,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                                    -> Vec<MatchPair<'pat, 'tcx>> {
         subpatterns.iter()
                    .map(|fieldpat| {
-                       let lvalue = lvalue.clone().field(fieldpat.field);
+                       let lvalue = lvalue.clone().field(fieldpat.field,
+                                                         fieldpat.field_ty());
                        MatchPair::new(lvalue, &fieldpat.pattern)
                    })
                    .collect()
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 86b34858189..b83d0f6a980 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -80,7 +80,7 @@ macro_rules! unpack {
 /// the main entry point for building MIR for a function
 
 pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
-                          _span: Span,
+                          span: Span,
                           implicit_arguments: Vec<Ty<'tcx>>,
                           explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
                           argument_extent: CodeExtent,
@@ -97,7 +97,7 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
         temp_decls: vec![],
         var_decls: vec![],
         var_indices: FnvHashMap(),
-        unit_temp: None
+        unit_temp: None,
     };
 
     assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
@@ -119,6 +119,7 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
         arg_decls: arg_decls,
         temp_decls: builder.temp_decls,
         return_ty: return_ty,
+        span: span
     }
 }
 
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 167317f426b..7be70867796 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -418,25 +418,28 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                              len: Operand<'tcx>,
                              span: Span) {
         // fn(&(filename: &'static str, line: u32), index: usize, length: usize) -> !
+        let region = ty::ReStatic; // FIXME(mir-borrowck): use a better region?
         let func = self.lang_function(lang_items::PanicBoundsCheckFnLangItem);
-        let args = func.ty.fn_args();
-        let ref_ty = args.skip_binder()[0];
-        let (region, tup_ty) = if let ty::TyRef(region, tyandmut) = ref_ty.sty {
-            (region, tyandmut.ty)
+        let args = self.hir.tcx().replace_late_bound_regions(&func.ty.fn_args(), |_| region).0;
+
+        let ref_ty = args[0];
+        let tup_ty = if let ty::TyRef(_, tyandmut) = ref_ty.sty {
+            tyandmut.ty
         } else {
             self.hir.span_bug(span, &format!("unexpected panic_bound_check type: {:?}", func.ty));
         };
+
         let (tuple, tuple_ref) = (self.temp(tup_ty), self.temp(ref_ty));
         let (file, line) = self.span_to_fileline_args(span);
         let elems = vec![Operand::Constant(file), Operand::Constant(line)];
         // FIXME: We should have this as a constant, rather than a stack variable (to not pollute
         // icache with cold branch code), however to achieve that we either have to rely on rvalue
         // promotion or have some way, in MIR, to create constants.
-        self.cfg.push_assign(block, DUMMY_SP, &tuple, // tuple = (file_arg, line_arg);
+        self.cfg.push_assign(block, span, &tuple, // tuple = (file_arg, line_arg);
                              Rvalue::Aggregate(AggregateKind::Tuple, elems));
         // FIXME: is this region really correct here?
-        self.cfg.push_assign(block, DUMMY_SP, &tuple_ref, // tuple_ref = &tuple;
-                             Rvalue::Ref(*region, BorrowKind::Unique, tuple));
+        self.cfg.push_assign(block, span, &tuple_ref, // tuple_ref = &tuple;
+                             Rvalue::Ref(region, BorrowKind::Shared, tuple));
         let cleanup = self.diverge_cleanup();
         self.cfg.terminate(block, Terminator::Call {
             func: Operand::Constant(func),
@@ -449,18 +452,21 @@ impl<'a,'tcx> Builder<'a,'tcx> {
     /// Create diverge cleanup and branch to it from `block`.
     pub fn panic(&mut self, block: BasicBlock, msg: &'static str, span: Span) {
         // fn(&(msg: &'static str filename: &'static str, line: u32)) -> !
+        let region = ty::ReStatic; // FIXME(mir-borrowck): use a better region?
         let func = self.lang_function(lang_items::PanicFnLangItem);
-        let args = func.ty.fn_args();
-        let ref_ty = args.skip_binder()[0];
-        let (region, tup_ty) = if let ty::TyRef(region, tyandmut) = ref_ty.sty {
-            (region, tyandmut.ty)
+        let args = self.hir.tcx().replace_late_bound_regions(&func.ty.fn_args(), |_| region).0;
+
+        let ref_ty = args[0];
+        let tup_ty = if let ty::TyRef(_, tyandmut) = ref_ty.sty {
+            tyandmut.ty
         } else {
             self.hir.span_bug(span, &format!("unexpected panic type: {:?}", func.ty));
         };
+
         let (tuple, tuple_ref) = (self.temp(tup_ty), self.temp(ref_ty));
         let (file, line) = self.span_to_fileline_args(span);
         let message = Constant {
-            span: DUMMY_SP,
+            span: span,
             ty: self.hir.tcx().mk_static_str(),
             literal: self.hir.str_literal(intern_and_get_ident(msg))
         };
@@ -470,11 +476,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         // FIXME: We should have this as a constant, rather than a stack variable (to not pollute
         // icache with cold branch code), however to achieve that we either have to rely on rvalue
         // promotion or have some way, in MIR, to create constants.
-        self.cfg.push_assign(block, DUMMY_SP, &tuple, // tuple = (message_arg, file_arg, line_arg);
+        self.cfg.push_assign(block, span, &tuple, // tuple = (message_arg, file_arg, line_arg);
                              Rvalue::Aggregate(AggregateKind::Tuple, elems));
         // FIXME: is this region really correct here?
-        self.cfg.push_assign(block, DUMMY_SP, &tuple_ref, // tuple_ref = &tuple;
-                             Rvalue::Ref(*region, BorrowKind::Unique, tuple));
+        self.cfg.push_assign(block, span, &tuple_ref, // tuple_ref = &tuple;
+                             Rvalue::Ref(region, BorrowKind::Shared, tuple));
         let cleanup = self.diverge_cleanup();
         self.cfg.terminate(block, Terminator::Call {
             func: Operand::Constant(func),
@@ -505,11 +511,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
     fn span_to_fileline_args(&mut self, span: Span) -> (Constant<'tcx>, Constant<'tcx>) {
         let span_lines = self.hir.tcx().sess.codemap().lookup_char_pos(span.lo);
         (Constant {
-            span: DUMMY_SP,
+            span: span,
             ty: self.hir.tcx().mk_static_str(),
             literal: self.hir.str_literal(intern_and_get_ident(&span_lines.file.name))
         }, Constant {
-            span: DUMMY_SP,
+            span: span,
             ty: self.hir.tcx().types.u32,
             literal: self.hir.usize_literal(span_lines.line)
         })
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 90d049cdc73..ac1cff527fe 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -32,6 +32,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
         debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
 
         let expr_ty = cx.tcx.expr_ty(self); // note: no adjustments (yet)!
+        let temp_lifetime = cx.tcx.region_maps.temporary_scope(self.id);
+        let expr_extent = cx.tcx.region_maps.node_extent(self.id);
 
         let kind = match self.node {
             // Here comes the interesting stuff:
@@ -54,14 +56,35 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     // Find the actual method implementation being called and
                     // build the appropriate UFCS call expression with the
                     // callee-object as self parameter.
+
+                    // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
+
                     let method = method_callee(cx, self, ty::MethodCall::expr(self.id));
-                    let mut argrefs = vec![fun.to_ref()];
-                    argrefs.extend(args.iter().map(|a| a.to_ref()));
+
+                    let sig = match method.ty.sty {
+                        ty::TyBareFn(_, fn_ty) => &fn_ty.sig,
+                        _ => cx.tcx.sess.span_bug(self.span, "type of method is not an fn")
+                    };
+
+                    let sig = cx.tcx.no_late_bound_regions(sig).unwrap_or_else(|| {
+                        cx.tcx.sess.span_bug(self.span, "method call has late-bound regions")
+                    });
+
+                    assert_eq!(sig.inputs.len(), 2);
+
+                    let tupled_args = Expr {
+                        ty: sig.inputs[1],
+                        temp_lifetime: temp_lifetime,
+                        span: self.span,
+                        kind: ExprKind::Tuple {
+                            fields: args.iter().map(ToRef::to_ref).collect()
+                        }
+                    };
 
                     ExprKind::Call {
                         ty: method.ty,
                         fun: method.to_ref(),
-                        args: argrefs,
+                        args: vec![fun.to_ref(), tupled_args.to_ref()]
                     }
                 } else {
                     let adt_data = if let hir::ExprPath(..) = fun.node {
@@ -125,11 +148,20 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
             }
 
             hir::ExprAssignOp(op, ref lhs, ref rhs) => {
-                let op = bin_op(op.node);
-                ExprKind::AssignOp {
-                    op: op,
-                    lhs: lhs.to_ref(),
-                    rhs: rhs.to_ref(),
+                if cx.tcx.is_method_call(self.id) {
+                    let pass_args = if hir_util::is_by_value_binop(op.node) {
+                        PassArgs::ByValue
+                    } else {
+                        PassArgs::ByRef
+                    };
+                    overloaded_operator(cx, self, ty::MethodCall::expr(self.id),
+                                        pass_args, lhs.to_ref(), vec![rhs])
+                } else {
+                    ExprKind::AssignOp {
+                        op: bin_op(op.node),
+                        lhs: lhs.to_ref(),
+                        rhs: rhs.to_ref(),
+                    }
                 }
             }
 
@@ -227,13 +259,23 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                             variant_index: 0,
                             substs: substs,
                             fields: field_refs,
-                            base: base.to_ref(),
+                            base: base.as_ref().map(|base| {
+                                FruInfo {
+                                    base: base.to_ref(),
+                                    field_types: cx.tcx.tables
+                                        .borrow()
+                                        .fru_field_types[&self.id]
+                                        .clone()
+                                }
+                            })
                         }
                     }
                     ty::TyEnum(adt, substs) => {
                         match cx.tcx.def_map.borrow()[&self.id].full_def() {
                             Def::Variant(enum_id, variant_id) => {
                                 debug_assert!(adt.did == enum_id);
+                                assert!(base.is_none());
+
                                 let index = adt.variant_index_with_id(variant_id);
                                 let field_refs = field_refs(&adt.variants[index], fields);
                                 ExprKind::Adt {
@@ -241,7 +283,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                                     variant_index: index,
                                     substs: substs,
                                     fields: field_refs,
-                                    base: base.to_ref(),
+                                    base: None
                                 }
                             }
                             ref def => {
@@ -385,9 +427,6 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                 ExprKind::Tuple { fields: fields.to_ref() },
         };
 
-        let temp_lifetime = cx.tcx.region_maps.temporary_scope(self.id);
-        let expr_extent = cx.tcx.region_maps.node_extent(self.id);
-
         let mut expr = Expr {
             temp_lifetime: temp_lifetime,
             ty: expr_ty,
@@ -395,6 +434,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
             kind: kind,
         };
 
+        debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}",
+               expr, cx.tcx.tables.borrow().adjustments.get(&self.id));
+
         // Now apply adjustments, if any.
         match cx.tcx.tables.borrow().adjustments.get(&self.id) {
             None => {}
@@ -416,6 +458,15 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
                 };
             }
+            Some(&ty::adjustment::AdjustMutToConstPointer) => {
+                let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
+                expr = Expr {
+                    temp_lifetime: temp_lifetime,
+                    ty: adjusted_ty,
+                    span: self.span,
+                    kind: ExprKind::Cast { source: expr.to_ref() },
+                };
+            }
             Some(&ty::adjustment::AdjustDerefRef(ref adj)) => {
                 for i in 0..adj.autoderefs {
                     let i = i as u32;
@@ -426,10 +477,38 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                             self.span,
                             i,
                             |mc| cx.tcx.tables.borrow().method_map.get(&mc).map(|m| m.ty));
-                    let kind = if cx.tcx.is_overloaded_autoderef(self.id, i) {
-                        overloaded_lvalue(cx, self, ty::MethodCall::autoderef(self.id, i),
-                                          PassArgs::ByValue, expr.to_ref(), vec![])
+                    debug!("make_mirror: autoderef #{}, adjusted_ty={:?}", i, adjusted_ty);
+                    let method_key = ty::MethodCall::autoderef(self.id, i);
+                    let meth_ty =
+                        cx.tcx.tables.borrow().method_map.get(&method_key).map(|m| m.ty);
+                    let kind = if let Some(meth_ty) = meth_ty {
+                        debug!("make_mirror: overloaded autoderef (meth_ty={:?})", meth_ty);
+
+                        let ref_ty = cx.tcx.no_late_bound_regions(&meth_ty.fn_ret());
+                        let (region, mutbl) = match ref_ty {
+                            Some(ty::FnConverging(&ty::TyS {
+                                sty: ty::TyRef(region, mt), ..
+                            })) => (region, mt.mutbl),
+                            _ => cx.tcx.sess.span_bug(
+                                expr.span, "autoderef returned bad type")
+                        };
+
+                        expr = Expr {
+                            temp_lifetime: temp_lifetime,
+                            ty: cx.tcx.mk_ref(
+                                region, ty::TypeAndMut { ty: expr.ty, mutbl: mutbl }),
+                            span: expr.span,
+                            kind: ExprKind::Borrow {
+                                region: *region,
+                                borrow_kind: to_borrow_kind(mutbl),
+                                arg: expr.to_ref()
+                            }
+                        };
+
+                        overloaded_lvalue(cx, self, method_key,
+                                          PassArgs::ByRef, expr.to_ref(), vec![])
                     } else {
+                        debug!("make_mirror: built-in autoderef");
                         ExprKind::Deref { arg: expr.to_ref() }
                     };
                     expr = Expr {
@@ -749,11 +828,16 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             };
             match upvar_capture {
                 ty::UpvarCapture::ByValue => field_kind,
-                ty::UpvarCapture::ByRef(_) => {
+                ty::UpvarCapture::ByRef(borrow) => {
                     ExprKind::Deref {
                         arg: Expr {
                             temp_lifetime: temp_lifetime,
-                            ty: var_ty,
+                            ty: cx.tcx.mk_ref(
+                                cx.tcx.mk_region(borrow.region),
+                                ty::TypeAndMut {
+                                    ty: var_ty,
+                                    mutbl: borrow.kind.to_mutbl_lossy()
+                                }),
                             span: expr.span,
                             kind: field_kind,
                         }.to_ref()
diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs
index 5985a88382e..6f4375d53ec 100644
--- a/src/librustc_mir/hair/cx/pattern.rs
+++ b/src/librustc_mir/hair/cx/pattern.rs
@@ -16,7 +16,7 @@ use rustc::middle::def::Def;
 use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
 use rustc::middle::ty::{self, Ty};
 use rustc::mir::repr::*;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::ptr::P;
@@ -64,14 +64,14 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
 
     fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
         let kind = match pat.node {
-            hir::PatWild => PatternKind::Wild,
+            PatKind::Wild => PatternKind::Wild,
 
-            hir::PatLit(ref value) => {
+            PatKind::Lit(ref value) => {
                 let value = const_eval::eval_const_expr(self.cx.tcx, value);
                 PatternKind::Constant { value: value }
             }
 
-            hir::PatRange(ref lo, ref hi) => {
+            PatKind::Range(ref lo, ref hi) => {
                 let lo = const_eval::eval_const_expr(self.cx.tcx, lo);
                 let lo = Literal::Value { value: lo };
                 let hi = const_eval::eval_const_expr(self.cx.tcx, hi);
@@ -79,7 +79,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 PatternKind::Range { lo: lo, hi: hi }
             },
 
-            hir::PatEnum(..) | hir::PatIdent(..) | hir::PatQPath(..)
+            PatKind::Path(..) | PatKind::Ident(..) | PatKind::QPath(..)
                 if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) =>
             {
                 let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
@@ -105,12 +105,12 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 }
             }
 
-            hir::PatRegion(ref subpattern, _) |
-            hir::PatBox(ref subpattern) => {
+            PatKind::Ref(ref subpattern, _) |
+            PatKind::Box(ref subpattern) => {
                 PatternKind::Deref { subpattern: self.to_pattern(subpattern) }
             }
 
-            hir::PatVec(ref prefix, ref slice, ref suffix) => {
+            PatKind::Vec(ref prefix, ref slice, ref suffix) => {
                 let ty = self.cx.tcx.node_id_to_type(pat.id);
                 match ty.sty {
                     ty::TyRef(_, mt) =>
@@ -134,7 +134,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 }
             }
 
-            hir::PatTup(ref subpatterns) => {
+            PatKind::Tup(ref subpatterns) => {
                 let subpatterns =
                     subpatterns.iter()
                                .enumerate()
@@ -147,7 +147,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 PatternKind::Leaf { subpatterns: subpatterns }
             }
 
-            hir::PatIdent(bm, ref ident, ref sub)
+            PatKind::Ident(bm, ref ident, ref sub)
                 if pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) =>
             {
                 let id = match self.binding_map {
@@ -179,11 +179,11 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 }
             }
 
-            hir::PatIdent(..) => {
+            PatKind::Ident(..) | PatKind::Path(..) => {
                 self.variant_or_leaf(pat, vec![])
             }
 
-            hir::PatEnum(_, ref opt_subpatterns) => {
+            PatKind::TupleStruct(_, ref opt_subpatterns) => {
                 let subpatterns =
                     opt_subpatterns.iter()
                                    .flat_map(|v| v.iter())
@@ -196,7 +196,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 self.variant_or_leaf(pat, subpatterns)
             }
 
-            hir::PatStruct(_, ref fields, _) => {
+            PatKind::Struct(_, ref fields, _) => {
                 let pat_ty = self.cx.tcx.node_id_to_type(pat.id);
                 let adt_def = match pat_ty.sty {
                     ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def,
@@ -229,7 +229,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 self.variant_or_leaf(pat, subpatterns)
             }
 
-            hir::PatQPath(..) => {
+            PatKind::QPath(..) => {
                 self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc");
             }
         };
@@ -314,3 +314,20 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
         }
     }
 }
+
+impl<'tcx> FieldPattern<'tcx> {
+    pub fn field_ty(&self) -> Ty<'tcx> {
+        debug!("field_ty({:?},ty={:?})", self, self.pattern.ty);
+        let r = match *self.pattern.kind {
+            PatternKind::Binding { mode: BindingMode::ByRef(..), ..} => {
+                match self.pattern.ty.sty {
+                    ty::TyRef(_, mt) => mt.ty,
+                    _ => unreachable!()
+                }
+            }
+            _ => self.pattern.ty
+        };
+        debug!("field_ty -> {:?}", r);
+        r
+    }
+}
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 0891c2845b0..e8edd4067e2 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -229,7 +229,7 @@ pub enum ExprKind<'tcx> {
         variant_index: usize,
         substs: &'tcx Substs<'tcx>,
         fields: Vec<FieldExprRef<'tcx>>,
-        base: Option<ExprRef<'tcx>>,
+        base: Option<FruInfo<'tcx>>
     },
     Closure {
         closure_id: DefId,
@@ -257,6 +257,12 @@ pub struct FieldExprRef<'tcx> {
 }
 
 #[derive(Clone, Debug)]
+pub struct FruInfo<'tcx> {
+    pub base: ExprRef<'tcx>,
+    pub field_types: Vec<Ty<'tcx>>
+}
+
+#[derive(Clone, Debug)]
 pub struct Arm<'tcx> {
     pub patterns: Vec<Pattern<'tcx>>,
     pub guard: Option<ExprRef<'tcx>>,
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 6f4128fc24d..5d915f37f6e 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -20,6 +20,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![cfg_attr(not(stage0), deny(warnings))]
 #![unstable(feature = "rustc_private", issue = "27812")]
 
+#![feature(box_patterns)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index 0e641bf679d..70c33540121 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -22,7 +22,8 @@ extern crate rustc_front;
 use build;
 use graphviz;
 use pretty;
-use transform::simplify_cfg;
+use transform::{clear_dead_blocks, simplify_cfg, type_check};
+use transform::{no_landing_pads};
 use rustc::dep_graph::DepNode;
 use rustc::mir::repr::Mir;
 use hair::cx::Cx;
@@ -148,8 +149,12 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
 
         match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
             Ok(mut mir) => {
-                simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir, self.tcx);
-
+                clear_dead_blocks::ClearDeadBlocks::new().run_on_mir(&mut mir, &infcx);
+                type_check::TypeckMir::new().run_on_mir(&mut mir, &infcx);
+                no_landing_pads::NoLandingPads.run_on_mir(&mut mir, &infcx);
+                if self.tcx.sess.opts.mir_opt_level > 0 {
+                    simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir, &infcx);
+                }
                 let meta_item_list = self.attr
                                          .iter()
                                          .flat_map(|a| a.meta_item_list())
diff --git a/src/librustc_mir/transform/clear_dead_blocks.rs b/src/librustc_mir/transform/clear_dead_blocks.rs
new file mode 100644
index 00000000000..b35d8c08f5d
--- /dev/null
+++ b/src/librustc_mir/transform/clear_dead_blocks.rs
@@ -0,0 +1,81 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A pass that erases the contents of dead blocks. This pass must
+//! run before any analysis passes because some of the dead blocks
+//! can be ill-typed.
+//!
+//! The main problem is that typeck lets most blocks whose end is not
+//! reachable have an arbitrary return type, rather than having the
+//! usual () return type (as a note, typeck's notion of reachability
+//! is in fact slightly weaker than MIR CFG reachability - see #31617).
+//!
+//! A standard example of the situation is:
+//! ```rust
+//!   fn example() {
+//!       let _a: char = { return; };
+//!   }
+//! ```
+//!
+//! Here the block (`{ return; }`) has the return type `char`,
+//! rather than `()`, but the MIR we naively generate still contains
+//! the `_a = ()` write in the unreachable block "after" the return.
+//!
+//! As we have to run this pass even when we want to debug the MIR,
+//! this pass just replaces the blocks with empty "return" blocks
+//! and does not renumber anything.
+
+use rustc::middle::infer;
+use rustc::mir::repr::*;
+use rustc::mir::transform::MirPass;
+
+pub struct ClearDeadBlocks;
+
+impl ClearDeadBlocks {
+    pub fn new() -> ClearDeadBlocks {
+        ClearDeadBlocks
+    }
+
+    fn clear_dead_blocks(&self, mir: &mut Mir) {
+        let mut seen = vec![false; mir.basic_blocks.len()];
+
+        // These blocks are always required.
+        seen[START_BLOCK.index()] = true;
+        seen[END_BLOCK.index()] = true;
+
+        let mut worklist = vec![START_BLOCK];
+        while let Some(bb) = worklist.pop() {
+            for succ in mir.basic_block_data(bb).terminator().successors().iter() {
+                if !seen[succ.index()] {
+                    seen[succ.index()] = true;
+                    worklist.push(*succ);
+                }
+            }
+        }
+
+        for (n, (block, seen)) in mir.basic_blocks.iter_mut().zip(seen).enumerate() {
+            if !seen {
+                info!("clearing block #{}: {:?}", n, block);
+                *block = BasicBlockData {
+                    statements: vec![],
+                    terminator: Some(Terminator::Return),
+                    is_cleanup: false
+                };
+            }
+        }
+    }
+}
+
+impl MirPass for ClearDeadBlocks {
+    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &infer::InferCtxt<'a, 'tcx>)
+    {
+        self.clear_dead_blocks(mir);
+    }
+}
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index b927ab489f1..a82d1fc5399 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -16,18 +16,13 @@ use rustc::middle::ty;
 use rustc::mir::repr::*;
 use rustc::mir::visit::MutVisitor;
 use rustc::mir::mir_map::MirMap;
-use rustc::mir::transform::MirPass;
 
 pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) {
-    let mut eraser = EraseRegions;
-
     for (_, mir) in &mut mir_map.map {
-        eraser.run_on_mir(mir, tcx);
+        EraseRegionsVisitor::new(tcx).visit_mir(mir);
     }
 }
 
-pub struct EraseRegions;
-
 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
 }
@@ -58,12 +53,6 @@ impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
     }
 }
 
-impl MirPass for EraseRegions {
-    fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) {
-        EraseRegionsVisitor::new(tcx).visit_mir(mir);
-    }
-}
-
 impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
     fn visit_mir(&mut self, mir: &mut Mir<'tcx>) {
         self.erase_regions_return_ty(&mut mir.return_ty);
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 41ea4469734..adca68114fd 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+pub mod clear_dead_blocks;
 pub mod simplify_cfg;
 pub mod erase_regions;
-mod util;
+pub mod no_landing_pads;
+pub mod type_check;
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
new file mode 100644
index 00000000000..e2c93bd4e87
--- /dev/null
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -0,0 +1,50 @@
+// 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.
+
+//! This pass removes the unwind branch of all the terminators when the no-landing-pads option is
+//! specified.
+
+use rustc::middle::infer;
+use rustc::mir::repr::*;
+use rustc::mir::visit::MutVisitor;
+use rustc::mir::transform::MirPass;
+
+pub struct NoLandingPads;
+
+impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
+    fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
+        match *terminator {
+            Terminator::Goto { .. } |
+            Terminator::Resume |
+            Terminator::Return |
+            Terminator::If { .. } |
+            Terminator::Switch { .. } |
+            Terminator::SwitchInt { .. } => {
+                /* nothing to do */
+            },
+            Terminator::Drop { ref mut unwind, .. } => {
+                unwind.take();
+            },
+            Terminator::Call { ref mut cleanup, .. } => {
+                cleanup.take();
+            },
+        }
+        self.super_terminator(bb, terminator);
+    }
+}
+
+impl MirPass for NoLandingPads {
+    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>,
+                            infcx: &infer::InferCtxt<'a, 'tcx>) {
+        if infcx.tcx.sess.no_landing_pads() {
+            self.visit_mir(mir);
+        }
+    }
+}
diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs
index 17c5b5f7c3c..785e6db57a5 100644
--- a/src/librustc_mir/transform/simplify_cfg.rs
+++ b/src/librustc_mir/transform/simplify_cfg.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc_data_structures::bitvec::BitVector;
 use rustc::middle::const_eval::ConstVal;
+use rustc::middle::infer;
 use rustc::mir::repr::*;
-use transform::util;
 use rustc::mir::transform::MirPass;
 
 pub struct SimplifyCfg;
@@ -21,23 +22,21 @@ impl SimplifyCfg {
     }
 
     fn remove_dead_blocks(&self, mir: &mut Mir) {
-        let mut seen = vec![false; mir.basic_blocks.len()];
-
+        let mut seen = BitVector::new(mir.basic_blocks.len());
         // These blocks are always required.
-        seen[START_BLOCK.index()] = true;
-        seen[END_BLOCK.index()] = true;
+        seen.insert(START_BLOCK.index());
+        seen.insert(END_BLOCK.index());
 
-        let mut worklist = vec![START_BLOCK];
+        let mut worklist = Vec::with_capacity(4);
+        worklist.push(START_BLOCK);
         while let Some(bb) = worklist.pop() {
             for succ in mir.basic_block_data(bb).terminator().successors().iter() {
-                if !seen[succ.index()] {
-                    seen[succ.index()] = true;
+                if seen.insert(succ.index()) {
                     worklist.push(*succ);
                 }
             }
         }
-
-        util::retain_basic_blocks(mir, &seen);
+        retain_basic_blocks(mir, &seen);
     }
 
     fn remove_goto_chains(&self, mir: &mut Mir) -> bool {
@@ -89,12 +88,12 @@ impl SimplifyCfg {
         for bb in mir.all_basic_blocks() {
             let basic_block = mir.basic_block_data_mut(bb);
             let mut terminator = basic_block.terminator_mut();
-
             *terminator = match *terminator {
                 Terminator::If { ref targets, .. } if targets.0 == targets.1 => {
                     changed = true;
                     Terminator::Goto { target: targets.0 }
                 }
+
                 Terminator::If { ref targets, cond: Operand::Constant(Constant {
                     literal: Literal::Value {
                         value: ConstVal::Bool(cond)
@@ -107,6 +106,7 @@ impl SimplifyCfg {
                         Terminator::Goto { target: targets.1 }
                     }
                 }
+
                 Terminator::SwitchInt { ref targets, .. }  if targets.len() == 1 => {
                     Terminator::Goto { target: targets[0] }
                 }
@@ -119,7 +119,7 @@ impl SimplifyCfg {
 }
 
 impl MirPass for SimplifyCfg {
-    fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &::rustc::middle::ty::ctxt<'tcx>) {
+    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &infer::InferCtxt<'a, 'tcx>) {
         let mut changed = true;
         while changed {
             changed = self.simplify_branches(mir);
@@ -130,3 +130,27 @@ impl MirPass for SimplifyCfg {
         mir.basic_blocks.shrink_to_fit();
     }
 }
+
+/// Mass removal of basic blocks to keep the ID-remapping cheap.
+fn retain_basic_blocks(mir: &mut Mir, keep: &BitVector) {
+    let num_blocks = mir.basic_blocks.len();
+
+    let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
+    let mut used_blocks = 0;
+    for alive_index in keep.iter() {
+        replacements[alive_index] = BasicBlock::new(used_blocks);
+        if alive_index != used_blocks {
+            // Swap the next alive block data with the current available slot. Since alive_index is
+            // non-decreasing this is a valid operation.
+            mir.basic_blocks.swap(alive_index, used_blocks);
+        }
+        used_blocks += 1;
+    }
+    mir.basic_blocks.truncate(used_blocks);
+
+    for bb in mir.all_basic_blocks() {
+        for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
+            *target = replacements[target.index()];
+        }
+    }
+}
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
new file mode 100644
index 00000000000..0e97e362906
--- /dev/null
+++ b/src/librustc_mir/transform/type_check.rs
@@ -0,0 +1,598 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This pass type-checks the MIR to ensure it is not broken.
+#![allow(unreachable_code)]
+
+use rustc::middle::infer::{self, InferCtxt};
+use rustc::middle::traits;
+use rustc::middle::ty::{self, Ty};
+use rustc::middle::ty::fold::TypeFoldable;
+use rustc::mir::repr::*;
+use rustc::mir::tcx::LvalueTy;
+use rustc::mir::transform::MirPass;
+use rustc::mir::visit::{self, Visitor};
+
+use syntax::codemap::{Span, DUMMY_SP};
+use std::fmt;
+
+macro_rules! span_mirbug {
+    ($context:expr, $elem:expr, $($message:tt)*) => ({
+        $context.tcx().sess.span_warn(
+            $context.last_span,
+            &format!("broken MIR ({:?}): {}", $elem, format!($($message)*))
+        )
+    })
+}
+
+macro_rules! span_mirbug_and_err {
+    ($context:expr, $elem:expr, $($message:tt)*) => ({
+        {
+            $context.tcx().sess.span_warn(
+                $context.last_span,
+                &format!("broken MIR ({:?}): {:?}", $elem, format!($($message)*))
+            );
+            $context.error()
+        }
+    })
+}
+
+enum FieldAccessError {
+    OutOfRange { field_count: usize }
+}
+
+/// Verifies that MIR types are sane to not crash further checks.
+///
+/// The sanitize_XYZ methods here take an MIR object and compute its
+/// type, calling `span_mirbug` and returning an error type if there
+/// is a problem.
+struct TypeVerifier<'a, 'b: 'a, 'tcx: 'b> {
+    cx: &'a mut TypeChecker<'b, 'tcx>,
+    mir: &'a Mir<'tcx>,
+    last_span: Span,
+    errors_reported: bool
+}
+
+impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
+    fn visit_span(&mut self, span: &Span) {
+        if *span != DUMMY_SP {
+            self.last_span = *span;
+        }
+    }
+
+    fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, _context: visit::LvalueContext) {
+        self.sanitize_lvalue(lvalue);
+    }
+
+    fn visit_constant(&mut self, constant: &Constant<'tcx>) {
+        self.super_constant(constant);
+        self.sanitize_type(constant, constant.ty);
+    }
+
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
+        self.super_rvalue(rvalue);
+        if let Some(ty) = self.mir.rvalue_ty(self.tcx(), rvalue) {
+            self.sanitize_type(rvalue, ty);
+        }
+    }
+
+    fn visit_mir(&mut self, mir: &Mir<'tcx>) {
+        if let ty::FnConverging(t) = mir.return_ty {
+            self.sanitize_type(&"return type", t);
+        }
+        for var_decl in &mir.var_decls {
+            self.sanitize_type(var_decl, var_decl.ty);
+        }
+        for (n, arg_decl) in mir.arg_decls.iter().enumerate() {
+            self.sanitize_type(&(n, arg_decl), arg_decl.ty);
+        }
+        for (n, tmp_decl) in mir.temp_decls.iter().enumerate() {
+            self.sanitize_type(&(n, tmp_decl), tmp_decl.ty);
+        }
+        if self.errors_reported {
+            return;
+        }
+        self.super_mir(mir);
+    }
+}
+
+impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
+    fn new(cx: &'a mut TypeChecker<'b, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+        TypeVerifier {
+            cx: cx,
+            mir: mir,
+            last_span: mir.span,
+            errors_reported: false
+        }
+    }
+
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+        self.cx.infcx.tcx
+    }
+
+    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
+        self.cx.infcx
+    }
+
+    fn sanitize_type(&mut self, parent: &fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if ty.needs_infer() || ty.has_escaping_regions() || ty.references_error() {
+            span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
+        } else {
+            ty
+        }
+    }
+
+    fn sanitize_lvalue(&mut self, lvalue: &Lvalue<'tcx>) -> LvalueTy<'tcx> {
+        debug!("sanitize_lvalue: {:?}", lvalue);
+        match *lvalue {
+            Lvalue::Var(index) => LvalueTy::Ty { ty: self.mir.var_decls[index as usize].ty },
+            Lvalue::Temp(index) =>
+                LvalueTy::Ty { ty: self.mir.temp_decls[index as usize].ty },
+            Lvalue::Arg(index) =>
+                LvalueTy::Ty { ty: self.mir.arg_decls[index as usize].ty },
+            Lvalue::Static(def_id) =>
+                LvalueTy::Ty { ty: self.tcx().lookup_item_type(def_id).ty },
+            Lvalue::ReturnPointer => {
+                if let ty::FnConverging(return_ty) = self.mir.return_ty {
+                    LvalueTy::Ty { ty: return_ty }
+                } else {
+                    LvalueTy::Ty {
+                        ty: span_mirbug_and_err!(
+                            self, lvalue, "return in diverging function")
+                    }
+                }
+            }
+            Lvalue::Projection(ref proj) => {
+                let base_ty = self.sanitize_lvalue(&proj.base);
+                if let LvalueTy::Ty { ty } = base_ty {
+                    if ty.references_error() {
+                        assert!(self.errors_reported);
+                        return LvalueTy::Ty { ty: self.tcx().types.err };
+                    }
+                }
+                self.sanitize_projection(base_ty, &proj.elem, lvalue)
+            }
+        }
+    }
+
+    fn sanitize_projection(&mut self,
+                           base: LvalueTy<'tcx>,
+                           pi: &LvalueElem<'tcx>,
+                           lvalue: &Lvalue<'tcx>)
+                           -> LvalueTy<'tcx> {
+        debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, lvalue);
+        let tcx = self.tcx();
+        let base_ty = base.to_ty(tcx);
+        let span = self.last_span;
+        match *pi {
+            ProjectionElem::Deref => {
+                let deref_ty = base_ty.builtin_deref(true, ty::LvaluePreference::NoPreference);
+                LvalueTy::Ty {
+                    ty: deref_ty.map(|t| t.ty).unwrap_or_else(|| {
+                        span_mirbug_and_err!(
+                            self, lvalue, "deref of non-pointer {:?}", base_ty)
+                    })
+                }
+            }
+            ProjectionElem::Index(ref i) => {
+                self.visit_operand(i);
+                let index_ty = self.mir.operand_ty(tcx, i);
+                if index_ty != tcx.types.usize {
+                    LvalueTy::Ty {
+                        ty: span_mirbug_and_err!(self, i, "index by non-usize {:?}", i)
+                    }
+                } else {
+                    LvalueTy::Ty {
+                        ty: base_ty.builtin_index().unwrap_or_else(|| {
+                            span_mirbug_and_err!(
+                                self, lvalue, "index of non-array {:?}", base_ty)
+                        })
+                    }
+                }
+            }
+            ProjectionElem::ConstantIndex { .. } => {
+                // consider verifying in-bounds
+                LvalueTy::Ty {
+                    ty: base_ty.builtin_index().unwrap_or_else(|| {
+                        span_mirbug_and_err!(
+                            self, lvalue, "index of non-array {:?}", base_ty)
+                    })
+                }
+            }
+            ProjectionElem::Downcast(adt_def1, index) =>
+                match base_ty.sty {
+                    ty::TyEnum(adt_def, substs) if adt_def == adt_def1 => {
+                        if index >= adt_def.variants.len() {
+                            LvalueTy::Ty {
+                                ty: span_mirbug_and_err!(
+                                    self,
+                                    lvalue,
+                                    "cast to variant #{:?} but enum only has {:?}",
+                                    index,
+                                    adt_def.variants.len())
+                            }
+                        } else {
+                            LvalueTy::Downcast {
+                                adt_def: adt_def,
+                                substs: substs,
+                                variant_index: index
+                            }
+                        }
+                    }
+                    _ => LvalueTy::Ty {
+                        ty: span_mirbug_and_err!(
+                            self, lvalue, "can't downcast {:?} as {:?}",
+                            base_ty, adt_def1)
+                    }
+                },
+            ProjectionElem::Field(field, fty) => {
+                let fty = self.sanitize_type(lvalue, fty);
+                match self.field_ty(lvalue, base, field) {
+                    Ok(ty) => {
+                        if let Err(terr) = self.cx.mk_eqty(span, ty, fty) {
+                            span_mirbug!(
+                                self, lvalue, "bad field access ({:?}: {:?}): {:?}",
+                                ty, fty, terr);
+                        }
+                    }
+                    Err(FieldAccessError::OutOfRange { field_count }) => {
+                        span_mirbug!(
+                            self, lvalue, "accessed field #{} but variant only has {}",
+                            field.index(), field_count)
+                    }
+                }
+                LvalueTy::Ty { ty: fty }
+            }
+        }
+    }
+
+    fn error(&mut self) -> Ty<'tcx> {
+        self.errors_reported = true;
+        self.tcx().types.err
+    }
+
+    fn field_ty(&mut self,
+                parent: &fmt::Debug,
+                base_ty: LvalueTy<'tcx>,
+                field: Field)
+                -> Result<Ty<'tcx>, FieldAccessError>
+    {
+        let tcx = self.tcx();
+
+        let (variant, substs) = match base_ty {
+            LvalueTy::Downcast { adt_def, substs, variant_index } => {
+                (&adt_def.variants[variant_index], substs)
+            }
+            LvalueTy::Ty { ty } => match ty.sty {
+                ty::TyStruct(adt_def, substs) | ty::TyEnum(adt_def, substs)
+                    if adt_def.is_univariant() => {
+                        (&adt_def.variants[0], substs)
+                    }
+                ty::TyTuple(ref tys) | ty::TyClosure(_, box ty::ClosureSubsts {
+                    upvar_tys: ref tys, ..
+                }) => {
+                    return match tys.get(field.index()) {
+                        Some(&ty) => Ok(ty),
+                        None => Err(FieldAccessError::OutOfRange {
+                            field_count: tys.len()
+                        })
+                    }
+                }
+                _ => return Ok(span_mirbug_and_err!(
+                    self, parent, "can't project out of {:?}", base_ty))
+            }
+        };
+
+        if let Some(field) = variant.fields.get(field.index()) {
+            Ok(self.normalize(field.ty(tcx, substs)))
+        } else {
+            Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
+        }
+    }
+
+    fn normalize(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        let infcx = self.infcx();
+        let mut selcx = traits::SelectionContext::new(infcx);
+        let cause = traits::ObligationCause::misc(self.last_span, 0);
+        let traits::Normalized { value: ty, obligations } =
+            traits::normalize(&mut selcx, cause, &ty);
+
+        debug!("normalize: ty={:?} obligations={:?}",
+               ty,
+               obligations);
+
+        let mut fulfill_cx = &mut self.cx.fulfillment_cx;
+        for obligation in obligations {
+            fulfill_cx.register_predicate_obligation(infcx, obligation);
+        }
+
+        ty
+    }
+}
+
+pub struct TypeChecker<'a, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    fulfillment_cx: traits::FulfillmentContext<'tcx>,
+    last_span: Span
+}
+
+impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
+    fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+        TypeChecker {
+            infcx: infcx,
+            fulfillment_cx: traits::FulfillmentContext::new(),
+            last_span: DUMMY_SP
+        }
+    }
+
+    fn mk_subty(&self, span: Span, sup: Ty<'tcx>, sub: Ty<'tcx>)
+                -> infer::UnitResult<'tcx>
+    {
+        infer::mk_subty(self.infcx, false, infer::TypeOrigin::Misc(span),
+                        sup, sub)
+    }
+
+    fn mk_eqty(&self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>)
+                -> infer::UnitResult<'tcx>
+    {
+        infer::mk_eqty(self.infcx, false, infer::TypeOrigin::Misc(span),
+                       a, b)
+    }
+
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn check_stmt(&mut self, mir: &Mir<'tcx>, stmt: &Statement<'tcx>) {
+        debug!("check_stmt: {:?}", stmt);
+        let tcx = self.tcx();
+        match stmt.kind {
+            StatementKind::Assign(ref lv, ref rv) => {
+                let lv_ty = mir.lvalue_ty(tcx, lv).to_ty(tcx);
+                let rv_ty = mir.rvalue_ty(tcx, rv);
+                if let Some(rv_ty) = rv_ty {
+                    if let Err(terr) = self.mk_subty(self.last_span, rv_ty, lv_ty) {
+                        span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}",
+                                     lv_ty, rv_ty, terr);
+                    }
+                }
+
+                // FIXME: rvalue with undeterminable type - e.g. inline
+                // asm.
+            }
+        }
+    }
+
+    fn check_terminator(&self,
+                        mir: &Mir<'tcx>,
+                        term: &Terminator<'tcx>) {
+        debug!("check_terminator: {:?}", term);
+        let tcx = self.tcx();
+        match *term {
+            Terminator::Goto { .. } |
+            Terminator::Resume |
+            Terminator::Return |
+            Terminator::Drop { .. } => {
+                // no checks needed for these
+            }
+
+            Terminator::If { ref cond, .. } => {
+                let cond_ty = mir.operand_ty(tcx, cond);
+                match cond_ty.sty {
+                    ty::TyBool => {}
+                    _ => {
+                        span_mirbug!(self, term, "bad If ({:?}, not bool", cond_ty);
+                    }
+                }
+            }
+            Terminator::SwitchInt { ref discr, switch_ty, .. } => {
+                let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
+                if let Err(terr) = self.mk_subty(self.last_span, discr_ty, switch_ty) {
+                    span_mirbug!(self, term, "bad SwitchInt ({:?} on {:?}): {:?}",
+                                 switch_ty, discr_ty, terr);
+                }
+                if !switch_ty.is_integral() && !switch_ty.is_char() &&
+                    !switch_ty.is_bool()
+                {
+                    span_mirbug!(self, term, "bad SwitchInt discr ty {:?}",switch_ty);
+                }
+                // FIXME: check the values
+            }
+            Terminator::Switch { ref discr, adt_def, ref targets } => {
+                let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
+                match discr_ty.sty {
+                    ty::TyEnum(def, _)
+                        if def == adt_def && adt_def.variants.len() == targets.len()
+                        => {},
+                    _ => {
+                        span_mirbug!(self, term, "bad Switch ({:?} on {:?})",
+                                     adt_def, discr_ty);
+                    }
+                }
+            }
+            Terminator::Call { ref func, ref args, ref destination, .. } => {
+                let func_ty = mir.operand_ty(tcx, func);
+                debug!("check_terminator: call, func_ty={:?}", func_ty);
+                let func_ty = match func_ty.sty {
+                    ty::TyBareFn(_, func_ty) => func_ty,
+                    _ => {
+                        span_mirbug!(self, term, "call to non-function {:?}", func_ty);
+                        return;
+                    }
+                };
+                let sig = tcx.erase_late_bound_regions(&func_ty.sig);
+                self.check_call_dest(mir, term, &sig, destination);
+
+                if self.is_box_free(func) {
+                    self.check_box_free_inputs(mir, term, &sig, args);
+                } else {
+                    self.check_call_inputs(mir, term, &sig, args);
+                }
+            }
+        }
+    }
+
+    fn check_call_dest(&self,
+                       mir: &Mir<'tcx>,
+                       term: &Terminator<'tcx>,
+                       sig: &ty::FnSig<'tcx>,
+                       destination: &Option<(Lvalue<'tcx>, BasicBlock)>) {
+        let tcx = self.tcx();
+        match (destination, sig.output) {
+            (&Some(..), ty::FnDiverging) => {
+                span_mirbug!(self, term, "call to diverging function {:?} with dest", sig);
+            }
+            (&Some((ref dest, _)), ty::FnConverging(ty)) => {
+                let dest_ty = mir.lvalue_ty(tcx, dest).to_ty(tcx);
+                if let Err(terr) = self.mk_subty(self.last_span, ty, dest_ty) {
+                    span_mirbug!(self, term,
+                                 "call dest mismatch ({:?} <- {:?}): {:?}",
+                                 dest_ty, ty, terr);
+                }
+            }
+            (&None, ty::FnDiverging) => {}
+            (&None, ty::FnConverging(..)) => {
+                span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
+             }
+        }
+    }
+
+    fn check_call_inputs(&self,
+                         mir: &Mir<'tcx>,
+                         term: &Terminator<'tcx>,
+                         sig: &ty::FnSig<'tcx>,
+                         args: &[Operand<'tcx>])
+    {
+        debug!("check_call_inputs({:?}, {:?})", sig, args);
+        if args.len() < sig.inputs.len() ||
+           (args.len() > sig.inputs.len() && !sig.variadic) {
+            span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
+        }
+        for (n, (fn_arg, op_arg)) in sig.inputs.iter().zip(args).enumerate() {
+            let op_arg_ty = mir.operand_ty(self.tcx(), op_arg);
+            if let Err(terr) = self.mk_subty(self.last_span, op_arg_ty, fn_arg) {
+                span_mirbug!(self, term, "bad arg #{:?} ({:?} <- {:?}): {:?}",
+                             n, fn_arg, op_arg_ty, terr);
+            }
+        }
+    }
+
+    fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
+        match operand {
+            &Operand::Constant(Constant {
+                literal: Literal::Item { def_id, .. }, ..
+            }) => {
+                Some(def_id) == self.tcx().lang_items.box_free_fn()
+            }
+            _ => false,
+        }
+    }
+
+    fn check_box_free_inputs(&self,
+                             mir: &Mir<'tcx>,
+                             term: &Terminator<'tcx>,
+                             sig: &ty::FnSig<'tcx>,
+                             args: &[Operand<'tcx>])
+    {
+        debug!("check_box_free_inputs");
+
+        // box_free takes a Box as a pointer. Allow for that.
+
+        if sig.inputs.len() != 1 {
+            span_mirbug!(self, term, "box_free should take 1 argument");
+            return;
+        }
+
+        let pointee_ty = match sig.inputs[0].sty {
+            ty::TyRawPtr(mt) => mt.ty,
+            _ => {
+                span_mirbug!(self, term, "box_free should take a raw ptr");
+                return;
+            }
+        };
+
+        if args.len() != 1 {
+            span_mirbug!(self, term, "box_free called with wrong # of args");
+            return;
+        }
+
+        let arg_ty = match mir.operand_ty(self.tcx(), &args[0]).sty {
+            ty::TyRawPtr(mt) => mt.ty,
+            ty::TyBox(ty) => ty,
+            _ => {
+                span_mirbug!(self, term, "box_free called with bad arg ty");
+                return;
+            }
+        };
+
+        if let Err(terr) = self.mk_subty(self.last_span, arg_ty, pointee_ty) {
+            span_mirbug!(self, term, "bad box_free arg ({:?} <- {:?}): {:?}",
+                         pointee_ty, arg_ty, terr);
+        }
+    }
+
+    fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
+        self.last_span = mir.span;
+        debug!("run_on_mir: {:?}", mir.span);
+        for block in &mir.basic_blocks {
+            for stmt in &block.statements {
+                if stmt.span != DUMMY_SP {
+                    self.last_span = stmt.span;
+                }
+                self.check_stmt(mir, stmt);
+            }
+
+            if let Some(ref terminator) = block.terminator {
+                self.check_terminator(mir, terminator);
+            }
+        }
+    }
+
+    fn verify_obligations(&mut self, mir: &Mir<'tcx>) {
+        self.last_span = mir.span;
+        if let Err(e) = self.fulfillment_cx.select_all_or_error(self.infcx) {
+            span_mirbug!(self, "", "errors selecting obligation: {:?}",
+                         e);
+        }
+    }
+}
+
+pub struct TypeckMir;
+
+impl TypeckMir {
+    pub fn new() -> Self {
+        TypeckMir
+    }
+}
+
+impl MirPass for TypeckMir {
+    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, infcx: &InferCtxt<'a, 'tcx>)
+    {
+        if infcx.tcx.sess.err_count() > 0 {
+            // compiling a broken program can obviously result in a
+            // broken MIR, so try not to report duplicate errors.
+            return;
+        }
+
+        let mut checker = TypeChecker::new(infcx);
+
+        {
+            let mut verifier = TypeVerifier::new(&mut checker, mir);
+            verifier.visit_mir(mir);
+            if verifier.errors_reported {
+                // don't do further checks to avoid ICEs
+                return;
+            }
+        }
+
+        checker.typeck_mir(mir);
+        checker.verify_obligations(mir);
+    }
+}
diff --git a/src/librustc_mir/transform/util.rs b/src/librustc_mir/transform/util.rs
deleted file mode 100644
index 7e44beb18a2..00000000000
--- a/src/librustc_mir/transform/util.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::mir::repr::*;
-
-/// Update basic block ids in all terminators using the given replacements,
-/// useful e.g. after removal of several basic blocks to update all terminators
-/// in a single pass
-pub fn update_basic_block_ids(mir: &mut Mir, replacements: &[BasicBlock]) {
-    for bb in mir.all_basic_blocks() {
-        for target in mir.basic_block_data_mut(bb).terminator_mut().successors_mut() {
-            *target = replacements[target.index()];
-        }
-    }
-}
-
-/// Mass removal of basic blocks to keep the ID-remapping cheap.
-pub fn retain_basic_blocks(mir: &mut Mir, keep: &[bool]) {
-    let num_blocks = mir.basic_blocks.len();
-
-    // Check that we have a usage flag for every block
-    assert_eq!(num_blocks, keep.len());
-
-    let first_dead = match keep.iter().position(|&k| !k) {
-        None => return,
-        Some(first_dead) => first_dead,
-    };
-
-    // `replacements` maps the old block ids to the new ones
-    let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect();
-
-    let mut dead = 0;
-    for i in first_dead..num_blocks {
-        if keep[i] {
-            replacements[i] = BasicBlock::new(i - dead);
-            mir.basic_blocks.swap(i, i - dead);
-        } else {
-            dead += 1;
-        }
-    }
-    mir.basic_blocks.truncate(num_blocks - dead);
-
-    update_basic_block_ids(mir, &replacements);
-}
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index c3699735ae8..b0d459063ef 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -41,7 +41,7 @@ use rustc::util::nodemap::NodeMap;
 use rustc::middle::const_qualif::ConstQualif;
 use rustc::lint::builtin::CONST_ERR;
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::feature_gate::UnstableFeatures;
@@ -322,10 +322,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
 
     fn visit_pat(&mut self, p: &hir::Pat) {
         match p.node {
-            hir::PatLit(ref lit) => {
+            PatKind::Lit(ref lit) => {
                 self.global_expr(Mode::Const, &lit);
             }
-            hir::PatRange(ref start, ref end) => {
+            PatKind::Range(ref start, ref end) => {
                 self.global_expr(Mode::Const, &start);
                 self.global_expr(Mode::Const, &end);
 
@@ -768,7 +768,8 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
     match v.tcx.tables.borrow().adjustments.get(&e.id) {
         None |
         Some(&ty::adjustment::AdjustReifyFnPointer) |
-        Some(&ty::adjustment::AdjustUnsafeFnPointer) => {}
+        Some(&ty::adjustment::AdjustUnsafeFnPointer) |
+        Some(&ty::adjustment::AdjustMutToConstPointer) => {}
 
         Some(&ty::adjustment::AdjustDerefRef(
             ty::adjustment::AutoDerefRef { autoderefs, .. }
diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml
index 59cfe158624..0b88f313047 100644
--- a/src/librustc_plugin/Cargo.toml
+++ b/src/librustc_plugin/Cargo.toml
@@ -11,6 +11,7 @@ crate-type = ["dylib"]
 [dependencies]
 log = { path = "../liblog" }
 rustc = { path = "../librustc" }
+rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_front = { path = "../librustc_front" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
diff --git a/src/librustc_privacy/diagnostics.rs b/src/librustc_privacy/diagnostics.rs
index d124ead5091..1b49409970d 100644
--- a/src/librustc_privacy/diagnostics.rs
+++ b/src/librustc_privacy/diagnostics.rs
@@ -27,8 +27,8 @@ pub fn foo<T: Foo> (t: T) {} // same error
 ```
 
 To solve this error, please ensure that the trait is also public. The trait
-can be made inaccessible if necessary by placing it into a private inner module,
-but it still has to be marked with `pub`. Example:
+can be made inaccessible if necessary by placing it into a private inner
+module, but it still has to be marked with `pub`. Example:
 
 ```ignore
 pub trait Foo { // we set the Foo trait public
@@ -55,8 +55,8 @@ mod Foo {
 ```
 
 To solve this error, please ensure that the type is also public. The type
-can be made inaccessible if necessary by placing it into a private inner module,
-but it still has to be marked with `pub`.
+can be made inaccessible if necessary by placing it into a private inner
+module, but it still has to be marked with `pub`.
 Example:
 
 ```
@@ -165,7 +165,7 @@ let f = Bar::Foo(0); // error: cannot invoke tuple struct constructor with
 ```
 
 To solve this issue, please ensure that all of the fields of the tuple struct
-are public. Alternatively, provide a new() method to the tuple struct to
+are public. Alternatively, provide a `new()` method to the tuple struct to
 construct it from a given inner value. Example:
 
 ```
@@ -205,8 +205,8 @@ let f = Bar::Foo{ a: 0, b: 0 }; // error: field `b` of struct `Bar::Foo`
                                 //        is private
 ```
 
-To fix this error, please ensure that all the fields of the struct, or
-implement a function for easy instantiation. Examples:
+To fix this error, please ensure that all the fields of the struct are public,
+or implement a function for easy instantiation. Examples:
 
 ```
 mod Bar {
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 85c2fe0c0a5..8908dac7a36 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -33,7 +33,7 @@ use self::FieldName::*;
 use std::cmp;
 use std::mem::replace;
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::intravisit::{self, Visitor};
 
 use rustc::dep_graph::DepNode;
@@ -169,6 +169,10 @@ struct EmbargoVisitor<'a, 'tcx: 'a> {
     changed: bool,
 }
 
+struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
+    ev: &'b mut EmbargoVisitor<'a, 'tcx>,
+}
+
 impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
     fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
         if let hir::TyPath(..) = ty.node {
@@ -214,6 +218,10 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
             old_level
         }
     }
+
+    fn reach<'b>(&'b mut self) -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
+        ReachEverythingInTheInterfaceVisitor { ev: self }
+    }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
@@ -245,10 +253,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             }
         };
 
-        // Update id of the item itself
+        // Update level of the item itself
         let item_level = self.update(item.id, inherited_item_level);
 
-        // Update ids of nested things
+        // Update levels of nested things
         match item.node {
             hir::ItemEnum(ref def, _) => {
                 for variant in &def.variants {
@@ -292,19 +300,72 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
                     }
                 }
             }
-            hir::ItemTy(ref ty, _) if item_level.is_some() => {
-                if let hir::TyPath(..) = ty.node {
-                    match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
-                        Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {},
-                        def => {
-                            if let Some(node_id) = self.tcx.map.as_local_node_id(def.def_id()) {
-                                self.update(node_id, Some(AccessLevel::Reachable));
-                            }
+            _ => {}
+        }
+
+        // Mark all items in interfaces of reachable items as reachable
+        match item.node {
+            // The interface is empty
+            hir::ItemExternCrate(..) => {}
+            // All nested items are checked by visit_item
+            hir::ItemMod(..) => {}
+            // Reexports are handled in visit_mod
+            hir::ItemUse(..) => {}
+            // Visit everything
+            hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
+            hir::ItemTrait(..) | hir::ItemTy(..) | hir::ItemImpl(_, _, _, Some(..), _, _) => {
+                if item_level.is_some() {
+                    self.reach().visit_item(item);
+                }
+            }
+            // Visit everything, but enum variants have their own levels
+            hir::ItemEnum(ref def, ref generics) => {
+                if item_level.is_some() {
+                    self.reach().visit_generics(generics);
+                }
+                for variant in &def.variants {
+                    if self.get(variant.node.data.id()).is_some() {
+                        for field in variant.node.data.fields() {
+                            self.reach().visit_struct_field(field);
+                        }
+                        // Corner case: if the variant is reachable, but its
+                        // enum is not, make the enum reachable as well.
+                        self.update(item.id, Some(AccessLevel::Reachable));
+                    }
+                }
+            }
+            // Visit everything, but foreign items have their own levels
+            hir::ItemForeignMod(ref foreign_mod) => {
+                for foreign_item in &foreign_mod.items {
+                    if self.get(foreign_item.id).is_some() {
+                        self.reach().visit_foreign_item(foreign_item);
+                    }
+                }
+            }
+            // Visit everything except for private fields
+            hir::ItemStruct(ref struct_def, ref generics) => {
+                if item_level.is_some() {
+                    self.reach().visit_generics(generics);
+                    for field in struct_def.fields() {
+                        if self.get(field.node.id).is_some() {
+                            self.reach().visit_struct_field(field);
+                        }
+                    }
+                }
+            }
+            // The interface is empty
+            hir::ItemDefaultImpl(..) => {}
+            // Visit everything except for private impl items
+            hir::ItemImpl(_, _, ref generics, None, _, ref impl_items) => {
+                if item_level.is_some() {
+                    self.reach().visit_generics(generics);
+                    for impl_item in impl_items {
+                        if self.get(impl_item.id).is_some() {
+                            self.reach().visit_impl_item(impl_item);
                         }
                     }
                 }
             }
-            _ => {}
         }
 
         let orig_level = self.prev_level;
@@ -347,6 +408,68 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
     }
 }
 
+impl<'b, 'a, 'tcx: 'a> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
+    // Make the type hidden under a type alias reachable
+    fn reach_aliased_type(&mut self, item: &hir::Item, path: &hir::Path) {
+        if let hir::ItemTy(ref ty, ref generics) = item.node {
+            // See `fn is_public_type_alias` for details
+            self.visit_ty(ty);
+            let provided_params = path.segments.last().unwrap().parameters.types().len();
+            for ty_param in &generics.ty_params[provided_params..] {
+                if let Some(ref default_ty) = ty_param.default {
+                    self.visit_ty(default_ty);
+                }
+            }
+        }
+    }
+}
+
+impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
+    fn visit_ty(&mut self, ty: &hir::Ty) {
+        if let hir::TyPath(_, ref path) = ty.node {
+            let def = self.ev.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
+            match def {
+                Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) |
+                Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => {
+                    if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) {
+                        let item = self.ev.tcx.map.expect_item(node_id);
+                        if let Def::TyAlias(..) = def {
+                            // Type aliases are substituted. Associated type aliases are not
+                            // substituted yet, but ideally they should be.
+                            if self.ev.get(item.id).is_none() {
+                                self.reach_aliased_type(item, path);
+                            }
+                        } else {
+                            self.ev.update(item.id, Some(AccessLevel::Reachable));
+                        }
+                    }
+                }
+
+                _ => {}
+            }
+        }
+
+        intravisit::walk_ty(self, ty);
+    }
+
+    fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
+        let def_id = self.ev.tcx.trait_ref_to_def_id(trait_ref);
+        if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) {
+            let item = self.ev.tcx.map.expect_item(node_id);
+            self.ev.update(item.id, Some(AccessLevel::Reachable));
+        }
+
+        intravisit::walk_trait_ref(self, trait_ref);
+    }
+
+    // Don't recurse into function bodies
+    fn visit_block(&mut self, _: &hir::Block) {}
+    // Don't recurse into expressions in array sizes or const initializers
+    fn visit_expr(&mut self, _: &hir::Expr) {}
+    // Don't recurse into patterns in function arguments
+    fn visit_pat(&mut self, _: &hir::Pat) {}
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 /// The privacy visitor, where privacy checks take place (violations reported)
 ////////////////////////////////////////////////////////////////////////////////
@@ -620,6 +743,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                      source_did: Option<DefId>,
                      msg: &str)
                      -> CheckResult {
+        use rustc_front::hir::Item_::ItemExternCrate;
         debug!("ensure_public(span={:?}, to_check={:?}, source_did={:?}, msg={:?})",
                span, to_check, source_did, msg);
         let def_privacy = self.def_privacy(to_check);
@@ -640,6 +764,21 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
         // be local.)
         let def_id = source_did.unwrap_or(to_check);
         let node_id = self.tcx.map.as_local_node_id(def_id);
+
+        // Warn when using a inaccessible extern crate.
+        if let Some(node_id) = self.tcx.map.as_local_node_id(to_check) {
+            match self.tcx.map.get(node_id) {
+                ast_map::Node::NodeItem(&hir::Item { node: ItemExternCrate(_), name, .. }) => {
+                    self.tcx.sess.add_lint(lint::builtin::INACCESSIBLE_EXTERN_CRATE,
+                                           node_id,
+                                           span,
+                                           format!("extern crate `{}` is private", name));
+                    return None;
+                }
+                _ => {}
+            }
+        }
+
         let (err_span, err_msg) = if Some(id) == node_id {
             return Some((span, format!("{} is private", msg), None));
         } else {
@@ -710,7 +849,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             NamedField(name) => format!("field `{}` of {} is private",
                                         name, struct_desc),
             UnnamedField(idx) => format!("field #{} of {} is private",
-                                         idx + 1, struct_desc),
+                                         idx, struct_desc),
         };
         span_err!(self.tcx.sess, span, E0451,
                   "{}", &msg[..]);
@@ -920,7 +1059,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
         if self.in_foreign { return }
 
         match pattern.node {
-            hir::PatStruct(_, ref fields, _) => {
+            PatKind::Struct(_, ref fields, _) => {
                 let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap();
                 let def = self.tcx.def_map.borrow().get(&pattern.id).unwrap().full_def();
                 let variant = adt.variant_of_def(def);
@@ -932,11 +1071,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
 
             // Patterns which bind no fields are allowable (the path is check
             // elsewhere).
-            hir::PatEnum(_, Some(ref fields)) => {
+            PatKind::TupleStruct(_, Some(ref fields)) => {
                 match self.tcx.pat_ty(pattern).sty {
                     ty::TyStruct(def, _) => {
                         for (i, field) in fields.iter().enumerate() {
-                            if let hir::PatWild = field.node {
+                            if let PatKind::Wild = field.node {
                                 continue
                             }
                             self.check_field(field.span,
diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml
index da01a36d762..82e952d2bee 100644
--- a/src/librustc_resolve/Cargo.toml
+++ b/src/librustc_resolve/Cargo.toml
@@ -12,5 +12,6 @@ crate-type = ["dylib"]
 log = { path = "../liblog" }
 syntax = { path = "../libsyntax" }
 rustc = { path = "../librustc" }
+rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_front = { path = "../librustc_front" }
 arena = { path = "../libarena" }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 5c94c6e4369..385fae46cba 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -19,7 +19,7 @@ use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
 use Module;
 use Namespace::{self, TypeNS, ValueNS};
 use {NameBinding, NameBindingKind};
-use {names_to_string, module_to_string};
+use module_to_string;
 use ParentLink::{ModuleParentLink, BlockParentLink};
 use Resolver;
 use resolve_imports::Shadowable;
@@ -293,9 +293,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                     self.external_exports.insert(def_id);
                     let parent_link = ModuleParentLink(parent, name);
                     let def = Def::Mod(def_id);
-                    let external_module = self.new_extern_crate_module(parent_link, def);
+                    let local_def_id = self.ast_map.local_def_id(item.id);
+                    let external_module =
+                        self.new_extern_crate_module(parent_link, def, is_public, local_def_id);
                     self.define(parent, name, TypeNS, (external_module, sp));
 
+                    if is_public {
+                        let export = Export { name: name, def_id: def_id };
+                        if let Some(def_id) = parent.def_id() {
+                            let node_id = self.resolver.ast_map.as_local_node_id(def_id).unwrap();
+                            self.export_map.entry(node_id).or_insert(Vec::new()).push(export);
+                        }
+                    }
+
                     self.build_reduced_graph_for_external_crate(external_module);
                 }
                 parent
@@ -682,7 +692,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                               id: NodeId,
                               is_public: bool,
                               shadowable: Shadowable) {
-        module_.imports
+        module_.unresolved_imports
                .borrow_mut()
                .push(ImportDirective::new(module_path, subclass, span, id, is_public, shadowable));
         self.unresolved_imports += 1;
@@ -696,9 +706,6 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
 
         match subclass {
             SingleImport(target, _) => {
-                debug!("(building import directive) building import directive: {}::{}",
-                       names_to_string(&module_.imports.borrow().last().unwrap().module_path),
-                       target);
                 module_.increment_outstanding_references_for(target, ValueNS);
                 module_.increment_outstanding_references_for(target, TypeNS);
             }
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index 99c29bbb8ef..bfd8a6f1f61 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -94,8 +94,8 @@ mod bar {
 "##,
 
 E0253: r##"
-Attempt was made to import an unimportable value. This can happen when
-trying to import a method from a trait. An example of this error:
+Attempt was made to import an unimportable value. This can happen when trying
+to import a method from a trait. An example of this error:
 
 ```compile_fail
 mod foo {
@@ -149,10 +149,10 @@ fn main() {}
 "##,
 
 E0259: r##"
-The name chosen for an external crate conflicts with another external crate that
-has been imported into the current module.
+The name chosen for an external crate conflicts with another external crate
+that has been imported into the current module.
 
-Wrong example:
+Erroneous code example:
 
 ```compile_fail
 extern crate a;
@@ -251,8 +251,8 @@ https://doc.rust-lang.org/reference.html#types
 "##,
 
 E0364: r##"
-Private items cannot be publicly re-exported.  This error indicates that
-you attempted to `pub use` a type or value that was not itself public.
+Private items cannot be publicly re-exported.  This error indicates that you
+attempted to `pub use` a type or value that was not itself public.
 
 Here is an example that demonstrates the error:
 
@@ -275,15 +275,15 @@ mod foo {
 pub use foo::X;
 ```
 
-See the 'Use Declarations' section of the reference for more information
-on this topic:
+See the 'Use Declarations' section of the reference for more information on
+this topic:
 
 https://doc.rust-lang.org/reference.html#use-declarations
 "##,
 
 E0365: r##"
-Private modules cannot be publicly re-exported.  This error indicates
-that you attempted to `pub use` a module that was not itself public.
+Private modules cannot be publicly re-exported. This error indicates that you
+attempted to `pub use` a module that was not itself public.
 
 Here is an example that demonstrates the error:
 
@@ -313,8 +313,8 @@ https://doc.rust-lang.org/reference.html#use-declarations
 "##,
 
 E0401: r##"
-Inner items do not inherit type parameters from the functions they are
-embedded in. For example, this will not compile:
+Inner items do not inherit type parameters from the functions they are embedded
+in. For example, this will not compile:
 
 ```compile_fail
 fn foo<T>(x: T) {
@@ -461,12 +461,12 @@ impl Foo for Bar { // ok!
 "##,
 
 E0405: r##"
-An unknown trait was implemented. Example of erroneous code:
+The code refers to a trait that is not in scope. Example of erroneous code:
 
 ```compile_fail
 struct Foo;
 
-impl SomeTrait for Foo {} // error: use of undeclared trait name `SomeTrait`
+impl SomeTrait for Foo {} // error: trait `SomeTrait` is not in scope
 ```
 
 Please verify that the name of the trait wasn't misspelled and ensure that it
@@ -543,16 +543,15 @@ impl Bar {
 "##,
 
 E0411: r##"
-The `Self` keyword was used outside an impl or a trait. Erroneous
-code example:
+The `Self` keyword was used outside an impl or a trait. Erroneous code example:
 
 ```compile_fail
 <Self>::foo; // error: use of `Self` outside of an impl or trait
 ```
 
-The `Self` keyword represents the current type, which explains why it
-can only be used inside an impl or a trait. It gives access to the
-associated items of a type:
+The `Self` keyword represents the current type, which explains why it can only
+be used inside an impl or a trait. It gives access to the associated items of a
+type:
 
 ```
 trait Foo {
@@ -564,7 +563,7 @@ trait Baz : Foo {
 }
 ```
 
-However, be careful when two types has a common associated type:
+However, be careful when two types have a common associated type:
 
 ```compile_fail
 trait Foo {
@@ -581,8 +580,8 @@ trait Baz : Foo + Foo2 {
 }
 ```
 
-This problem can be solved by specifying from which trait we want
-to use the `Bar` type:
+This problem can be solved by specifying from which trait we want to use the
+`Bar` type:
 
 ```
 trait Foo {
@@ -600,20 +599,24 @@ trait Baz : Foo + Foo2 {
 "##,
 
 E0412: r##"
-An undeclared type name was used. Example of erroneous codes:
+The type name used is not in scope. Example of erroneous codes:
 
 ```compile_fail
-impl Something {} // error: use of undeclared type name `Something`
+impl Something {} // error: type name `Something` is not in scope
+
 // or:
+
 trait Foo {
-    fn bar(N); // error: use of undeclared type name `N`
+    fn bar(N); // error: type name `N` is not in scope
 }
+
 // or:
-fn foo(x: T) {} // error: use of undeclared type name `T`
+
+fn foo(x: T) {} // type name `T` is not in scope
 ```
 
-To fix this error, please verify you didn't misspell the type name,
-you did declare it or imported it into the scope. Examples:
+To fix this error, please verify you didn't misspell the type name, you did
+declare it or imported it into the scope. Examples:
 
 ```
 struct Something;
@@ -635,8 +638,8 @@ fn foo<T>(x: T) {} // ok!
 "##,
 
 E0413: r##"
-A declaration shadows an enum variant or unit-like struct in scope.
-Example of erroneous code:
+A declaration shadows an enum variant or unit-like struct in scope. Example of
+erroneous code:
 
 ```compile_fail
 struct Foo;
@@ -666,8 +669,7 @@ The goal here is to avoid a conflict of names.
 "##,
 
 E0415: r##"
-More than one function parameter have the same name. Example of erroneous
-code:
+More than one function parameter have the same name. Example of erroneous code:
 
 ```compile_fail
 fn foo(f: i32, f: i32) {} // error: identifier `f` is bound more than
@@ -682,8 +684,7 @@ fn foo(f: i32, g: i32) {} // ok!
 "##,
 
 E0416: r##"
-An identifier is bound more than once in a pattern. Example of erroneous
-code:
+An identifier is bound more than once in a pattern. Example of erroneous code:
 
 ```compile_fail
 match (1, 2) {
@@ -739,8 +740,7 @@ match 0 {
 "##,
 
 E0419: r##"
-An unknown enum variant, struct or const was used. Example of
-erroneous code:
+An unknown enum variant, struct or const was used. Example of erroneous code:
 
 ```compile_fail
 match 0 {
@@ -766,8 +766,8 @@ match Something::NotFoo {
 "##,
 
 E0422: r##"
-You are trying to use an identifier that is either undefined or not a
-struct. For instance:
+You are trying to use an identifier that is either undefined or not a struct.
+For instance:
 
 ``` compile_fail
 fn main () {
@@ -785,13 +785,13 @@ fn main () {
 }
 ```
 
-In this case, `foo` is defined, but is not a struct, so Rust can't use
-it as one.
+In this case, `foo` is defined, but is not a struct, so Rust can't use it as
+one.
 "##,
 
 E0423: r##"
-A `struct` variant name was used like a function name. Example of
-erroneous code:
+A `struct` variant name was used like a function name. Example of erroneous
+code:
 
 ```compile_fail
 struct Foo { a: bool};
@@ -801,8 +801,8 @@ let f = Foo();
 //        it like a function name
 ```
 
-Please verify you didn't misspell the name of what you actually wanted
-to use here. Example:
+Please verify you didn't misspell the name of what you actually wanted to use
+here. Example:
 
 ```
 fn Foo() -> u32 { 0 }
@@ -851,6 +851,7 @@ something_that_doesnt_exist::foo;
 // error: unresolved name `something_that_doesnt_exist::foo`
 
 // or:
+
 trait Foo {
     fn bar() {
         Self; // error: unresolved name `Self`
@@ -858,6 +859,7 @@ trait Foo {
 }
 
 // or:
+
 let x = unknown_variable;  // error: unresolved name `unknown_variable`
 ```
 
@@ -941,7 +943,7 @@ use something::self; // ok!
 "##,
 
 E0431: r##"
-`self` import was made. Erroneous code example:
+An invalid `self` import was made. Erroneous code example:
 
 ```compile_fail
 use {self}; // error: `self` import can only appear in an import list with a
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 3244d2f1d96..067d83a17e5 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -18,7 +18,6 @@
 #![cfg_attr(not(stage0), deny(warnings))]
 
 #![feature(associated_consts)]
-#![feature(borrow_state)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
@@ -80,8 +79,9 @@ use rustc_front::hir::{ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
 use rustc_front::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
 use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
 use rustc_front::hir::Local;
-use rustc_front::hir::{Pat, PatEnum, PatIdent, PatLit, PatQPath};
-use rustc_front::hir::{PatRange, PatStruct, Path, PrimTy};
+use rustc_front::hir::{Pat, PatKind, Path, PrimTy};
+use rustc_front::hir::{PathSegment, PathParameters};
+use rustc_front::hir::HirVec;
 use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
 use rustc_front::hir::{TyRptr, TyStr, TyUint, TyPath, TyPtr};
 use rustc_front::util::walk_pat;
@@ -118,6 +118,12 @@ enum SuggestionType {
     NotFound,
 }
 
+/// Candidates for a name resolution failure
+pub struct SuggestedCandidates {
+    name: String,
+    candidates: Vec<Path>,
+}
+
 pub enum ResolutionError<'a> {
     /// error E0401: can't use type parameters from outer function
     TypeParametersFromOuterFunction,
@@ -128,7 +134,7 @@ pub enum ResolutionError<'a> {
     /// error E0404: is not a trait
     IsNotATrait(&'a str),
     /// error E0405: use of undeclared trait name
-    UndeclaredTraitName(&'a str),
+    UndeclaredTraitName(&'a str, SuggestedCandidates),
     /// error E0406: undeclared associated type
     UndeclaredAssociatedType,
     /// error E0407: method is not a member of trait
@@ -146,7 +152,7 @@ pub enum ResolutionError<'a> {
     /// error E0411: use of `Self` outside of an impl or trait
     SelfUsedOutsideImplOrTrait,
     /// error E0412: use of undeclared
-    UseOfUndeclared(&'a str, &'a str),
+    UseOfUndeclared(&'a str, &'a str, SuggestedCandidates),
     /// error E0413: declaration shadows an enum variant or unit-like struct in scope
     DeclarationShadowsEnumVariantOrUnitLikeStruct(Name),
     /// error E0414: only irrefutable patterns allowed here
@@ -249,12 +255,14 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
         ResolutionError::IsNotATrait(name) => {
             struct_span_err!(resolver.session, span, E0404, "`{}` is not a trait", name)
         }
-        ResolutionError::UndeclaredTraitName(name) => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0405,
-                             "use of undeclared trait name `{}`",
-                             name)
+        ResolutionError::UndeclaredTraitName(name, candidates) => {
+            let mut err = struct_span_err!(resolver.session,
+                                           span,
+                                           E0405,
+                                           "trait `{}` is not in scope",
+                                           name);
+            show_candidates(&mut err, span, &candidates);
+            err
         }
         ResolutionError::UndeclaredAssociatedType => {
             struct_span_err!(resolver.session, span, E0406, "undeclared associated type")
@@ -314,13 +322,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
                              E0411,
                              "use of `Self` outside of an impl or trait")
         }
-        ResolutionError::UseOfUndeclared(kind, name) => {
-            struct_span_err!(resolver.session,
-                             span,
-                             E0412,
-                             "use of undeclared {} `{}`",
-                             kind,
-                             name)
+        ResolutionError::UseOfUndeclared(kind, name, candidates) => {
+            let mut err = struct_span_err!(resolver.session,
+                                           span,
+                                           E0412,
+                                           "{} `{}` is undefined or not in scope",
+                                           kind,
+                                           name);
+            show_candidates(&mut err, span, &candidates);
+            err
         }
         ResolutionError::DeclarationShadowsEnumVariantOrUnitLikeStruct(name) => {
             struct_span_err!(resolver.session,
@@ -721,8 +731,8 @@ enum RibKind<'a> {
     // We're in a constant item. Can't refer to dynamic stuff.
     ConstantItemRibKind,
 
-    // We passed through an anonymous module.
-    AnonymousModuleRibKind(Module<'a>),
+    // We passed through a module.
+    ModuleRibKind(Module<'a>),
 }
 
 #[derive(Copy, Clone)]
@@ -796,10 +806,13 @@ pub struct ModuleS<'a> {
     parent_link: ParentLink<'a>,
     def: Option<Def>,
     is_public: bool,
-    is_extern_crate: bool,
+
+    // If the module is an extern crate, `def` is root of the external crate and `extern_crate_did`
+    // is the DefId of the local `extern crate` item (otherwise, `extern_crate_did` is None).
+    extern_crate_did: Option<DefId>,
 
     resolutions: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
-    imports: RefCell<Vec<ImportDirective>>,
+    unresolved_imports: RefCell<Vec<ImportDirective>>,
 
     // The module children of this node, including normal modules and anonymous modules.
     // Anonymous children are pseudo-modules that are implicitly created around items
@@ -828,9 +841,6 @@ pub struct ModuleS<'a> {
     // The number of unresolved pub glob imports in this module
     pub_glob_count: Cell<usize>,
 
-    // The index of the import we're resolving.
-    resolved_import_count: Cell<usize>,
-
     // Whether this module is populated. If not populated, any attempt to
     // access the children must be preceded with a
     // `populate_module_if_necessary` call.
@@ -840,20 +850,20 @@ pub struct ModuleS<'a> {
 pub type Module<'a> = &'a ModuleS<'a>;
 
 impl<'a> ModuleS<'a> {
+
     fn new(parent_link: ParentLink<'a>, def: Option<Def>, external: bool, is_public: bool) -> Self {
         ModuleS {
             parent_link: parent_link,
             def: def,
             is_public: is_public,
-            is_extern_crate: false,
+            extern_crate_did: None,
             resolutions: RefCell::new(HashMap::new()),
-            imports: RefCell::new(Vec::new()),
+            unresolved_imports: RefCell::new(Vec::new()),
             module_children: RefCell::new(NodeMap()),
             shadowed_traits: RefCell::new(Vec::new()),
             glob_count: Cell::new(0),
             pub_count: Cell::new(0),
             pub_glob_count: Cell::new(0),
-            resolved_import_count: Cell::new(0),
             populated: Cell::new(!external),
         }
     }
@@ -910,6 +920,16 @@ impl<'a> ModuleS<'a> {
         self.def.as_ref().map(Def::def_id)
     }
 
+    // This returns the DefId of the crate local item that controls this module's visibility.
+    // It is only used to compute `LastPrivate` data, and it differs from `def_id` only for extern
+    // crates, whose `def_id` is the external crate's root, not the local `extern crate` item.
+    fn local_def_id(&self) -> Option<DefId> {
+        match self.extern_crate_did {
+            Some(def_id) => Some(def_id),
+            None => self.def_id(),
+        }
+    }
+
     fn is_normal(&self) -> bool {
         match self.def {
             Some(Def::Mod(_)) | Some(Def::ForeignMod(_)) => true,
@@ -924,15 +944,6 @@ impl<'a> ModuleS<'a> {
         }
     }
 
-    fn all_imports_resolved(&self) -> bool {
-        if self.imports.borrow_state() == ::std::cell::BorrowState::Writing {
-            // it is currently being resolved ! so nope
-            false
-        } else {
-            self.imports.borrow().len() == self.resolved_import_count.get()
-        }
-    }
-
     pub fn inc_glob_count(&self) {
         self.glob_count.set(self.glob_count.get() + 1);
     }
@@ -1029,6 +1040,14 @@ impl<'a> NameBinding<'a> {
         }
     }
 
+    fn local_def_id(&self) -> Option<DefId> {
+        match self.kind {
+            NameBindingKind::Def(def) => Some(def.def_id()),
+            NameBindingKind::Module(ref module) => module.local_def_id(),
+            NameBindingKind::Import { binding, .. } => binding.local_def_id(),
+        }
+    }
+
     fn defined_with(&self, modifiers: DefModifiers) -> bool {
         self.modifiers.contains(modifiers)
     }
@@ -1039,11 +1058,13 @@ impl<'a> NameBinding<'a> {
 
     fn def_and_lp(&self) -> (Def, LastPrivate) {
         let def = self.def().unwrap();
-        (def, LastMod(if self.is_public() { AllPublic } else { DependsOn(def.def_id()) }))
+        if let Def::Err = def { return (def, LastMod(AllPublic)) }
+        let lp = if self.is_public() { AllPublic } else { DependsOn(self.local_def_id().unwrap()) };
+        (def, LastMod(lp))
     }
 
     fn is_extern_crate(&self) -> bool {
-        self.module().map(|module| module.is_extern_crate).unwrap_or(false)
+        self.module().and_then(|module| module.extern_crate_did).is_some()
     }
 
     fn is_import(&self) -> bool {
@@ -1237,9 +1258,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         self.arenas.name_bindings.alloc(name_binding)
     }
 
-    fn new_extern_crate_module(&self, parent_link: ParentLink<'a>, def: Def) -> Module<'a> {
-        let mut module = ModuleS::new(parent_link, Some(def), false, true);
-        module.is_extern_crate = true;
+    fn new_extern_crate_module(&self,
+                               parent_link: ParentLink<'a>,
+                               def: Def,
+                               is_public: bool,
+                               local_def: DefId)
+                               -> Module<'a> {
+        let mut module = ModuleS::new(parent_link, Some(def), false, is_public);
+        module.extern_crate_did = Some(local_def);
         self.arenas.modules.alloc(module)
     }
 
@@ -1290,7 +1316,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                      span: Span,
                                      lp: LastPrivate)
                                      -> ResolveResult<(Module<'a>, LastPrivate)> {
-        fn search_parent_externals<'a>(needle: Name, module: Module<'a>) -> Option<Module<'a>> {
+        fn search_parent_externals(needle: Name, module: Module) -> Option<Module> {
             match module.resolve_name(needle, TypeNS, false) {
                 Success(binding) if binding.is_extern_crate() => Some(module),
                 _ => match module.parent_link {
@@ -1358,7 +1384,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         // Keep track of the closest private module used
                         // when resolving this import chain.
                         if !binding.is_public() {
-                            if let Some(did) = search_module.def_id() {
+                            if let Some(did) = search_module.local_def_id() {
                                 closest_private = LastMod(DependsOn(did));
                             }
                         }
@@ -1463,7 +1489,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             Success(PrefixFound(ref containing_module, index)) => {
                 search_module = containing_module;
                 start_index = index;
-                last_private = LastMod(DependsOn(containing_module.def_id()
+                last_private = LastMod(DependsOn(containing_module.local_def_id()
                                                                   .unwrap()));
             }
         }
@@ -1622,13 +1648,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     fn report_unresolved_imports(&mut self, module_: Module<'a>) {
-        let index = module_.resolved_import_count.get();
-        let imports = module_.imports.borrow();
-        let import_count = imports.len();
-        if index != import_count {
-            resolve_error(self,
-                          (*imports)[index].span,
-                          ResolutionError::UnresolvedImport(None));
+        for import in module_.unresolved_imports.borrow().iter() {
+            resolve_error(self, import.span, ResolutionError::UnresolvedImport(None));
+            break;
         }
 
         // Descend into children and anonymous children.
@@ -1658,16 +1680,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     fn with_scope<F>(&mut self, id: NodeId, f: F)
         where F: FnOnce(&mut Resolver)
     {
-        let orig_module = self.current_module;
+        if let Some(module) = self.current_module.module_children.borrow().get(&id) {
+            // Move down in the graph.
+            let orig_module = ::std::mem::replace(&mut self.current_module, module);
+            self.value_ribs.push(Rib::new(ModuleRibKind(module)));
+            self.type_ribs.push(Rib::new(ModuleRibKind(module)));
 
-        // Move down in the graph.
-        if let Some(module) = orig_module.module_children.borrow().get(&id) {
-            self.current_module = module;
-        }
+            f(self);
 
-        f(self);
-
-        self.current_module = orig_module;
+            self.current_module = orig_module;
+            self.value_ribs.pop();
+            self.type_ribs.pop();
+        } else {
+            f(self);
+        }
     }
 
     /// Searches the current set of local scopes for labels.
@@ -1970,10 +1996,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 Err(())
             }
         } else {
-            resolve_error(self,
-                          trait_path.span,
-                          ResolutionError::UndeclaredTraitName(&path_names_to_string(trait_path,
-                                                                                      path_depth)));
+
+            // find possible candidates
+            let trait_name = trait_path.segments.last().unwrap().identifier.name;
+            let candidates =
+                self.lookup_candidates(
+                    trait_name,
+                    TypeNS,
+                    |def| match def {
+                        Def::Trait(_) => true,
+                        _             => false,
+                    },
+                );
+
+            // create error object
+            let name = &path_names_to_string(trait_path, path_depth);
+            let error =
+                ResolutionError::UndeclaredTraitName(
+                    name,
+                    candidates,
+                );
+
+            resolve_error(self, trait_path.span, error);
             Err(())
         }
     }
@@ -2226,8 +2270,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         if let Some(anonymous_module) = anonymous_module {
             debug!("(resolving block) found anonymous module, moving down");
-            self.value_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
-            self.type_ribs.push(Rib::new(AnonymousModuleRibKind(anonymous_module)));
+            self.value_ribs.push(Rib::new(ModuleRibKind(anonymous_module)));
+            self.type_ribs.push(Rib::new(ModuleRibKind(anonymous_module)));
             self.current_module = anonymous_module;
         } else {
             self.value_ribs.push(Rib::new(NormalRibKind));
@@ -2297,13 +2341,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                           ty.span,
                                           ResolutionError::SelfUsedOutsideImplOrTrait);
                         } else {
-                            resolve_error(self,
-                                          ty.span,
-                                          ResolutionError::UseOfUndeclared(
-                                                                    kind,
-                                                                    &path_names_to_string(path,
-                                                                                           0))
-                                         );
+                            let segment = path.segments.last();
+                            let segment = segment.expect("missing name in path");
+                            let type_name = segment.identifier.name;
+
+                            let candidates =
+                                self.lookup_candidates(
+                                    type_name,
+                                    TypeNS,
+                                    |def| match def {
+                                        Def::Trait(_) |
+                                        Def::Enum(_) |
+                                        Def::Struct(_) |
+                                        Def::TyAlias(_) => true,
+                                        _               => false,
+                                    },
+                                );
+
+                            // create error object
+                            let name = &path_names_to_string(path, 0);
+                            let error =
+                                ResolutionError::UseOfUndeclared(
+                                    kind,
+                                    name,
+                                    candidates,
+                                );
+
+                            resolve_error(self, ty.span, error);
                         }
                     }
                 }
@@ -2323,8 +2387,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let pat_id = pattern.id;
         walk_pat(pattern, |pattern| {
             match pattern.node {
-                PatIdent(binding_mode, ref path1, ref at_rhs) => {
-                    // The meaning of PatIdent with no type parameters
+                PatKind::Ident(binding_mode, ref path1, ref at_rhs) => {
+                    // The meaning of PatKind::Ident with no type parameters
                     // depends on whether an enum variant or unit-like struct
                     // with that name is in scope. The probing lookup has to
                     // be careful not to emit spurious errors. Only matching
@@ -2435,7 +2499,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     }
                 }
 
-                PatEnum(ref path, _) => {
+                PatKind::TupleStruct(ref path, _) | PatKind::Path(ref path) => {
                     // This must be an enum variant, struct or const.
                     let resolution = match self.resolve_possibly_assoc_item(pat_id,
                                                                             None,
@@ -2443,16 +2507,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                                                             ValueNS,
                                                                             false) {
                         // The below shouldn't happen because all
-                        // qualified paths should be in PatQPath.
+                        // qualified paths should be in PatKind::QPath.
                         TypecheckRequired =>
                             self.session.span_bug(path.span,
-                                                  "resolve_possibly_assoc_item claimed
-                                     \
-                                                   that a path in PatEnum requires typecheck
-                                     \
-                                                   to resolve, but qualified paths should be
-                                     \
-                                                   PatQPath"),
+                                                  "resolve_possibly_assoc_item claimed that a path \
+                                                   in PatKind::Path or PatKind::TupleStruct \
+                                                   requires typecheck to resolve, but qualified \
+                                                   paths should be PatKind::QPath"),
                         ResolveAttempt(resolution) => resolution,
                     };
                     if let Some(path_res) = resolution {
@@ -2511,7 +2572,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     intravisit::walk_path(self, path);
                 }
 
-                PatQPath(ref qself, ref path) => {
+                PatKind::QPath(ref qself, ref path) => {
                     // Associated constants only.
                     let resolution = match self.resolve_possibly_assoc_item(pat_id,
                                                                             Some(qself),
@@ -2566,7 +2627,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     intravisit::walk_pat(self, pattern);
                 }
 
-                PatStruct(ref path, _, _) => {
+                PatKind::Struct(ref path, _, _) => {
                     match self.resolve_path(pat_id, path, 0, TypeNS, false) {
                         Some(definition) => {
                             self.record_def(pattern.id, definition);
@@ -2585,7 +2646,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     intravisit::walk_path(self, path);
                 }
 
-                PatLit(_) | PatRange(..) => {
+                PatKind::Lit(_) | PatKind::Range(..) => {
                     intravisit::walk_pat(self, pattern);
                 }
 
@@ -2754,8 +2815,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         if check_ribs {
-            if let Some(def) = self.resolve_identifier_in_local_ribs(identifier, namespace) {
-                return Some(def);
+            match self.resolve_identifier_in_local_ribs(identifier, namespace, record_used) {
+                Some(def) => return Some(def),
+                None => {}
             }
         }
 
@@ -2787,7 +2849,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             Def::Local(_, node_id) => {
                 for rib in ribs {
                     match rib.kind {
-                        NormalRibKind | AnonymousModuleRibKind(..) => {
+                        NormalRibKind | ModuleRibKind(..) => {
                             // Nothing to do. Continue.
                         }
                         ClosureRibKind(function_id) => {
@@ -2836,7 +2898,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind | MethodRibKind | ClosureRibKind(..) |
-                        AnonymousModuleRibKind(..) => {
+                        ModuleRibKind(..) => {
                             // Nothing to do. Continue.
                         }
                         ItemRibKind => {
@@ -2967,7 +3029,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     fn resolve_identifier_in_local_ribs(&mut self,
                                         ident: hir::Ident,
-                                        namespace: Namespace)
+                                        namespace: Namespace,
+                                        record_used: bool)
                                         -> Option<LocalDef> {
         // Check the local set of ribs.
         let name = match namespace { ValueNS => ident.name, TypeNS => ident.unhygienic_name };
@@ -2994,16 +3057,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 }
             }
 
-            if let AnonymousModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
+            if let ModuleRibKind(module) = self.get_ribs(namespace)[i].kind {
                 if let Success(binding) = self.resolve_name_in_module(module,
                                                                       ident.unhygienic_name,
                                                                       namespace,
                                                                       true,
-                                                                      true) {
+                                                                      record_used) {
                     if let Some(def) = binding.def() {
                         return Some(LocalDef::from_def(def));
                     }
                 }
+                // We can only see through anonymous modules
+                if module.def.is_some() { return None; }
             }
         }
 
@@ -3461,6 +3526,99 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         found_traits
     }
 
+    /// When name resolution fails, this method can be used to look up candidate
+    /// entities with the expected name. It allows filtering them using the
+    /// supplied predicate (which should be used to only accept the types of
+    /// definitions expected e.g. traits). The lookup spans across all crates.
+    ///
+    /// NOTE: The method does not look into imports, but this is not a problem,
+    /// since we report the definitions (thus, the de-aliased imports).
+    fn lookup_candidates<FilterFn>(&mut self,
+                                   lookup_name: Name,
+                                   namespace: Namespace,
+                                   filter_fn: FilterFn) -> SuggestedCandidates
+        where FilterFn: Fn(Def) -> bool {
+
+        let mut lookup_results = Vec::new();
+        let mut worklist = Vec::new();
+        worklist.push((self.graph_root, Vec::new(), false));
+
+        while let Some((in_module,
+                        path_segments,
+                        in_module_is_extern)) = worklist.pop() {
+            build_reduced_graph::populate_module_if_necessary(self, &in_module);
+
+            in_module.for_each_child(|name, ns, name_binding| {
+
+                // avoid imports entirely
+                if name_binding.is_import() { return; }
+
+                // collect results based on the filter function
+                if let Some(def) = name_binding.def() {
+                    if name == lookup_name && ns == namespace && filter_fn(def) {
+                        // create the path
+                        let ident = hir::Ident::from_name(name);
+                        let params = PathParameters::none();
+                        let segment = PathSegment {
+                            identifier: ident,
+                            parameters: params,
+                        };
+                        let span = name_binding.span.unwrap_or(syntax::codemap::DUMMY_SP);
+                        let mut segms = path_segments.clone();
+                        segms.push(segment);
+                        let segms = HirVec::from_vec(segms);
+                        let path = Path {
+                            span: span,
+                            global: true,
+                            segments: segms,
+                        };
+                        // the entity is accessible in the following cases:
+                        // 1. if it's defined in the same crate, it's always
+                        // accessible (since private entities can be made public)
+                        // 2. if it's defined in another crate, it's accessible
+                        // only if both the module is public and the entity is
+                        // declared as public (due to pruning, we don't explore
+                        // outside crate private modules => no need to check this)
+                        if !in_module_is_extern || name_binding.is_public() {
+                            lookup_results.push(path);
+                        }
+                    }
+                }
+
+                // collect submodules to explore
+                if let Some(module) = name_binding.module() {
+                    // form the path
+                    let path_segments = match module.parent_link {
+                        NoParentLink => path_segments.clone(),
+                        ModuleParentLink(_, name) => {
+                            let mut paths = path_segments.clone();
+                            let ident = hir::Ident::from_name(name);
+                            let params = PathParameters::none();
+                            let segm = PathSegment {
+                                identifier: ident,
+                                parameters: params,
+                            };
+                            paths.push(segm);
+                            paths
+                        }
+                        _ => unreachable!(),
+                    };
+
+                    if !in_module_is_extern || name_binding.is_public() {
+                        // add the module to the lookup
+                        let is_extern = in_module_is_extern || name_binding.is_extern_crate();
+                        worklist.push((module, path_segments, is_extern));
+                    }
+                }
+            })
+        }
+
+        SuggestedCandidates {
+            name: lookup_name.as_str().to_string(),
+            candidates: lookup_results,
+        }
+    }
+
     fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
         debug!("(recording def) recording {:?} for {}", resolution, node_id);
         assert!(match resolution.last_private {
@@ -3516,11 +3674,72 @@ fn path_names_to_string(path: &Path, depth: usize) -> String {
     names_to_string(&names[..])
 }
 
+/// When an entity with a given name is not available in scope, we search for
+/// entities with that name in all crates. This method allows outputting the
+/// results of this search in a programmer-friendly way
+fn show_candidates(session: &mut DiagnosticBuilder,
+                   span: syntax::codemap::Span,
+                   candidates: &SuggestedCandidates) {
+
+    let paths = &candidates.candidates;
+
+    if paths.len() > 0 {
+        // don't show more than MAX_CANDIDATES results, so
+        // we're consistent with the trait suggestions
+        const MAX_CANDIDATES: usize = 5;
+
+        // we want consistent results across executions, but candidates are produced
+        // by iterating through a hash map, so make sure they are ordered:
+        let mut path_strings: Vec<_> = paths.into_iter()
+                                            .map(|p| path_names_to_string(&p, 0))
+                                            .collect();
+        path_strings.sort();
+
+        // behave differently based on how many candidates we have:
+        if !paths.is_empty() {
+            if paths.len() == 1 {
+                session.fileline_help(
+                    span,
+                    &format!("you can to import it into scope: `use {};`.",
+                        &path_strings[0]),
+                );
+            } else {
+                session.fileline_help(span, "you can import several candidates \
+                    into scope (`use ...;`):");
+                let count = path_strings.len() as isize - MAX_CANDIDATES as isize + 1;
+
+                for (idx, path_string) in path_strings.iter().enumerate() {
+                    if idx == MAX_CANDIDATES - 1 && count > 1 {
+                        session.fileline_help(
+                            span,
+                            &format!("  and {} other candidates", count).to_string(),
+                        );
+                        break;
+                    } else {
+                        session.fileline_help(
+                            span,
+                            &format!("  `{}`", path_string).to_string(),
+                        );
+                    }
+                }
+            }
+        }
+    } else {
+        // nothing found:
+        session.fileline_help(
+            span,
+            &format!("no candidates by the name of `{}` found in your \
+            project; maybe you misspelled the name or forgot to import \
+            an external crate?", candidates.name.to_string()),
+        );
+    };
+}
+
 /// A somewhat inefficient routine to obtain the name of a module.
-fn module_to_string<'a>(module: Module<'a>) -> String {
+fn module_to_string(module: Module) -> String {
     let mut names = Vec::new();
 
-    fn collect_mod<'a>(names: &mut Vec<ast::Name>, module: Module<'a>) {
+    fn collect_mod(names: &mut Vec<ast::Name>, module: Module) {
         match module.parent_link {
             NoParentLink => {}
             ModuleParentLink(ref module, name) => {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 1253d4f9cef..c068ff258b0 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -173,13 +173,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
     fn resolve_imports(&mut self) {
         let mut i = 0;
         let mut prev_unresolved_imports = 0;
+        let mut errors = Vec::new();
+
         loop {
             debug!("(resolving imports) iteration {}, {} imports left",
                    i,
                    self.resolver.unresolved_imports);
 
-            let module_root = self.resolver.graph_root;
-            let errors = self.resolve_imports_for_module_subtree(module_root);
+            self.resolve_imports_for_module_subtree(self.resolver.graph_root, &mut errors);
 
             if self.resolver.unresolved_imports == 0 {
                 debug!("(resolving imports) success");
@@ -197,7 +198,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                     // to avoid generating multiple errors on the same import.
                     // Imports that are still indeterminate at this point are actually blocked
                     // by errored imports, so there is no point reporting them.
-                    self.resolver.report_unresolved_imports(module_root);
+                    self.resolver.report_unresolved_imports(self.resolver.graph_root);
                 }
                 break;
             }
@@ -218,6 +219,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                 kind: NameBindingKind::Def(Def::Err),
                 span: None,
             });
+            let dummy_binding =
+                self.resolver.new_name_binding(e.import_directive.import(dummy_binding));
 
             let _ = e.source_module.try_define_child(target, ValueNS, dummy_binding);
             let _ = e.source_module.try_define_child(target, TypeNS, dummy_binding);
@@ -234,67 +237,45 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
     /// Attempts to resolve imports for the given module and all of its
     /// submodules.
     fn resolve_imports_for_module_subtree(&mut self,
-                                          module_: Module<'b>)
-                                          -> Vec<ImportResolvingError<'b>> {
-        let mut errors = Vec::new();
+                                          module_: Module<'b>,
+                                          errors: &mut Vec<ImportResolvingError<'b>>) {
         debug!("(resolving imports for module subtree) resolving {}",
                module_to_string(&module_));
         let orig_module = replace(&mut self.resolver.current_module, module_);
-        errors.extend(self.resolve_imports_for_module(module_));
+        self.resolve_imports_for_module(module_, errors);
         self.resolver.current_module = orig_module;
 
         for (_, child_module) in module_.module_children.borrow().iter() {
-            errors.extend(self.resolve_imports_for_module_subtree(child_module));
+            self.resolve_imports_for_module_subtree(child_module, errors);
         }
-
-        errors
     }
 
     /// Attempts to resolve imports for the given module only.
-    fn resolve_imports_for_module(&mut self, module: Module<'b>) -> Vec<ImportResolvingError<'b>> {
-        let mut errors = Vec::new();
-
-        if module.all_imports_resolved() {
-            debug!("(resolving imports for module) all imports resolved for {}",
-                   module_to_string(&module));
-            return errors;
-        }
-
-        let mut imports = module.imports.borrow_mut();
-        let import_count = imports.len();
-        let mut indeterminate_imports = Vec::new();
-        while module.resolved_import_count.get() + indeterminate_imports.len() < import_count {
-            let import_index = module.resolved_import_count.get();
-            match self.resolve_import_for_module(module, &imports[import_index]) {
-                ResolveResult::Failed(err) => {
-                    let import_directive = &imports[import_index];
+    fn resolve_imports_for_module(&mut self,
+                                  module: Module<'b>,
+                                  errors: &mut Vec<ImportResolvingError<'b>>) {
+        let mut imports = Vec::new();
+        let mut unresolved_imports = module.unresolved_imports.borrow_mut();
+        ::std::mem::swap(&mut imports, &mut unresolved_imports);
+
+        for import_directive in imports {
+            match self.resolve_import_for_module(module, &import_directive) {
+                Failed(err) => {
                     let (span, help) = match err {
                         Some((span, msg)) => (span, format!(". {}", msg)),
                         None => (import_directive.span, String::new()),
                     };
                     errors.push(ImportResolvingError {
                         source_module: module,
-                        import_directive: import_directive.clone(),
+                        import_directive: import_directive,
                         span: span,
                         help: help,
                     });
                 }
-                ResolveResult::Indeterminate => {}
-                ResolveResult::Success(()) => {
-                    // count success
-                    module.resolved_import_count
-                          .set(module.resolved_import_count.get() + 1);
-                    continue;
-                }
+                Indeterminate => unresolved_imports.push(import_directive),
+                Success(()) => {}
             }
-            // This resolution was not successful, keep it for later
-            indeterminate_imports.push(imports.swap_remove(import_index));
-
         }
-
-        imports.extend(indeterminate_imports);
-
-        errors
     }
 
     /// Attempts to resolve the given import. The return value indicates
@@ -413,7 +394,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                                            directive.is_public &&
                                            !name_binding.is_public() => {
                 let msg = format!("`{}` is private, and cannot be reexported", source);
-                let note_msg = format!("Consider marking `{}` as `pub` in the imported module",
+                let note_msg = format!("consider marking `{}` as `pub` in the imported module",
                                         source);
                 struct_span_err!(self.resolver.session, directive.span, E0364, "{}", &msg)
                     .span_note(directive.span, &note_msg)
@@ -422,12 +403,22 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
 
             (_, &Success(name_binding)) if !name_binding.is_import() && directive.is_public => {
                 if !name_binding.is_public() {
-                    let msg = format!("`{}` is private, and cannot be reexported", source);
-                    let note_msg =
-                        format!("Consider declaring type or module `{}` with `pub`", source);
-                    struct_span_err!(self.resolver.session, directive.span, E0365, "{}", &msg)
-                        .span_note(directive.span, &note_msg)
-                        .emit();
+                    if name_binding.is_extern_crate() {
+                        let msg = format!("extern crate `{}` is private, and cannot be reexported \
+                                           (error E0364), consider declaring with `pub`",
+                                           source);
+                        self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
+                                                       directive.id,
+                                                       directive.span,
+                                                       msg);
+                    } else {
+                        let msg = format!("`{}` is private, and cannot be reexported", source);
+                        let note_msg =
+                            format!("consider declaring type or module `{}` with `pub`", source);
+                        struct_span_err!(self.resolver.session, directive.span, E0365, "{}", &msg)
+                            .span_note(directive.span, &note_msg)
+                            .emit();
+                    }
                 } else if name_binding.defined_with(DefModifiers::PRIVATE_VARIANT) {
                     let msg = format!("variant `{}` is private, and cannot be reexported \
                                        (error E0364), consider declaring its enum as `pub`",
@@ -460,9 +451,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         module_.decrement_outstanding_references_for(target, TypeNS);
 
         let def_and_priv = |binding: &NameBinding| {
-            let def = binding.def().unwrap();
-            let last_private = if binding.is_public() { lp } else { DependsOn(def.def_id()) };
-            (def, last_private)
+            let last_private =
+                if binding.is_public() { lp } else { DependsOn(binding.local_def_id().unwrap()) };
+            (binding.def().unwrap(), last_private)
         };
         let value_def_and_priv = value_result.success().map(&def_and_priv);
         let type_def_and_priv = type_result.success().map(&def_and_priv);
@@ -512,7 +503,6 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
         build_reduced_graph::populate_module_if_necessary(self.resolver, target_module);
         target_module.for_each_child(|name, ns, binding| {
             if !binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) { return }
-            if binding.is_extern_crate() { return }
             self.define(module_, name, ns, directive.import(binding));
 
             if ns == TypeNS && directive.is_public &&
@@ -562,6 +552,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                        ns: Namespace,
                        binding: &'b NameBinding<'b>,
                        old_binding: &'b NameBinding<'b>) {
+        // Error on the second of two conflicting imports
+        if old_binding.is_import() && binding.is_import() &&
+           old_binding.span.unwrap().lo > binding.span.unwrap().lo {
+            self.report_conflict(name, ns, old_binding, binding);
+            return;
+        }
+
         if old_binding.is_extern_crate() {
             let msg = format!("import `{0}` conflicts with imported crate \
                                in this module (maybe you meant `use {0}::*`?)",
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 33734d615a6..76360dcc1b9 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -226,9 +226,8 @@ fn symbol_hash<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 fn get_symbol_hash<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> String {
-    match ccx.type_hashcodes().borrow().get(&t) {
-        Some(h) => return h.to_string(),
-        None => {}
+    if let Some(h) = ccx.type_hashcodes().borrow().get(&t) {
+        return h.to_string()
     }
 
     let mut symbol_hasher = ccx.symbol_hasher().borrow_mut();
@@ -315,9 +314,8 @@ pub fn mangle<PI: Iterator<Item=InternedString>>(path: PI, hash: Option<&str>) -
         push(&mut n, &data);
     }
 
-    match hash {
-        Some(s) => push(&mut n, s),
-        None => {}
+    if let Some(s) = hash {
+        push(&mut n, s)
     }
 
     n.push('E'); // End name-sequence.
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 27d6dbae28a..6f596b15b92 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -46,7 +46,7 @@ extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_data_structures;
 extern crate rustc_front;
-extern crate rustc_llvm as llvm;
+pub extern crate rustc_llvm as llvm;
 extern crate rustc_mir;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate serialize;
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index 70f8e268f17..c5efc9b7e22 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -227,7 +227,7 @@ use std::cell::RefCell;
 use std::cmp::Ordering;
 use std::fmt;
 use std::rc::Rc;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
 use syntax::codemap::Span;
 use rustc_front::fold::Folder;
@@ -424,7 +424,7 @@ impl<'a, 'p, 'blk, 'tcx> fmt::Debug for Match<'a, 'p, 'blk, 'tcx> {
 fn has_nested_bindings(m: &[Match], col: usize) -> bool {
     for br in m {
         match br.pats[col].node {
-            hir::PatIdent(_, _, Some(_)) => return true,
+            PatKind::Ident(_, _, Some(_)) => return true,
             _ => ()
         }
     }
@@ -477,7 +477,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let mut pat = br.pats[col];
         loop {
             pat = match pat.node {
-                hir::PatIdent(_, ref path, Some(ref inner)) => {
+                PatKind::Ident(_, ref path, Some(ref inner)) => {
                     bound_ptrs.push((path.node.name, val.val));
                     &inner
                 },
@@ -517,13 +517,13 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             let this = br.pats[col];
             let mut bound_ptrs = br.bound_ptrs.clone();
             match this.node {
-                hir::PatIdent(_, ref path, None) => {
+                PatKind::Ident(_, ref path, None) => {
                     if pat_is_binding(&dm.borrow(), &this) {
                         bound_ptrs.push((path.node.name, val.val));
                     }
                 }
-                hir::PatVec(ref before, Some(ref slice), ref after) => {
-                    if let hir::PatIdent(_, ref path, None) = slice.node {
+                PatKind::Vec(ref before, Some(ref slice), ref after) => {
+                    if let PatKind::Ident(_, ref path, None) = slice.node {
                         let subslice_val = bind_subslice_pat(
                             bcx, this.id, val,
                             before.len(), after.len());
@@ -662,10 +662,11 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         };
 
         let opt = match cur.node {
-            hir::PatLit(ref l) => {
+            PatKind::Lit(ref l) => {
                 ConstantValue(ConstantExpr(&l), debug_loc)
             }
-            hir::PatIdent(..) | hir::PatEnum(..) | hir::PatStruct(..) => {
+            PatKind::Ident(..) | PatKind::Path(..) |
+            PatKind::TupleStruct(..) | PatKind::Struct(..) => {
                 // This is either an enum variant or a variable binding.
                 let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
                 match opt_def {
@@ -679,13 +680,13 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     _ => continue
                 }
             }
-            hir::PatRange(ref l1, ref l2) => {
+            PatKind::Range(ref l1, ref l2) => {
                 ConstantRange(ConstantExpr(&l1), ConstantExpr(&l2), debug_loc)
             }
-            hir::PatVec(ref before, None, ref after) => {
+            PatKind::Vec(ref before, None, ref after) => {
                 SliceLengthEqual(before.len() + after.len(), debug_loc)
             }
-            hir::PatVec(ref before, Some(_), ref after) => {
+            PatKind::Vec(ref before, Some(_), ref after) => {
                 SliceLengthGreaterOrEqual(before.len(), after.len(), debug_loc)
             }
             _ => continue
@@ -786,28 +787,23 @@ macro_rules! any_pat {
 }
 
 fn any_uniq_pat(m: &[Match], col: usize) -> bool {
-    any_pat!(m, col, hir::PatBox(_))
+    any_pat!(m, col, PatKind::Box(_))
 }
 
 fn any_region_pat(m: &[Match], col: usize) -> bool {
-    any_pat!(m, col, hir::PatRegion(..))
+    any_pat!(m, col, PatKind::Ref(..))
 }
 
 fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: usize) -> bool {
     m.iter().any(|br| {
         let pat = br.pats[col];
         match pat.node {
-            hir::PatTup(_) => true,
-            hir::PatStruct(..) => {
-                match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                    Some(Def::Variant(..)) => false,
-                    _ => true,
-                }
-            }
-            hir::PatEnum(..) | hir::PatIdent(_, _, None) => {
-                match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                    Some(Def::Struct(..)) => true,
-                    _ => false
+            PatKind::Tup(_) => true,
+            PatKind::Struct(..) | PatKind::TupleStruct(..) |
+            PatKind::Path(..) | PatKind::Ident(_, _, None) => {
+                match tcx.def_map.borrow().get(&pat.id).unwrap().full_def() {
+                    Def::Struct(..) | Def::TyAlias(..) => true,
+                    _ => false,
                 }
             }
             _ => false
@@ -849,7 +845,7 @@ impl FailureHandler {
 fn pick_column_to_specialize(def_map: &RefCell<DefMap>, m: &[Match]) -> Option<usize> {
     fn pat_score(def_map: &RefCell<DefMap>, pat: &hir::Pat) -> usize {
         match pat.node {
-            hir::PatIdent(_, _, Some(ref inner)) => pat_score(def_map, &inner),
+            PatKind::Ident(_, _, Some(ref inner)) => pat_score(def_map, &inner),
             _ if pat_is_refutable(&def_map.borrow(), pat) => 1,
             _ => 0
         }
@@ -871,7 +867,7 @@ fn pick_column_to_specialize(def_map: &RefCell<DefMap>, m: &[Match]) -> Option<u
 
     let column_contains_any_nonwild_patterns = |&col: &usize| -> bool {
         m.iter().any(|row| match row.pats[col].node {
-            hir::PatWild => false,
+            PatKind::Wild => false,
             _ => true
         })
     };
@@ -1639,7 +1635,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
     // to the default arm.
     let has_default = arms.last().map_or(false, |arm| {
         arm.pats.len() == 1
-        && arm.pats.last().unwrap().node == hir::PatWild
+        && arm.pats.last().unwrap().node == PatKind::Wild
     });
 
     compile_submatch(bcx, &matches[..], &[discr_datum.match_input()], &chk, has_default);
@@ -1812,7 +1808,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let tcx = bcx.tcx();
     let ccx = bcx.ccx();
     match pat.node {
-        hir::PatIdent(pat_binding_mode, ref path1, ref inner) => {
+        PatKind::Ident(pat_binding_mode, ref path1, ref inner) => {
             if pat_is_binding(&tcx.def_map.borrow(), &pat) {
                 // Allocate the stack slot where the value of this
                 // binding will live and place it into the appropriate
@@ -1849,7 +1845,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 bcx = bind_irrefutable_pat(bcx, &inner_pat, val, cleanup_scope);
             }
         }
-        hir::PatEnum(_, ref sub_pats) => {
+        PatKind::TupleStruct(_, ref sub_pats) => {
             let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
             match opt_def {
                 Some(Def::Variant(enum_id, var_id)) => {
@@ -1895,7 +1891,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        hir::PatStruct(_, ref fields, _) => {
+        PatKind::Struct(_, ref fields, _) => {
             let tcx = bcx.tcx();
             let pat_ty = node_id_type(bcx, pat.id);
             let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
@@ -1935,7 +1931,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                            cleanup_scope);
             }
         }
-        hir::PatTup(ref elems) => {
+        PatKind::Tup(ref elems) => {
             let repr = adt::represent_node(bcx, pat.id);
             let val = adt::MaybeSizedValue::sized(val.val);
             for (i, elem) in elems.iter().enumerate() {
@@ -1947,13 +1943,13 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     cleanup_scope);
             }
         }
-        hir::PatBox(ref inner) => {
+        PatKind::Box(ref inner) => {
             let pat_ty = node_id_type(bcx, inner.id);
             // Pass along DSTs as fat pointers.
             let val = if type_is_fat_ptr(tcx, pat_ty) {
                 // We need to check for this, as the pattern could be binding
                 // a fat pointer by-value.
-                if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+                if let PatKind::Ident(hir::BindByRef(_),_,_) = inner.node {
                     val.val
                 } else {
                     Load(bcx, val.val)
@@ -1966,13 +1962,13 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             bcx = bind_irrefutable_pat(
                 bcx, &inner, MatchInput::from_val(val), cleanup_scope);
         }
-        hir::PatRegion(ref inner, _) => {
+        PatKind::Ref(ref inner, _) => {
             let pat_ty = node_id_type(bcx, inner.id);
             // Pass along DSTs as fat pointers.
             let val = if type_is_fat_ptr(tcx, pat_ty) {
                 // We need to check for this, as the pattern could be binding
                 // a fat pointer by-value.
-                if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+                if let PatKind::Ident(hir::BindByRef(_),_,_) = inner.node {
                     val.val
                 } else {
                     Load(bcx, val.val)
@@ -1988,7 +1984,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 MatchInput::from_val(val),
                 cleanup_scope);
         }
-        hir::PatVec(ref before, ref slice, ref after) => {
+        PatKind::Vec(ref before, ref slice, ref after) => {
             let pat_ty = node_id_type(bcx, pat.id);
             let mut extracted = extract_vec_elems(bcx, pat_ty, before.len(), after.len(), val);
             match slice {
@@ -2013,8 +2009,8 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         cleanup_scope)
                 });
         }
-        hir::PatQPath(..) | hir::PatWild | hir::PatLit(_) |
-        hir::PatRange(_, _) => ()
+        PatKind::Path(..) | PatKind::QPath(..) | PatKind::Wild | PatKind::Lit(_) |
+        PatKind::Range(_, _) => ()
     }
     return bcx;
 }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index e36905c6d90..161ab90c03a 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -150,9 +150,8 @@ impl Drop for _InsnCtxt {
 pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
     debug!("new InsnCtxt: {}", s);
     TASK_LOCAL_INSN_KEY.with(|slot| {
-        match slot.borrow_mut().as_mut() {
-            Some(ctx) => ctx.push(s),
-            None => {}
+        if let Some(ctx) = slot.borrow_mut().as_mut() {
+            ctx.push(s)
         }
     });
     _InsnCtxt {
@@ -198,9 +197,8 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 name: &str,
                                 did: DefId)
                                 -> ValueRef {
-    match ccx.externs().borrow().get(name) {
-        Some(n) => return *n,
-        None => (),
+    if let Some(n) = ccx.externs().borrow().get(name) {
+        return *n;
     }
 
     let f = declare::declare_rust_fn(ccx, name, fn_ty);
@@ -238,9 +236,8 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                   -> ValueRef {
     let name = ccx.sess().cstore.item_symbol(did);
     let ty = type_of(ccx, t);
-    match ccx.externs().borrow_mut().get(&name) {
-        Some(n) => return *n,
-        None => (),
+    if let Some(n) = ccx.externs().borrow_mut().get(&name) {
+        return *n;
     }
     // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
     // FIXME(nagisa): investigate whether it can be changed into define_global
@@ -2755,9 +2752,8 @@ fn contains_null(s: &str) -> bool {
 pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
     debug!("get_item_val(id=`{}`)", id);
 
-    match ccx.item_vals().borrow().get(&id).cloned() {
-        Some(v) => return v,
-        None => {}
+    if let Some(v) = ccx.item_vals().borrow().get(&id).cloned() {
+        return v;
     }
 
     let item = ccx.tcx().map.get(id);
diff --git a/src/librustc_trans/trans/build.rs b/src/librustc_trans/trans/build.rs
index ce541c8d411..2b4fcf436cb 100644
--- a/src/librustc_trans/trans/build.rs
+++ b/src/librustc_trans/trans/build.rs
@@ -1067,8 +1067,9 @@ pub fn Resume(cx: Block, exn: ValueRef) -> ValueRef {
 pub fn AtomicCmpXchg(cx: Block, dst: ValueRef,
                      cmp: ValueRef, src: ValueRef,
                      order: AtomicOrdering,
-                     failure_order: AtomicOrdering) -> ValueRef {
-    B(cx).atomic_cmpxchg(dst, cmp, src, order, failure_order)
+                     failure_order: AtomicOrdering,
+                     weak: llvm::Bool) -> ValueRef {
+    B(cx).atomic_cmpxchg(dst, cmp, src, order, failure_order, weak)
 }
 pub fn AtomicRMW(cx: Block, op: AtomicBinOp,
                  dst: ValueRef, src: ValueRef,
diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs
index 878d01f46b6..434fca41688 100644
--- a/src/librustc_trans/trans/builder.rs
+++ b/src/librustc_trans/trans/builder.rs
@@ -1077,10 +1077,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn atomic_cmpxchg(&self, dst: ValueRef,
                          cmp: ValueRef, src: ValueRef,
                          order: AtomicOrdering,
-                         failure_order: AtomicOrdering) -> ValueRef {
+                         failure_order: AtomicOrdering,
+                         weak: llvm::Bool) -> ValueRef {
         unsafe {
             llvm::LLVMBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
-                                         order, failure_order)
+                                         order, failure_order, weak)
         }
     }
     pub fn atomic_rmw(&self, op: AtomicBinOp,
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index eb54527b373..7f7de0e872b 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -767,6 +767,10 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
     {
         self.bcx.monomorphize(value)
     }
+
+    pub fn set_lpad(&self, lpad: Option<LandingPad>) {
+        self.bcx.lpad.set(lpad.map(|p| &*self.fcx().lpad_arena.alloc(p)))
+    }
 }
 
 impl<'blk, 'tcx> Deref for BlockAndBuilder<'blk, 'tcx> {
@@ -943,9 +947,8 @@ pub fn C_u8(ccx: &CrateContext, i: u8) -> ValueRef {
 // our boxed-and-length-annotated strings.
 pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> ValueRef {
     unsafe {
-        match cx.const_cstr_cache().borrow().get(&s) {
-            Some(&llval) => return llval,
-            None => ()
+        if let Some(&llval) = cx.const_cstr_cache().borrow().get(&s) {
+            return llval;
         }
 
         let sc = llvm::LLVMConstStringInContext(cx.llcx(),
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 4f25091d343..79c73a83ee7 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -24,8 +24,6 @@ use middle::const_eval::{const_int_checked_div, const_uint_checked_div};
 use middle::const_eval::{const_int_checked_rem, const_uint_checked_rem};
 use middle::const_eval::{const_int_checked_shl, const_uint_checked_shl};
 use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
-use middle::const_eval::EvalHint::ExprTypeChecked;
-use middle::const_eval::eval_const_expr_partial;
 use middle::def::Def;
 use middle::def_id::DefId;
 use trans::{adt, closure, debuginfo, expr, inline, machine};
@@ -42,7 +40,7 @@ use trans::type_of;
 use trans::Disr;
 use middle::subst::Substs;
 use middle::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
-use middle::ty::adjustment::AdjustUnsafeFnPointer;
+use middle::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
 use middle::ty::{self, Ty};
 use middle::ty::cast::{CastTy,IntTy};
 use util::nodemap::NodeMap;
@@ -261,7 +259,7 @@ impl ConstEvalFailure {
     }
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum TrueConst {
     Yes, No
 }
@@ -356,7 +354,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // FIXME(#19925) once fn item types are
             // zero-sized, we'll need to do something here
         }
-        Some(AdjustUnsafeFnPointer) => {
+        Some(AdjustUnsafeFnPointer) | Some(AdjustMutToConstPointer) => {
             // purely a type-level thing
         }
         Some(AdjustDerefRef(adj)) => {
@@ -665,11 +663,11 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         },
         hir::ExprIndex(ref base, ref index) => {
             let (bv, bt) = try!(const_expr(cx, &base, param_substs, fn_args, trueconst));
-            let iv = match eval_const_expr_partial(cx.tcx(), &index, ExprTypeChecked, None) {
-                Ok(ConstVal::Int(i)) => i as u64,
-                Ok(ConstVal::Uint(u)) => u,
-                _ => cx.sess().span_bug(index.span,
-                                        "index is not an integer-constant expression")
+            let iv = try!(const_expr(cx, &index, param_substs, fn_args, TrueConst::Yes)).0;
+            let iv = if let Some(iv) = const_to_opt_uint(iv) {
+                iv
+            } else {
+                cx.sess().span_bug(index.span, "index is not an integer-constant expression");
             };
             let (arr, len) = match bt.sty {
                 ty::TyArray(_, u) => (bv, C_uint(cx, u)),
diff --git a/src/librustc_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs
index bbbc9c4eda4..73fdbd54b29 100644
--- a/src/librustc_trans/trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/trans/debuginfo/create_scope_map.rs
@@ -22,7 +22,7 @@ use syntax::codemap::{Span, Pos};
 use syntax::{ast, codemap};
 
 use rustc_front;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 
 // This procedure builds the *scope map* for a given function, which maps any
 // given ast::NodeId in the function's AST to the correct DIScope metadata instance.
@@ -163,7 +163,7 @@ fn walk_pattern(cx: &CrateContext,
     // ast_util::walk_pat() here because we have to visit *all* nodes in
     // order to put them into the scope map. The above functions don't do that.
     match pat.node {
-        hir::PatIdent(_, ref path1, ref sub_pat_opt) => {
+        PatKind::Ident(_, ref path1, ref sub_pat_opt) => {
 
             // Check if this is a binding. If so we need to put it on the
             // scope stack and maybe introduce an artificial scope
@@ -235,11 +235,11 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        hir::PatWild => {
+        PatKind::Wild => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
         }
 
-        hir::PatEnum(_, ref sub_pats_opt) => {
+        PatKind::TupleStruct(_, ref sub_pats_opt) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             if let Some(ref sub_pats) = *sub_pats_opt {
@@ -249,11 +249,11 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        hir::PatQPath(..) => {
+        PatKind::Path(..) | PatKind::QPath(..) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
         }
 
-        hir::PatStruct(_, ref field_pats, _) => {
+        PatKind::Struct(_, ref field_pats, _) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             for &codemap::Spanned {
@@ -264,7 +264,7 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        hir::PatTup(ref sub_pats) => {
+        PatKind::Tup(ref sub_pats) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             for sub_pat in sub_pats {
@@ -272,23 +272,23 @@ fn walk_pattern(cx: &CrateContext,
             }
         }
 
-        hir::PatBox(ref sub_pat) | hir::PatRegion(ref sub_pat, _) => {
+        PatKind::Box(ref sub_pat) | PatKind::Ref(ref sub_pat, _) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
             walk_pattern(cx, &sub_pat, scope_stack, scope_map);
         }
 
-        hir::PatLit(ref exp) => {
+        PatKind::Lit(ref exp) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
             walk_expr(cx, &exp, scope_stack, scope_map);
         }
 
-        hir::PatRange(ref exp1, ref exp2) => {
+        PatKind::Range(ref exp1, ref exp2) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
             walk_expr(cx, &exp1, scope_stack, scope_map);
             walk_expr(cx, &exp2, scope_stack, scope_map);
         }
 
-        hir::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
+        PatKind::Vec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
             scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
             for sub_pat in front_sub_pats {
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index 843aebc4437..330d4077c41 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -28,7 +28,7 @@ use middle::infer;
 use middle::pat_util;
 use middle::subst;
 use rustc::front::map as hir_map;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use trans::{type_of, adt, machine, monomorphize};
 use trans::common::{self, CrateContext, FunctionContext, Block};
 use trans::_match::{BindingInfo, TransBindingMode};
@@ -1971,7 +1971,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         Some(hir_map::NodeLocal(pat)) => {
             match pat.node {
-                hir::PatIdent(_, ref path1, _) => {
+                PatKind::Ident(_, ref path1, _) => {
                     path1.node.name
                 }
                 _ => {
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index fac956c1ddd..782e38d3af2 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -71,7 +71,8 @@ use trans::tvec;
 use trans::type_of;
 use trans::Disr;
 use middle::ty::adjustment::{AdjustDerefRef, AdjustReifyFnPointer};
-use middle::ty::adjustment::{AdjustUnsafeFnPointer, CustomCoerceUnsized};
+use middle::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
+use middle::ty::adjustment::CustomCoerceUnsized;
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
 use middle::ty::cast::{CastKind, CastTy};
@@ -354,7 +355,7 @@ fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // zero-sized, we'll need to return true here
             false
         }
-        AdjustUnsafeFnPointer => {
+        AdjustUnsafeFnPointer | AdjustMutToConstPointer => {
             // purely a type-level thing
             false
         }
@@ -391,7 +392,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // FIXME(#19925) once fn item types are
             // zero-sized, we'll need to do something here
         }
-        AdjustUnsafeFnPointer => {
+        AdjustUnsafeFnPointer | AdjustMutToConstPointer => {
             // purely a type-level thing
         }
         AdjustDerefRef(ref adj) => {
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index b96f2cd45cf..06a4d3f1f64 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -39,6 +39,7 @@ use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token::{InternedString, special_idents};
 use syntax::ast;
+use syntax::attr::AttrMetaMethods;
 
 use rustc_front::print::pprust;
 use rustc_front::hir;
@@ -120,8 +121,8 @@ pub fn register_static(ccx: &CrateContext,
     let llty = type_of::type_of(ccx, ty);
 
     let ident = link_name(foreign_item);
-    match attr::first_attr_value_str_by_name(&foreign_item.attrs,
-                                             "linkage") {
+    let c = match attr::first_attr_value_str_by_name(&foreign_item.attrs,
+                                                     "linkage") {
         // If this is a static with a linkage specified, then we need to handle
         // it a little specially. The typesystem prevents things like &T and
         // extern "C" fn() from being non-null, so we can't just declare a
@@ -166,7 +167,16 @@ pub fn register_static(ccx: &CrateContext,
         }
         None => // Generate an external declaration.
             declare::declare_global(ccx, &ident[..], llty),
+    };
+
+    // Handle thread-local external statics.
+    for attr in foreign_item.attrs.iter() {
+        if attr.check_name("thread_local") {
+            llvm::set_thread_local(c, true);
+        }
     }
+
+    return c;
 }
 
 // only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index 188fb7de9dd..b7b520f6c82 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -678,49 +678,54 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         // "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
         (_, name) if name.starts_with("atomic_") => {
             let split: Vec<&str> = name.split('_').collect();
-            assert!(split.len() >= 2, "Atomic intrinsic not correct format");
 
-            let order = if split.len() == 2 {
-                llvm::SequentiallyConsistent
-            } else {
-                match split[2] {
-                    "unordered" => llvm::Unordered,
-                    "relaxed" => llvm::Monotonic,
-                    "acq"     => llvm::Acquire,
-                    "rel"     => llvm::Release,
-                    "acqrel"  => llvm::AcquireRelease,
+            let (order, failorder) = match split.len() {
+                2 => (llvm::SequentiallyConsistent, llvm::SequentiallyConsistent),
+                3 => match split[2] {
+                    "unordered" => (llvm::Unordered, llvm::Unordered),
+                    "relaxed" => (llvm::Monotonic, llvm::Monotonic),
+                    "acq"     => (llvm::Acquire, llvm::Acquire),
+                    "rel"     => (llvm::Release, llvm::Monotonic),
+                    "acqrel"  => (llvm::AcquireRelease, llvm::Acquire),
+                    "failrelaxed" if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+                        (llvm::SequentiallyConsistent, llvm::Monotonic),
+                    "failacq" if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+                        (llvm::SequentiallyConsistent, llvm::Acquire),
                     _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
-                }
+                },
+                4 => match (split[2], split[3]) {
+                    ("acq", "failrelaxed") if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+                        (llvm::Acquire, llvm::Monotonic),
+                    ("acqrel", "failrelaxed") if split[1] == "cxchg" || split[1] == "cxchgweak" =>
+                        (llvm::AcquireRelease, llvm::Monotonic),
+                    _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
+                },
+                _ => ccx.sess().fatal("Atomic intrinsic not in correct format"),
             };
 
             match split[1] {
                 "cxchg" => {
-                    // See include/llvm/IR/Instructions.h for their implementation
-                    // of this, I assume that it's good enough for us to use for
-                    // now.
-                    let strongest_failure_ordering = match order {
-                        llvm::NotAtomic | llvm::Unordered =>
-                            ccx.sess().fatal("cmpxchg must be atomic"),
-
-                        llvm::Monotonic | llvm::Release =>
-                            llvm::Monotonic,
-
-                        llvm::Acquire | llvm::AcquireRelease =>
-                            llvm::Acquire,
-
-                        llvm::SequentiallyConsistent =>
-                            llvm::SequentiallyConsistent
-                    };
-
                     let tp_ty = *substs.types.get(FnSpace, 0);
                     let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
                     let cmp = from_arg_ty(bcx, llargs[1], tp_ty);
                     let src = from_arg_ty(bcx, llargs[2], tp_ty);
-                    let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
-                                            strongest_failure_ordering);
+                    let res = AtomicCmpXchg(bcx, ptr, cmp, src, order, failorder, llvm::False);
                     ExtractValue(bcx, res, 0)
                 }
 
+                "cxchgweak" => {
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    let cmp = from_arg_ty(bcx, llargs[1], tp_ty);
+                    let src = from_arg_ty(bcx, llargs[2], tp_ty);
+                    let val = AtomicCmpXchg(bcx, ptr, cmp, src, order, failorder, llvm::True);
+                    let result = ExtractValue(bcx, val, 0);
+                    let success = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
+                    Store(bcx, result, StructGEP(bcx, llresult, 0));
+                    Store(bcx, success, StructGEP(bcx, llresult, 1));
+                    C_nil(ccx)
+                }
+
                 "load" => {
                     let tp_ty = *substs.types.get(FnSpace, 0);
                     let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index 875f09c02e8..609f1dee98a 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use llvm::{BasicBlockRef, ValueRef};
-use rustc::middle::ty;
+use llvm::{BasicBlockRef, ValueRef, OperandBundleDef};
+use rustc::middle::ty::{self, Ty};
 use rustc::mir::repr as mir;
 use syntax::abi::Abi;
 use trans::adt;
@@ -26,14 +26,73 @@ use trans::type_::Type;
 
 use super::MirContext;
 use super::operand::OperandValue::{FatPtr, Immediate, Ref};
+use super::operand::OperandRef;
+
+#[derive(PartialEq, Eq)]
+enum AbiStyle {
+    Foreign,
+    RustCall,
+    Rust
+}
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
+    fn abi_style(&self, fn_ty: Ty<'tcx>) -> AbiStyle {
+        if let ty::TyBareFn(_, ref f) = fn_ty.sty {
+            // We do not translate intrinsics here (they shouldn’t be functions)
+            assert!(f.abi != Abi::RustIntrinsic && f.abi != Abi::PlatformIntrinsic);
+
+            match f.abi {
+                Abi::Rust => AbiStyle::Rust,
+                Abi::RustCall => AbiStyle::RustCall,
+                _ => AbiStyle::Foreign
+            }
+        } else {
+            unreachable!()
+        }
+    }
+
+    fn arg_operands(&mut self,
+                    bcx: &BlockAndBuilder<'bcx, 'tcx>,
+                    abi_style: AbiStyle,
+                    args: &[mir::Operand<'tcx>])
+                    -> Vec<OperandRef<'tcx>>
+    {
+        match abi_style {
+            AbiStyle::Foreign | AbiStyle::Rust => {
+                args.iter().map(|arg| self.trans_operand(bcx, arg)).collect()
+            }
+            AbiStyle::RustCall => match args.split_last() {
+                None => vec![],
+                Some((tup, self_ty)) => {
+                    // we can reorder safely because of MIR
+                    let untupled_args = self.trans_operand_untupled(bcx, tup);
+                    self_ty
+                        .iter().map(|arg| self.trans_operand(bcx, arg))
+                        .chain(untupled_args.into_iter())
+                        .collect()
+                }
+            }
+        }
+    }
+
     pub fn trans_block(&mut self, bb: mir::BasicBlock) {
         debug!("trans_block({:?})", bb);
 
         let mut bcx = self.bcx(bb);
         let data = self.mir.basic_block_data(bb);
 
+        // MSVC SEH bits
+        let (cleanup_pad, cleanup_bundle) = if let Some((cp, cb)) = self.make_cleanup_pad(bb) {
+            (Some(cp), Some(cb))
+        } else {
+            (None, None)
+        };
+        let funclet_br = |bcx: BlockAndBuilder, llbb: BasicBlockRef| if let Some(cp) = cleanup_pad {
+            bcx.cleanup_ret(cp, Some(llbb));
+        } else {
+            bcx.br(llbb);
+        };
+
         for statement in &data.statements {
             bcx = self.trans_statement(bcx, statement);
         }
@@ -41,8 +100,21 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
         debug!("trans_block: terminator: {:?}", data.terminator());
 
         match *data.terminator() {
+            mir::Terminator::Resume => {
+                if let Some(cleanup_pad) = cleanup_pad {
+                    bcx.cleanup_ret(cleanup_pad, None);
+                } else {
+                    let ps = self.get_personality_slot(&bcx);
+                    let lp = bcx.load(ps);
+                    bcx.with_block(|bcx| {
+                        base::call_lifetime_end(bcx, ps);
+                        base::trans_unwind_resume(bcx, lp);
+                    });
+                }
+            }
+
             mir::Terminator::Goto { target } => {
-                bcx.br(self.llblock(target));
+                funclet_br(bcx, self.llblock(target));
             }
 
             mir::Terminator::If { ref cond, targets: (true_bb, false_bb) } => {
@@ -85,19 +157,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 }
             }
 
-            mir::Terminator::Resume => {
-                let ps = self.get_personality_slot(&bcx);
-                let lp = bcx.load(ps);
-                bcx.with_block(|bcx| {
-                    base::call_lifetime_end(bcx, ps);
-                    base::trans_unwind_resume(bcx, lp);
-                });
-            }
-
             mir::Terminator::Return => {
                 let return_ty = bcx.monomorphize(&self.mir.return_ty);
                 bcx.with_block(|bcx| {
-                    base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
+                    base::build_return_block(self.fcx, bcx, return_ty, DebugLoc::None);
                 })
             }
 
@@ -106,7 +169,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let ty = lvalue.ty.to_ty(bcx.tcx());
                 // Double check for necessity to drop
                 if !glue::type_needs_drop(bcx.tcx(), ty) {
-                    bcx.br(self.llblock(target));
+                    funclet_br(bcx, self.llblock(target));
                     return;
                 }
                 let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
@@ -123,11 +186,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                &[llvalue],
                                self.llblock(target),
                                unwind.llbb(),
-                               None,
+                               cleanup_bundle.as_ref(),
                                None);
                 } else {
-                    bcx.call(drop_fn, &[llvalue], None, None);
-                    bcx.br(self.llblock(target));
+                    bcx.call(drop_fn, &[llvalue], cleanup_bundle.as_ref(), None);
+                    funclet_br(bcx, self.llblock(target));
                 }
             }
 
@@ -143,13 +206,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let mut arg_tys = Vec::new();
 
                 // Foreign-ABI functions are translated differently
-                let is_foreign = if let ty::TyBareFn(_, ref f) = callee.ty.sty {
-                    // We do not translate intrinsics here (they shouldn’t be functions)
-                    assert!(f.abi != Abi::RustIntrinsic && f.abi != Abi::PlatformIntrinsic);
-                    f.abi != Abi::Rust && f.abi != Abi::RustCall
-                } else {
-                    false
-                };
+                let abi_style = self.abi_style(callee.ty);
+                let is_foreign = abi_style == AbiStyle::Foreign;
 
                 // Prepare the return value destination
                 let (ret_dest_ty, must_copy_dest) = if let Some((ref d, _)) = *destination {
@@ -166,8 +224,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 };
 
                 // Process the rest of the args.
-                for arg in args {
-                    let operand = self.trans_operand(&bcx, arg);
+                for operand in self.arg_operands(&bcx, abi_style, args) {
                     match operand.val {
                         Ref(llval) | Immediate(llval) => llargs.push(llval),
                         FatPtr(b, e) => {
@@ -180,11 +237,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     }
                 }
 
-                let avoid_invoke = bcx.with_block(|bcx| base::avoid_invoke(bcx));
                 // Many different ways to call a function handled here
-                match (is_foreign, avoid_invoke, cleanup, destination) {
+                match (is_foreign, cleanup, destination) {
                     // The two cases below are the only ones to use LLVM’s `invoke`.
-                    (false, false, &Some(cleanup), &None) => {
+                    (false, &Some(cleanup), &None) => {
                         let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         let unreachable_blk = self.unreachable_block();
@@ -192,14 +248,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                    &llargs[..],
                                    unreachable_blk.llbb,
                                    landingpad.llbb(),
-                                   None,
+                                   cleanup_bundle.as_ref(),
                                    Some(attrs));
                     },
-                    (false, false, &Some(cleanup), &Some((_, success))) => {
+                    (false, &Some(cleanup), &Some((_, success))) => {
                         let cleanup = self.bcx(cleanup);
                         let landingpad = self.make_landing_pad(cleanup);
                         let (target, postinvoke) = if must_copy_dest {
-                            (bcx.fcx().new_block("", None).build(), Some(self.bcx(success)))
+                            (self.fcx.new_block("", None).build(), Some(self.bcx(success)))
                         } else {
                             (self.bcx(success), None)
                         };
@@ -207,7 +263,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                                    &llargs[..],
                                                    target.llbb(),
                                                    landingpad.llbb(),
-                                                   None,
+                                                   cleanup_bundle.as_ref(),
                                                    Some(attrs));
                         if let Some(postinvoketarget) = postinvoke {
                             // We translate the copy into a temporary block. The temporary block is
@@ -242,14 +298,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             target.br(postinvoketarget.llbb());
                         }
                     },
-                    (false, _, _, &None) => {
-                        bcx.call(callee.immediate(), &llargs[..], None, Some(attrs));
+                    (false, _, &None) => {
+                        bcx.call(callee.immediate(),
+                                 &llargs[..],
+                                 cleanup_bundle.as_ref(),
+                                 Some(attrs));
                         bcx.unreachable();
                     }
-                    (false, _, _, &Some((_, target))) => {
+                    (false, _, &Some((_, target))) => {
                         let llret = bcx.call(callee.immediate(),
                                              &llargs[..],
-                                             None,
+                                             cleanup_bundle.as_ref(),
                                              Some(attrs));
                         if must_copy_dest {
                             let (ret_dest, ret_ty) = ret_dest_ty
@@ -258,10 +317,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                 base::store_ty(bcx, llret, ret_dest.llval, ret_ty);
                             });
                         }
-                        bcx.br(self.llblock(target));
+                        funclet_br(bcx, self.llblock(target));
                     }
                     // Foreign functions
-                    (true, _, _, destination) => {
+                    (true, _, destination) => {
                         let (dest, _) = ret_dest_ty
                             .expect("return destination is not set");
                         bcx = bcx.map_block(|bcx| {
@@ -274,7 +333,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                                        debugloc)
                         });
                         if let Some((_, target)) = *destination {
-                            bcx.br(self.llblock(target));
+                            funclet_br(bcx, self.llblock(target));
                         }
                     },
                 }
@@ -297,11 +356,16 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
         }
     }
 
+    /// Create a landingpad wrapper around the given Block.
+    ///
+    /// No-op in MSVC SEH scheme.
     fn make_landing_pad(&mut self,
                         cleanup: BlockAndBuilder<'bcx, 'tcx>)
                         -> BlockAndBuilder<'bcx, 'tcx>
     {
-        // FIXME(#30941) this doesn't handle msvc-style exceptions
+        if base::wants_msvc_seh(cleanup.sess()) {
+            return cleanup;
+        }
         let bcx = self.fcx.new_block("cleanup", None).build();
         let ccx = bcx.ccx();
         let llpersonality = self.fcx.eh_personality();
@@ -314,6 +378,31 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
         bcx
     }
 
+    /// Create prologue cleanuppad instruction under MSVC SEH handling scheme.
+    ///
+    /// Also handles setting some state for the original trans and creating an operand bundle for
+    /// function calls.
+    fn make_cleanup_pad(&mut self, bb: mir::BasicBlock) -> Option<(ValueRef, OperandBundleDef)> {
+        let bcx = self.bcx(bb);
+        let data = self.mir.basic_block_data(bb);
+        let use_funclets = base::wants_msvc_seh(bcx.sess()) && data.is_cleanup;
+        let cleanup_pad = if use_funclets {
+            bcx.set_personality_fn(self.fcx.eh_personality());
+            Some(bcx.cleanup_pad(None, &[]))
+        } else {
+            None
+        };
+        // Set the landingpad global-state for old translator, so it knows about the SEH used.
+        bcx.set_lpad(if let Some(cleanup_pad) = cleanup_pad {
+            Some(common::LandingPad::msvc(cleanup_pad))
+        } else if data.is_cleanup {
+            Some(common::LandingPad::gnu())
+        } else {
+            None
+        });
+        cleanup_pad.map(|f| (f, OperandBundleDef::new("funclet", &[f])))
+    }
+
     fn unreachable_block(&mut self) -> Block<'bcx, 'tcx> {
         self.unreachable_block.unwrap_or_else(|| {
             let bl = self.fcx.new_block("unreachable", None);
diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs
index 002584f51c6..826fb025bc1 100644
--- a/src/librustc_trans/trans/mir/lvalue.rs
+++ b/src/librustc_trans/trans/mir/lvalue.rs
@@ -126,7 +126,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             }
                         })
                     }
-                    mir::ProjectionElem::Field(ref field) => {
+                    mir::ProjectionElem::Field(ref field, _) => {
                         let base_ty = tr_base.ty.to_ty(tcx);
                         let base_repr = adt::represent_type(ccx, base_ty);
                         let discr = match tr_base.ty {
diff --git a/src/librustc_trans/trans/mir/operand.rs b/src/librustc_trans/trans/mir/operand.rs
index d0eaaeef057..2183348c8b5 100644
--- a/src/librustc_trans/trans/mir/operand.rs
+++ b/src/librustc_trans/trans/mir/operand.rs
@@ -9,13 +9,16 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use rustc::middle::ty::{Ty, TypeFoldable};
+use rustc::middle::ty::{self, Ty};
 use rustc::mir::repr as mir;
+use trans::adt;
 use trans::base;
 use trans::common::{self, Block, BlockAndBuilder};
 use trans::datum;
+use trans::Disr;
 
 use super::{MirContext, TempRef};
+use super::lvalue::LvalueRef;
 
 /// The representation of a Rust value. The enum variant is in fact
 /// uniquely determined by the value's type, but is kept as a
@@ -90,6 +93,32 @@ impl<'tcx> OperandRef<'tcx> {
 }
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
+    pub fn trans_load(&mut self,
+                      bcx: &BlockAndBuilder<'bcx, 'tcx>,
+                      llval: ValueRef,
+                      ty: Ty<'tcx>)
+                      -> OperandRef<'tcx>
+    {
+        debug!("trans_load: {} @ {:?}", bcx.val_to_string(llval), ty);
+
+        let val = match datum::appropriate_rvalue_mode(bcx.ccx(), ty) {
+            datum::ByValue => {
+                bcx.with_block(|bcx| {
+                    OperandValue::Immediate(base::load_ty(bcx, llval, ty))
+                })
+            }
+            datum::ByRef if common::type_is_fat_ptr(bcx.tcx(), ty) => {
+                let (lldata, llextra) = bcx.with_block(|bcx| {
+                    base::load_fat_ptr(bcx, llval, ty)
+                });
+                OperandValue::FatPtr(lldata, llextra)
+            }
+            datum::ByRef => OperandValue::Ref(llval)
+        };
+
+        OperandRef { val: val, ty: ty }
+    }
+
     pub fn trans_operand(&mut self,
                          bcx: &BlockAndBuilder<'bcx, 'tcx>,
                          operand: &mir::Operand<'tcx>)
@@ -120,30 +149,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 // out from their home
                 let tr_lvalue = self.trans_lvalue(bcx, lvalue);
                 let ty = tr_lvalue.ty.to_ty(bcx.tcx());
-                debug!("trans_operand: tr_lvalue={} @ {:?}",
-                       bcx.val_to_string(tr_lvalue.llval),
-                       ty);
-                let val = match datum::appropriate_rvalue_mode(bcx.ccx(), ty) {
-                    datum::ByValue => {
-                        bcx.with_block(|bcx| {
-                            OperandValue::Immediate(base::load_ty(bcx, tr_lvalue.llval, ty))
-                        })
-                    }
-                    datum::ByRef if common::type_is_fat_ptr(bcx.tcx(), ty) => {
-                        let (lldata, llextra) = bcx.with_block(|bcx| {
-                            base::load_fat_ptr(bcx, tr_lvalue.llval, ty)
-                        });
-                        OperandValue::FatPtr(lldata, llextra)
-                    }
-                    datum::ByRef => OperandValue::Ref(tr_lvalue.llval)
-                };
-
-                assert!(!ty.has_erasable_regions());
-
-                OperandRef {
-                    val: val,
-                    ty: ty
-                }
+                self.trans_load(bcx, tr_lvalue.llval, ty)
             }
 
             mir::Operand::Constant(ref constant) => {
@@ -197,4 +203,46 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
             }
         }
     }
+
+    pub fn trans_operand_untupled(&mut self,
+                                  bcx: &BlockAndBuilder<'bcx, 'tcx>,
+                                  operand: &mir::Operand<'tcx>)
+                                  -> Vec<OperandRef<'tcx>>
+    {
+        // FIXME: consider having some optimization to avoid tupling/untupling
+        // (and storing/loading in the case of immediates)
+
+        // avoid trans_operand for pointless copying
+        let lv = match *operand {
+            mir::Operand::Consume(ref lvalue) => self.trans_lvalue(bcx, lvalue),
+            mir::Operand::Constant(ref constant) => {
+                // FIXME: consider being less pessimized
+                if constant.ty.is_nil() {
+                    return vec![];
+                }
+
+                let ty = bcx.monomorphize(&constant.ty);
+                let lv = LvalueRef::alloca(bcx, ty, "__untuple_alloca");
+                let constant = self.trans_constant(bcx, constant);
+                self.store_operand(bcx, lv.llval, constant);
+                lv
+           }
+        };
+
+        let lv_ty = lv.ty.to_ty(bcx.tcx());
+        let result_types = match lv_ty.sty {
+            ty::TyTuple(ref tys) => tys,
+            _ => bcx.tcx().sess.span_bug(
+                self.mir.span,
+                &format!("bad final argument to \"rust-call\" fn {:?}", lv_ty))
+        };
+
+        let base_repr = adt::represent_type(bcx.ccx(), lv_ty);
+        let base = adt::MaybeSizedValue::sized(lv.llval);
+        result_types.iter().enumerate().map(|(n, &ty)| {
+            self.trans_load(bcx, bcx.with_block(|bcx| {
+                adt::trans_field_ptr(bcx, &base_repr, base, Disr(0), n)
+            }), ty)
+        }).collect()
+    }
 }
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 0f88269a2c9..24a7fd372f6 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -182,9 +182,8 @@ pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>)
 //     recursive types. For example, enum types rely on this behavior.
 
 pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    match cx.llsizingtypes().borrow().get(&t).cloned() {
-        Some(t) => return t,
-        None => ()
+    if let Some(t) = cx.llsizingtypes().borrow().get(&t).cloned() {
+        return t;
     }
 
     debug!("sizing_type_of {:?}", t);
@@ -317,9 +316,8 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
 /// NB: If you update this, be sure to update `sizing_type_of()` as well.
 pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     // Check the cache.
-    match cx.lltypes().borrow().get(&t) {
-        Some(&llty) => return llty,
-        None => ()
+    if let Some(&llty) = cx.lltypes().borrow().get(&t) {
+        return llty;
     }
 
     debug!("type_of {:?}", t);
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 6ca48f2d8d4..bd2c7b39153 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -30,7 +30,7 @@ use syntax::ast;
 use syntax::codemap::{Span, Spanned};
 use syntax::ptr::P;
 
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::print::pprust;
 use rustc_front::util as hir_util;
 
@@ -46,10 +46,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
            expected);
 
     match pat.node {
-        hir::PatWild => {
+        PatKind::Wild => {
             fcx.write_ty(pat.id, expected);
         }
-        hir::PatLit(ref lt) => {
+        PatKind::Lit(ref lt) => {
             check_expr(fcx, &lt);
             let expr_ty = fcx.expr_ty(&lt);
 
@@ -84,7 +84,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             // that's equivalent to there existing a LUB.
             demand::suptype(fcx, pat.span, expected, pat_ty);
         }
-        hir::PatRange(ref begin, ref end) => {
+        PatKind::Range(ref begin, ref end) => {
             check_expr(fcx, begin);
             check_expr(fcx, end);
 
@@ -135,14 +135,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             // subtyping doesn't matter here, as the value is some kind of scalar
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
         }
-        hir::PatEnum(..) | hir::PatIdent(..)
+        PatKind::Path(..) | PatKind::Ident(..)
                 if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
-            if let hir::PatEnum(ref path, ref subpats) = pat.node {
-                if !(subpats.is_some() && subpats.as_ref().unwrap().is_empty()) {
-                    bad_struct_kind_err(tcx.sess, pat, path, false);
-                    return;
-                }
-            }
             if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) {
                 let const_did = pat_def.def_id();
                 let const_scheme = tcx.lookup_item_type(const_did);
@@ -154,7 +148,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
                 // FIXME(#20489) -- we should limit the types here to scalars or something!
 
-                // As with PatLit, what we really want here is that there
+                // As with PatKind::Lit, what we really want here is that there
                 // exist a LUB, but for the cases that can occur, subtype
                 // is good enough.
                 demand::suptype(fcx, pat.span, expected, const_ty);
@@ -162,7 +156,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 fcx.write_error(pat.id);
             }
         }
-        hir::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => {
+        PatKind::Ident(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map.borrow(), pat) => {
             let typ = fcx.local_ty(pat.span, pat.id);
             match bm {
                 hir::BindByRef(mutbl) => {
@@ -202,16 +196,17 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 }
             }
         }
-        hir::PatIdent(_, ref path, _) => {
+        PatKind::Ident(_, ref path, _) => {
             let path = hir_util::ident_to_path(path.span, path.node);
             check_pat_enum(pcx, pat, &path, Some(&[]), expected, false);
         }
-        hir::PatEnum(ref path, ref subpats) => {
-            let subpats = subpats.as_ref().map(|v| &v[..]);
-            let is_tuple_struct_pat = !(subpats.is_some() && subpats.unwrap().is_empty());
-            check_pat_enum(pcx, pat, path, subpats, expected, is_tuple_struct_pat);
+        PatKind::TupleStruct(ref path, ref subpats) => {
+            check_pat_enum(pcx, pat, path, subpats.as_ref().map(|v| &v[..]), expected, true);
+        }
+        PatKind::Path(ref path) => {
+            check_pat_enum(pcx, pat, path, None, expected, false);
         }
-        hir::PatQPath(ref qself, ref path) => {
+        PatKind::QPath(ref qself, ref path) => {
             let self_ty = fcx.to_ty(&qself.ty);
             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
                 if d.base_def == Def::Err {
@@ -248,10 +243,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 }
             }
         }
-        hir::PatStruct(ref path, ref fields, etc) => {
+        PatKind::Struct(ref path, ref fields, etc) => {
             check_pat_struct(pcx, pat, path, fields, etc, expected);
         }
-        hir::PatTup(ref elements) => {
+        PatKind::Tup(ref elements) => {
             let element_tys: Vec<_> =
                 (0..elements.len()).map(|_| fcx.infcx().next_ty_var())
                                         .collect();
@@ -262,7 +257,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &element_pat, element_ty);
             }
         }
-        hir::PatBox(ref inner) => {
+        PatKind::Box(ref inner) => {
             let inner_ty = fcx.infcx().next_ty_var();
             let uniq_ty = tcx.mk_box(inner_ty);
 
@@ -278,7 +273,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &inner, tcx.types.err);
             }
         }
-        hir::PatRegion(ref inner, mutbl) => {
+        PatKind::Ref(ref inner, mutbl) => {
             let expected = fcx.infcx().shallow_resolve(expected);
             if check_dereferencable(pcx, pat.span, expected, &inner) {
                 // `demand::subtype` would be good enough, but using
@@ -310,7 +305,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &inner, tcx.types.err);
             }
         }
-        hir::PatVec(ref before, ref slice, ref after) => {
+        PatKind::Vec(ref before, ref slice, ref after) => {
             let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
             let inner_ty = fcx.infcx().next_ty_var();
             let pat_ty = match expected_ty.sty {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 8f64e85de4b..f07464592fa 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -67,7 +67,7 @@ use middle::traits::{self, ObligationCause};
 use middle::traits::{predicate_for_trait_def, report_selection_error};
 use middle::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
 use middle::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
-use middle::ty::adjustment::{AdjustUnsafeFnPointer};
+use middle::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
 use middle::ty::{self, LvaluePreference, TypeAndMut, Ty};
 use middle::ty::fold::TypeFoldable;
 use middle::ty::error::TypeError;
@@ -427,6 +427,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 autoref: Some(AutoUnsafe(mutbl_b)),
                 unsize: None
             })))
+        } else if mt_a.mutbl != mutbl_b {
+            Ok(Some(AdjustMutToConstPointer))
         } else {
             Ok(None)
         }
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index ba6fa9aed3d..5e1dc35870b 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -83,6 +83,10 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
                                 param(ccx, 0),
                                 param(ccx, 0)),
                         param(ccx, 0)),
+            "cxchgweak" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)),
+                                param(ccx, 0),
+                                param(ccx, 0)),
+                            tcx.mk_tup(vec!(param(ccx, 0), tcx.types.bool))),
             "load" => (1, vec!(tcx.mk_imm_ptr(param(ccx, 0))),
                        param(ccx, 0)),
             "store" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 1367db16314..e7d84efdaa2 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -271,7 +271,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
         for (i, trait_did) in candidates.iter().enumerate() {
             err.fileline_help(span,
-                              &format!("candidate #{}: use `{}`",
+                              &format!("candidate #{}: `use {}`",
                                         i + 1,
                                         fcx.tcx().item_path_str(*trait_did)));
         }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f890e087573..7b2e678499b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -127,7 +127,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
 
 use rustc_front::intravisit::{self, Visitor};
 use rustc_front::hir;
-use rustc_front::hir::Visibility;
+use rustc_front::hir::{Visibility, PatKind};
 use rustc_front::print::pprust;
 use rustc_back::slice;
 
@@ -506,7 +506,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
 
     // Add pattern bindings.
     fn visit_pat(&mut self, p: &'tcx hir::Pat) {
-        if let hir::PatIdent(_, ref path1, _) = p.node {
+        if let PatKind::Ident(_, ref path1, _) = p.node {
             if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map.borrow(), p) {
                 let var_ty = self.assign(p.span, p.id, None);
 
@@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Return the dict-like variant corresponding to a given `Def`.
     pub fn def_struct_variant(&self,
                               def: Def,
-                              span: Span)
+                              _span: Span)
                               -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
     {
         let (adt, variant) = match def {
@@ -1441,15 +1441,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if var_kind == ty::VariantKind::Struct {
             Some((adt, variant))
         } else if var_kind == ty::VariantKind::Unit {
-            if !self.tcx().sess.features.borrow().braced_empty_structs {
-                let mut err = self.tcx().sess.struct_span_err(span,
-                                                              "empty structs and enum variants \
-                                                               with braces are unstable");
-                fileline_help!(&mut err, span, "add #![feature(braced_empty_structs)] to \
-                                                the crate features to enable");
-                err.emit();
-            }
-
              Some((adt, variant))
          } else {
              None
@@ -3179,8 +3170,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             check_struct_fields_on_error(fcx, expr.id, fields, base_expr);
             return;
         }
-        let (adt, variant) = match fcx.def_struct_variant(def, path.span) {
-            Some((adt, variant)) => (adt, variant),
+        let variant = match fcx.def_struct_variant(def, path.span) {
+            Some((_, variant)) => variant,
             None => {
                 span_err!(fcx.tcx().sess, path.span, E0071,
                           "`{}` does not name a structure",
@@ -3195,12 +3186,23 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         check_expr_struct_fields(fcx, expr_ty, expr.span, variant, fields,
                                  base_expr.is_none());
-
         if let &Some(ref base_expr) = base_expr {
             check_expr_has_type(fcx, base_expr, expr_ty);
-            if adt.adt_kind() == ty::AdtKind::Enum {
-                span_err!(tcx.sess, base_expr.span, E0436,
-                          "functional record update syntax requires a struct");
+            match expr_ty.sty {
+                ty::TyStruct(adt, substs) => {
+                    fcx.inh.tables.borrow_mut().fru_field_types.insert(
+                        expr.id,
+                        adt.struct_variant().fields.iter().map(|f| {
+                            fcx.normalize_associated_types_in(
+                                expr.span, &f.ty(tcx, substs)
+                            )
+                        }).collect()
+                    );
+                }
+                _ => {
+                    span_err!(tcx.sess, base_expr.span, E0436,
+                              "functional record update syntax requires a struct");
+                }
             }
         }
     }
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 2335b76626b..e399818779e 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -101,7 +101,7 @@ use std::mem;
 use syntax::ast;
 use syntax::codemap::Span;
 use rustc_front::intravisit::{self, Visitor};
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::util as hir_util;
 
 use self::SubjectNode::Subject;
@@ -1190,14 +1190,14 @@ fn link_pattern<'t, 'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
     let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
             match sub_pat.node {
                 // `ref x` pattern
-                hir::PatIdent(hir::BindByRef(mutbl), _, _) => {
+                PatKind::Ident(hir::BindByRef(mutbl), _, _) => {
                     link_region_from_node_type(
                         rcx, sub_pat.span, sub_pat.id,
                         mutbl, sub_cmt);
                 }
 
                 // `[_, ..slice, _]` pattern
-                hir::PatVec(_, Some(ref slice_pat), _) => {
+                PatKind::Vec(_, Some(ref slice_pat), _) => {
                     match mc.cat_slice_pattern(sub_cmt, &slice_pat) {
                         Ok((slice_cmt, slice_mutbl, slice_r)) => {
                             link_region(rcx, sub_pat.span, &slice_r,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index e663e449cfc..a28944995c4 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -43,6 +43,7 @@ pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &hir::Expr) {
     wbcx.visit_upvar_borrow_map();
     wbcx.visit_closures();
     wbcx.visit_liberated_fn_sigs();
+    wbcx.visit_fru_field_types();
 }
 
 pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
@@ -64,6 +65,7 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
     wbcx.visit_upvar_borrow_map();
     wbcx.visit_closures();
     wbcx.visit_liberated_fn_sigs();
+    wbcx.visit_fru_field_types();
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -119,25 +121,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                         },
                         _ => {},
                     }
-                } else {
-                    let tcx = self.tcx();
-
-                    if let hir::ExprAssignOp(_, ref lhs, ref rhs) = e.node {
-                        if
-                            !tcx.sess.features.borrow().augmented_assignments &&
-                            !self.fcx.expr_ty(e).references_error() &&
-                            !self.fcx.expr_ty(lhs).references_error() &&
-                            !self.fcx.expr_ty(rhs).references_error()
-                        {
-                            tcx.sess.struct_span_err(e.span,
-                                                     "overloaded augmented assignments \
-                                                      are not stable")
-                                .fileline_help(e.span,
-                                               "add #![feature(augmented_assignments)] to the \
-                                                crate root to enable")
-                                .emit()
-                        }
-                    }
                 }
             }
             _ => {},
@@ -305,6 +288,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                         adjustment::AdjustReifyFnPointer
                     }
 
+                    adjustment::AdjustMutToConstPointer => {
+                        adjustment::AdjustMutToConstPointer
+                    }
+
                     adjustment::AdjustUnsafeFnPointer => {
                         adjustment::AdjustUnsafeFnPointer
                     }
@@ -367,6 +354,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
+    fn visit_fru_field_types(&self) {
+        for (&node_id, ftys) in self.fcx.inh.tables.borrow().fru_field_types.iter() {
+            let ftys = self.resolve(ftys, ResolvingFieldTypes(node_id));
+            self.tcx().tables.borrow_mut().fru_field_types.insert(node_id, ftys);
+        }
+    }
+
     fn resolve<T:TypeFoldable<'tcx>>(&self, t: &T, reason: ResolveReason) -> T {
         t.fold_with(&mut Resolver::new(self.fcx, reason))
     }
@@ -383,6 +377,7 @@ enum ResolveReason {
     ResolvingUpvar(ty::UpvarId),
     ResolvingClosure(DefId),
     ResolvingFnSig(ast::NodeId),
+    ResolvingFieldTypes(ast::NodeId)
 }
 
 impl ResolveReason {
@@ -397,6 +392,9 @@ impl ResolveReason {
             ResolvingFnSig(id) => {
                 tcx.map.span(id)
             }
+            ResolvingFieldTypes(id) => {
+                tcx.map.span(id)
+            }
             ResolvingClosure(did) => {
                 if let Some(node_id) = tcx.map.as_local_node_id(did) {
                     tcx.expr_span(node_id)
@@ -474,14 +472,14 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
                               "cannot determine a type for this closure")
                 }
 
-                ResolvingFnSig(id) => {
+                ResolvingFnSig(id) | ResolvingFieldTypes(id) => {
                     // any failures here should also fail when
                     // resolving the patterns, closure types, or
                     // something else.
                     let span = self.reason.span(self.tcx);
                     self.tcx.sess.delay_span_bug(
                         span,
-                        &format!("cannot resolve some aspect of fn sig for {:?}", id));
+                        &format!("cannot resolve some aspect of data for {:?}", id));
                 }
             }
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index cae2d9d890d..026881927cb 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -90,7 +90,7 @@ use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token::special_idents;
 use syntax::ptr::P;
-use rustc_front::hir;
+use rustc_front::hir::{self, PatKind};
 use rustc_front::intravisit;
 use rustc_front::print::pprust;
 
@@ -2121,8 +2121,8 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
 {
     for i in &decl.inputs {
         match i.pat.node {
-            hir::PatIdent(_, _, _) => (),
-            hir::PatWild => (),
+            PatKind::Ident(_, _, _) => (),
+            PatKind::Wild => (),
             _ => {
                 span_err!(ccx.tcx.sess, i.pat.span, E0130,
                           "patterns aren't allowed in foreign function declarations");
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 0c8ad5abe6f..0835762c4e5 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -81,7 +81,6 @@ This API is completely unstable and subject to change.
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(cell_extras)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs
deleted file mode 100644
index ce0e9e14035..00000000000
--- a/src/librustc_typeck/variance.rs
+++ /dev/null
@@ -1,1250 +0,0 @@
-// Copyright 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.
-
-//! This file infers the variance of type and lifetime parameters. The
-//! algorithm is taken from Section 4 of the paper "Taming the Wildcards:
-//! Combining Definition- and Use-Site Variance" published in PLDI'11 and
-//! written by Altidor et al., and hereafter referred to as The Paper.
-//!
-//! This inference is explicitly designed *not* to consider the uses of
-//! types within code. To determine the variance of type parameters
-//! defined on type `X`, we only consider the definition of the type `X`
-//! and the definitions of any types it references.
-//!
-//! We only infer variance for type parameters found on *data types*
-//! like structs and enums. In these cases, there is fairly straightforward
-//! explanation for what variance means. The variance of the type
-//! or lifetime parameters defines whether `T<A>` is a subtype of `T<B>`
-//! (resp. `T<'a>` and `T<'b>`) based on the relationship of `A` and `B`
-//! (resp. `'a` and `'b`).
-//!
-//! We do not infer variance for type parameters found on traits, fns,
-//! or impls. Variance on trait parameters can make indeed make sense
-//! (and we used to compute it) but it is actually rather subtle in
-//! meaning and not that useful in practice, so we removed it. See the
-//! addendum for some details. Variances on fn/impl parameters, otoh,
-//! doesn't make sense because these parameters are instantiated and
-//! then forgotten, they don't persist in types or compiled
-//! byproducts.
-//!
-//! ### The algorithm
-//!
-//! The basic idea is quite straightforward. We iterate over the types
-//! defined and, for each use of a type parameter X, accumulate a
-//! constraint indicating that the variance of X must be valid for the
-//! variance of that use site. We then iteratively refine the variance of
-//! X until all constraints are met. There is *always* a sol'n, because at
-//! the limit we can declare all type parameters to be invariant and all
-//! constraints will be satisfied.
-//!
-//! As a simple example, consider:
-//!
-//!     enum Option<A> { Some(A), None }
-//!     enum OptionalFn<B> { Some(|B|), None }
-//!     enum OptionalMap<C> { Some(|C| -> C), None }
-//!
-//! Here, we will generate the constraints:
-//!
-//!     1. V(A) <= +
-//!     2. V(B) <= -
-//!     3. V(C) <= +
-//!     4. V(C) <= -
-//!
-//! These indicate that (1) the variance of A must be at most covariant;
-//! (2) the variance of B must be at most contravariant; and (3, 4) the
-//! variance of C must be at most covariant *and* contravariant. All of these
-//! results are based on a variance lattice defined as follows:
-//!
-//!       *      Top (bivariant)
-//!    -     +
-//!       o      Bottom (invariant)
-//!
-//! Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the
-//! optimal solution. Note that there is always a naive solution which
-//! just declares all variables to be invariant.
-//!
-//! You may be wondering why fixed-point iteration is required. The reason
-//! is that the variance of a use site may itself be a function of the
-//! variance of other type parameters. In full generality, our constraints
-//! take the form:
-//!
-//!     V(X) <= Term
-//!     Term := + | - | * | o | V(X) | Term x Term
-//!
-//! Here the notation V(X) indicates the variance of a type/region
-//! parameter `X` with respect to its defining class. `Term x Term`
-//! represents the "variance transform" as defined in the paper:
-//!
-//!   If the variance of a type variable `X` in type expression `E` is `V2`
-//!   and the definition-site variance of the [corresponding] type parameter
-//!   of a class `C` is `V1`, then the variance of `X` in the type expression
-//!   `C<E>` is `V3 = V1.xform(V2)`.
-//!
-//! ### Constraints
-//!
-//! If I have a struct or enum with where clauses:
-//!
-//!     struct Foo<T:Bar> { ... }
-//!
-//! you might wonder whether the variance of `T` with respect to `Bar`
-//! affects the variance `T` with respect to `Foo`. I claim no.  The
-//! reason: assume that `T` is invariant w/r/t `Bar` but covariant w/r/t
-//! `Foo`. And then we have a `Foo<X>` that is upcast to `Foo<Y>`, where
-//! `X <: Y`. However, while `X : Bar`, `Y : Bar` does not hold.  In that
-//! case, the upcast will be illegal, but not because of a variance
-//! failure, but rather because the target type `Foo<Y>` is itself just
-//! not well-formed. Basically we get to assume well-formedness of all
-//! types involved before considering variance.
-//!
-//! ### Addendum: Variance on traits
-//!
-//! As mentioned above, we used to permit variance on traits. This was
-//! computed based on the appearance of trait type parameters in
-//! method signatures and was used to represent the compatibility of
-//! vtables in trait objects (and also "virtual" vtables or dictionary
-//! in trait bounds). One complication was that variance for
-//! associated types is less obvious, since they can be projected out
-//! and put to myriad uses, so it's not clear when it is safe to allow
-//! `X<A>::Bar` to vary (or indeed just what that means). Moreover (as
-//! covered below) all inputs on any trait with an associated type had
-//! to be invariant, limiting the applicability. Finally, the
-//! annotations (`MarkerTrait`, `PhantomFn`) needed to ensure that all
-//! trait type parameters had a variance were confusing and annoying
-//! for little benefit.
-//!
-//! Just for historical reference,I am going to preserve some text indicating
-//! how one could interpret variance and trait matching.
-//!
-//! #### Variance and object types
-//!
-//! Just as with structs and enums, we can decide the subtyping
-//! relationship between two object types `&Trait<A>` and `&Trait<B>`
-//! based on the relationship of `A` and `B`. Note that for object
-//! types we ignore the `Self` type parameter -- it is unknown, and
-//! the nature of dynamic dispatch ensures that we will always call a
-//! function that is expected the appropriate `Self` type. However, we
-//! must be careful with the other type parameters, or else we could
-//! end up calling a function that is expecting one type but provided
-//! another.
-//!
-//! To see what I mean, consider a trait like so:
-//!
-//!     trait ConvertTo<A> {
-//!         fn convertTo(&self) -> A;
-//!     }
-//!
-//! Intuitively, If we had one object `O=&ConvertTo<Object>` and another
-//! `S=&ConvertTo<String>`, then `S <: O` because `String <: Object`
-//! (presuming Java-like "string" and "object" types, my go to examples
-//! for subtyping). The actual algorithm would be to compare the
-//! (explicit) type parameters pairwise respecting their variance: here,
-//! the type parameter A is covariant (it appears only in a return
-//! position), and hence we require that `String <: Object`.
-//!
-//! You'll note though that we did not consider the binding for the
-//! (implicit) `Self` type parameter: in fact, it is unknown, so that's
-//! good. The reason we can ignore that parameter is precisely because we
-//! don't need to know its value until a call occurs, and at that time (as
-//! you said) the dynamic nature of virtual dispatch means the code we run
-//! will be correct for whatever value `Self` happens to be bound to for
-//! the particular object whose method we called. `Self` is thus different
-//! from `A`, because the caller requires that `A` be known in order to
-//! know the return type of the method `convertTo()`. (As an aside, we
-//! have rules preventing methods where `Self` appears outside of the
-//! receiver position from being called via an object.)
-//!
-//! #### Trait variance and vtable resolution
-//!
-//! But traits aren't only used with objects. They're also used when
-//! deciding whether a given impl satisfies a given trait bound. To set the
-//! scene here, imagine I had a function:
-//!
-//!     fn convertAll<A,T:ConvertTo<A>>(v: &[T]) {
-//!         ...
-//!     }
-//!
-//! Now imagine that I have an implementation of `ConvertTo` for `Object`:
-//!
-//!     impl ConvertTo<i32> for Object { ... }
-//!
-//! And I want to call `convertAll` on an array of strings. Suppose
-//! further that for whatever reason I specifically supply the value of
-//! `String` for the type parameter `T`:
-//!
-//!     let mut vector = vec!["string", ...];
-//!     convertAll::<i32, String>(vector);
-//!
-//! Is this legal? To put another way, can we apply the `impl` for
-//! `Object` to the type `String`? The answer is yes, but to see why
-//! we have to expand out what will happen:
-//!
-//! - `convertAll` will create a pointer to one of the entries in the
-//!   vector, which will have type `&String`
-//! - It will then call the impl of `convertTo()` that is intended
-//!   for use with objects. This has the type:
-//!
-//!       fn(self: &Object) -> i32
-//!
-//!   It is ok to provide a value for `self` of type `&String` because
-//!   `&String <: &Object`.
-//!
-//! OK, so intuitively we want this to be legal, so let's bring this back
-//! to variance and see whether we are computing the correct result. We
-//! must first figure out how to phrase the question "is an impl for
-//! `Object,i32` usable where an impl for `String,i32` is expected?"
-//!
-//! Maybe it's helpful to think of a dictionary-passing implementation of
-//! type classes. In that case, `convertAll()` takes an implicit parameter
-//! representing the impl. In short, we *have* an impl of type:
-//!
-//!     V_O = ConvertTo<i32> for Object
-//!
-//! and the function prototype expects an impl of type:
-//!
-//!     V_S = ConvertTo<i32> for String
-//!
-//! As with any argument, this is legal if the type of the value given
-//! (`V_O`) is a subtype of the type expected (`V_S`). So is `V_O <: V_S`?
-//! The answer will depend on the variance of the various parameters. In
-//! this case, because the `Self` parameter is contravariant and `A` is
-//! covariant, it means that:
-//!
-//!     V_O <: V_S iff
-//!         i32 <: i32
-//!         String <: Object
-//!
-//! These conditions are satisfied and so we are happy.
-//!
-//! #### Variance and associated types
-//!
-//! Traits with associated types -- or at minimum projection
-//! expressions -- must be invariant with respect to all of their
-//! inputs. To see why this makes sense, consider what subtyping for a
-//! trait reference means:
-//!
-//!    <T as Trait> <: <U as Trait>
-//!
-//! means that if I know that `T as Trait`, I also know that `U as
-//! Trait`. Moreover, if you think of it as dictionary passing style,
-//! it means that a dictionary for `<T as Trait>` is safe to use where
-//! a dictionary for `<U as Trait>` is expected.
-//!
-//! The problem is that when you can project types out from `<T as
-//! Trait>`, the relationship to types projected out of `<U as Trait>`
-//! is completely unknown unless `T==U` (see #21726 for more
-//! details). Making `Trait` invariant ensures that this is true.
-//!
-//! Another related reason is that if we didn't make traits with
-//! associated types invariant, then projection is no longer a
-//! function with a single result. Consider:
-//!
-//! ```
-//! trait Identity { type Out; fn foo(&self); }
-//! impl<T> Identity for T { type Out = T; ... }
-//! ```
-//!
-//! Now if I have `<&'static () as Identity>::Out`, this can be
-//! validly derived as `&'a ()` for any `'a`:
-//!
-//!    <&'a () as Identity> <: <&'static () as Identity>
-//!    if &'static () < : &'a ()   -- Identity is contravariant in Self
-//!    if 'static : 'a             -- Subtyping rules for relations
-//!
-//! This change otoh means that `<'static () as Identity>::Out` is
-//! always `&'static ()` (which might then be upcast to `'a ()`,
-//! separately). This was helpful in solving #21750.
-
-use self::VarianceTerm::*;
-use self::ParamKind::*;
-
-use arena;
-use arena::TypedArena;
-use dep_graph::DepNode;
-use middle::def_id::DefId;
-use middle::resolve_lifetime as rl;
-use middle::subst;
-use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace};
-use middle::ty::{self, Ty};
-use rustc::front::map as hir_map;
-use std::fmt;
-use std::rc::Rc;
-use syntax::ast;
-use rustc_front::hir;
-use rustc_front::intravisit::Visitor;
-use util::nodemap::NodeMap;
-
-pub fn infer_variance(tcx: &ty::ctxt) {
-    let _task = tcx.dep_graph.in_task(DepNode::Variance);
-    let krate = tcx.map.krate();
-    let mut arena = arena::TypedArena::new();
-    let terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate);
-    let constraints_cx = add_constraints_from_crate(terms_cx, krate);
-    solve_constraints(constraints_cx);
-    tcx.variance_computed.set(true);
-}
-
-// Representing terms
-//
-// Terms are structured as a straightforward tree. Rather than rely on
-// GC, we allocate terms out of a bounded arena (the lifetime of this
-// arena is the lifetime 'a that is threaded around).
-//
-// We assign a unique index to each type/region parameter whose variance
-// is to be inferred. We refer to such variables as "inferreds". An
-// `InferredIndex` is a newtype'd int representing the index of such
-// a variable.
-
-type VarianceTermPtr<'a> = &'a VarianceTerm<'a>;
-
-#[derive(Copy, Clone, Debug)]
-struct InferredIndex(usize);
-
-#[derive(Copy, Clone)]
-enum VarianceTerm<'a> {
-    ConstantTerm(ty::Variance),
-    TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>),
-    InferredTerm(InferredIndex),
-}
-
-impl<'a> fmt::Debug for VarianceTerm<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            ConstantTerm(c1) => write!(f, "{:?}", c1),
-            TransformTerm(v1, v2) => write!(f, "({:?} \u{00D7} {:?})", v1, v2),
-            InferredTerm(id) => write!(f, "[{}]", { let InferredIndex(i) = id; i })
-        }
-    }
-}
-
-// The first pass over the crate simply builds up the set of inferreds.
-
-struct TermsContext<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    arena: &'a TypedArena<VarianceTerm<'a>>,
-
-    empty_variances: Rc<ty::ItemVariances>,
-
-    // For marker types, UnsafeCell, and other lang items where
-    // variance is hardcoded, records the item-id and the hardcoded
-    // variance.
-    lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
-
-    // Maps from the node id of a type/generic parameter to the
-    // corresponding inferred index.
-    inferred_map: NodeMap<InferredIndex>,
-
-    // Maps from an InferredIndex to the info for that variable.
-    inferred_infos: Vec<InferredInfo<'a>> ,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-enum ParamKind {
-    TypeParam,
-    RegionParam,
-}
-
-struct InferredInfo<'a> {
-    item_id: ast::NodeId,
-    kind: ParamKind,
-    space: ParamSpace,
-    index: usize,
-    param_id: ast::NodeId,
-    term: VarianceTermPtr<'a>,
-
-    // 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.
-    initial_variance: ty::Variance,
-}
-
-fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
-                                                 arena: &'a mut TypedArena<VarianceTerm<'a>>,
-                                                 krate: &hir::Crate)
-                                                 -> TermsContext<'a, 'tcx> {
-    let mut terms_cx = TermsContext {
-        tcx: tcx,
-        arena: arena,
-        inferred_map: NodeMap(),
-        inferred_infos: Vec::new(),
-
-        lang_items: lang_items(tcx),
-
-        // cache and share the variance struct used for items with
-        // no type/region parameters
-        empty_variances: Rc::new(ty::ItemVariances {
-            types: VecPerParamSpace::empty(),
-            regions: VecPerParamSpace::empty()
-        })
-    };
-
-    krate.visit_all_items(&mut terms_cx);
-
-    terms_cx
-}
-
-fn lang_items(tcx: &ty::ctxt) -> Vec<(ast::NodeId,Vec<ty::Variance>)> {
-    let all = vec![
-        (tcx.lang_items.phantom_data(), vec![ty::Covariant]),
-        (tcx.lang_items.unsafe_cell_type(), vec![ty::Invariant]),
-
-        // Deprecated:
-        (tcx.lang_items.covariant_type(), vec![ty::Covariant]),
-        (tcx.lang_items.contravariant_type(), vec![ty::Contravariant]),
-        (tcx.lang_items.invariant_type(), vec![ty::Invariant]),
-        (tcx.lang_items.covariant_lifetime(), vec![ty::Covariant]),
-        (tcx.lang_items.contravariant_lifetime(), vec![ty::Contravariant]),
-        (tcx.lang_items.invariant_lifetime(), vec![ty::Invariant]),
-
-        ];
-
-    all.into_iter() // iterating over (Option<DefId>, Variance)
-       .filter(|&(ref d,_)| d.is_some())
-       .map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
-       .filter_map(|(d, v)| tcx.map.as_local_node_id(d).map(|n| (n, v))) // (NodeId, Variance)
-       .collect()
-}
-
-impl<'a, 'tcx> TermsContext<'a, 'tcx> {
-    fn add_inferreds_for_item(&mut self,
-                              item_id: ast::NodeId,
-                              has_self: bool,
-                              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.
-         */
-
-        // NB: In the code below for writing the results back into the
-        // tcx, we rely on the fact that all inferreds for a particular
-        // item are assigned continuous indices.
-
-        let inferreds_on_entry = self.num_inferred();
-
-        if has_self {
-            self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id);
-        }
-
-        for (i, p) in generics.lifetimes.iter().enumerate() {
-            let id = p.lifetime.id;
-            self.add_inferred(item_id, RegionParam, TypeSpace, i, id);
-        }
-
-        for (i, p) in generics.ty_params.iter().enumerate() {
-            self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id);
-        }
-
-        // If this item has no type or lifetime parameters,
-        // then there are no variances to infer, so just
-        // insert an empty entry into the variance map.
-        // Arguably we could just leave the map empty in this
-        // case but it seems cleaner to be able to distinguish
-        // "invalid item id" from "item id with no
-        // parameters".
-        if self.num_inferred() == inferreds_on_entry {
-            let item_def_id = self.tcx.map.local_def_id(item_id);
-            let newly_added =
-                self.tcx.item_variance_map.borrow_mut().insert(
-                    item_def_id,
-                    self.empty_variances.clone()).is_none();
-            assert!(newly_added);
-        }
-    }
-
-    fn add_inferred(&mut self,
-                    item_id: ast::NodeId,
-                    kind: ParamKind,
-                    space: ParamSpace,
-                    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, space, index);
-        self.inferred_infos.push(InferredInfo { item_id: item_id,
-                                                kind: kind,
-                                                space: space,
-                                                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();
-        assert!(newly_added);
-
-        debug!("add_inferred(item_path={}, \
-                item_id={}, \
-                kind={:?}, \
-                space={:?}, \
-                index={}, \
-                param_id={}, \
-                inf_index={:?}, \
-                initial_variance={:?})",
-               self.tcx.item_path_str(self.tcx.map.local_def_id(item_id)),
-               item_id, kind, space, index, param_id, inf_index,
-               initial_variance);
-    }
-
-    fn pick_initial_variance(&self,
-                             item_id: ast::NodeId,
-                             space: ParamSpace,
-                             index: usize)
-                             -> ty::Variance
-    {
-        match space {
-            SelfSpace | FnSpace => {
-                ty::Bivariant
-            }
-
-            TypeSpace => {
-                match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
-                    Some(&(_, ref variances)) => variances[index],
-                    None => ty::Bivariant
-                }
-            }
-        }
-    }
-
-    fn num_inferred(&self) -> usize {
-        self.inferred_infos.len()
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
-        debug!("add_inferreds for item {}", self.tcx.map.node_to_string(item.id));
-
-        match item.node {
-            hir::ItemEnum(_, ref generics) |
-            hir::ItemStruct(_, ref generics) => {
-                self.add_inferreds_for_item(item.id, false, generics);
-            }
-            hir::ItemTrait(_, ref generics, _, _) => {
-                // Note: all inputs for traits are ultimately
-                // constrained to be invariant. See `visit_item` in
-                // the impl for `ConstraintContext` below.
-                self.add_inferreds_for_item(item.id, true, generics);
-            }
-
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(_) |
-            hir::ItemDefaultImpl(..) |
-            hir::ItemImpl(..) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemTy(..) => {
-            }
-        }
-    }
-}
-
-// Constraint construction and representation
-//
-// The second pass over the AST determines the set of constraints.
-// We walk the set of items and, for each member, generate new constraints.
-
-struct ConstraintContext<'a, 'tcx: 'a> {
-    terms_cx: TermsContext<'a, 'tcx>,
-
-    // These are pointers to common `ConstantTerm` instances
-    covariant: VarianceTermPtr<'a>,
-    contravariant: VarianceTermPtr<'a>,
-    invariant: VarianceTermPtr<'a>,
-    bivariant: VarianceTermPtr<'a>,
-
-    constraints: Vec<Constraint<'a>> ,
-}
-
-/// Declares that the variable `decl_id` appears in a location with
-/// variance `variance`.
-#[derive(Copy, Clone)]
-struct Constraint<'a> {
-    inferred: InferredIndex,
-    variance: &'a VarianceTerm<'a>,
-}
-
-fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>,
-                                        krate: &hir::Crate)
-                                        -> ConstraintContext<'a, 'tcx>
-{
-    let covariant = terms_cx.arena.alloc(ConstantTerm(ty::Covariant));
-    let contravariant = terms_cx.arena.alloc(ConstantTerm(ty::Contravariant));
-    let invariant = terms_cx.arena.alloc(ConstantTerm(ty::Invariant));
-    let bivariant = terms_cx.arena.alloc(ConstantTerm(ty::Bivariant));
-    let mut constraint_cx = ConstraintContext {
-        terms_cx: terms_cx,
-        covariant: covariant,
-        contravariant: contravariant,
-        invariant: invariant,
-        bivariant: bivariant,
-        constraints: Vec::new(),
-    };
-    krate.visit_all_items(&mut constraint_cx);
-    constraint_cx
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
-        let tcx = self.terms_cx.tcx;
-        let did = tcx.map.local_def_id(item.id);
-
-        debug!("visit_item item={}", tcx.map.node_to_string(item.id));
-
-        match item.node {
-            hir::ItemEnum(..) | hir::ItemStruct(..) => {
-                let scheme = tcx.lookup_item_type(did);
-
-                // 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(&scheme.generics);
-
-                for field in tcx.lookup_adt_def(did).all_fields() {
-                    self.add_constraints_from_ty(&scheme.generics,
-                                                 field.unsubst_ty(),
-                                                 self.covariant);
-                }
-            }
-            hir::ItemTrait(..) => {
-                let trait_def = tcx.lookup_trait_def(did);
-                self.add_constraints_from_trait_ref(&trait_def.generics,
-                                                    trait_def.trait_ref,
-                                                    self.invariant);
-            }
-
-            hir::ItemExternCrate(_) |
-            hir::ItemUse(_) |
-            hir::ItemStatic(..) |
-            hir::ItemConst(..) |
-            hir::ItemFn(..) |
-            hir::ItemMod(..) |
-            hir::ItemForeignMod(..) |
-            hir::ItemTy(..) |
-            hir::ItemImpl(..) |
-            hir::ItemDefaultImpl(..) => {
-            }
-        }
-    }
-}
-
-/// 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) -> &'a ty::ctxt<'tcx> {
-        self.terms_cx.tcx
-    }
-
-    fn inferred_index(&self, param_id: ast::NodeId) -> InferredIndex {
-        match self.terms_cx.inferred_map.get(&param_id) {
-            Some(&index) => index,
-            None => {
-                self.tcx().sess.bug(&format!(
-                        "no inferred index entry for {}",
-                        self.tcx().map.node_to_string(param_id)));
-            }
-        }
-    }
-
-    fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
-        let tcx = self.terms_cx.tcx;
-        assert!(is_lifetime(&tcx.map, param_id));
-        match tcx.named_region_map.get(&param_id) {
-            Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id))
-                => lifetime_decl_id,
-            Some(_) => panic!("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.map, param_id));
-            let parent_id = tcx.map.get_parent(decl_id);
-            let parent = tcx.map.find(parent_id).unwrap_or_else(
-                || panic!("tcx.map missing entry for id: {}", parent_id));
-
-            let is_inferred;
-            macro_rules! cannot_happen { () => { {
-                panic!("invalid parent: {} for {}",
-                      tcx.map.node_to_string(parent_id),
-                      tcx.map.node_to_string(param_id));
-            } } }
-
-            match parent {
-                hir_map::NodeItem(p) => {
-                    match p.node {
-                        hir::ItemTy(..) |
-                        hir::ItemEnum(..) |
-                        hir::ItemStruct(..) |
-                        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,
-                         kind: ParamKind,
-                         space: ParamSpace,
-                         index: usize)
-                         -> VarianceTermPtr<'a> {
-        assert_eq!(param_def_id.krate, item_def_id.krate);
-
-        if let Some(param_node_id) = self.tcx().map.as_local_node_id(param_def_id) {
-            // Parameter on an item defined within current crate:
-            // variance not yet inferred, so return a symbolic
-            // variance.
-            let InferredIndex(index) = self.inferred_index(param_node_id);
-            self.terms_cx.inferred_infos[index].term
-        } else {
-            // Parameter on an item defined within another crate:
-            // variance already inferred, just look it up.
-            let variances = self.tcx().item_variances(item_def_id);
-            let variance = match kind {
-                TypeParam => *variances.types.get(space, index),
-                RegionParam => *variances.regions.get(space, index),
-            };
-            self.constant_term(variance)
-        }
-    }
-
-    fn add_constraint(&mut self,
-                      InferredIndex(index): InferredIndex,
-                      variance: VarianceTermPtr<'a>) {
-        debug!("add_constraint(index={}, variance={:?})",
-                index, variance);
-        self.constraints.push(Constraint { inferred: InferredIndex(index),
-                                           variance: variance });
-    }
-
-    fn contravariant(&mut self,
-                     variance: VarianceTermPtr<'a>)
-                     -> VarianceTermPtr<'a> {
-        self.xform(variance, self.contravariant)
-    }
-
-    fn invariant(&mut self,
-                 variance: VarianceTermPtr<'a>)
-                 -> VarianceTermPtr<'a> {
-        self.xform(variance, self.invariant)
-    }
-
-    fn constant_term(&self, v: ty::Variance) -> VarianceTermPtr<'a> {
-        match v {
-            ty::Covariant => self.covariant,
-            ty::Invariant => self.invariant,
-            ty::Contravariant => self.contravariant,
-            ty::Bivariant => self.bivariant,
-        }
-    }
-
-    fn xform(&mut self,
-             v1: VarianceTermPtr<'a>,
-             v2: VarianceTermPtr<'a>)
-             -> VarianceTermPtr<'a> {
-        match (*v1, *v2) {
-            (_, ConstantTerm(ty::Covariant)) => {
-                // Applying a "covariant" transform is always a no-op
-                v1
-            }
-
-            (ConstantTerm(c1), ConstantTerm(c2)) => {
-                self.constant_term(c1.xform(c2))
-            }
-
-            _ => {
-                &*self.terms_cx.arena.alloc(TransformTerm(v1, v2))
-            }
-        }
-    }
-
-    fn add_constraints_from_trait_ref(&mut self,
-                                      generics: &ty::Generics<'tcx>,
-                                      trait_ref: ty::TraitRef<'tcx>,
-                                      variance: VarianceTermPtr<'a>) {
-        debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
-               trait_ref,
-               variance);
-
-        let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
-
-        self.add_constraints_from_substs(
-            generics,
-            trait_ref.def_id,
-            trait_def.generics.types.as_slice(),
-            trait_def.generics.regions.as_slice(),
-            trait_ref.substs,
-            variance);
-    }
-
-    /// Adds constraints appropriate for an instance of `ty` appearing
-    /// in a context with the generics defined in `generics` and
-    /// ambient variance `variance`
-    fn add_constraints_from_ty(&mut self,
-                               generics: &ty::Generics<'tcx>,
-                               ty: Ty<'tcx>,
-                               variance: VarianceTermPtr<'a>) {
-        debug!("add_constraints_from_ty(ty={:?}, variance={:?})",
-               ty,
-               variance);
-
-        match ty.sty {
-            ty::TyBool |
-            ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
-            ty::TyFloat(_) | ty::TyStr => {
-                /* leaf type -- noop */
-            }
-
-            ty::TyClosure(..) => {
-                self.tcx().sess.bug("Unexpected closure type in variance computation");
-            }
-
-            ty::TyRef(region, ref mt) => {
-                let contra = self.contravariant(variance);
-                self.add_constraints_from_region(generics, *region, contra);
-                self.add_constraints_from_mt(generics, mt, variance);
-            }
-
-            ty::TyBox(typ) | ty::TyArray(typ, _) | ty::TySlice(typ) => {
-                self.add_constraints_from_ty(generics, typ, variance);
-            }
-
-
-            ty::TyRawPtr(ref mt) => {
-                self.add_constraints_from_mt(generics, mt, variance);
-            }
-
-            ty::TyTuple(ref subtys) => {
-                for &subty in subtys {
-                    self.add_constraints_from_ty(generics, subty, variance);
-                }
-            }
-
-            ty::TyEnum(def, substs) |
-            ty::TyStruct(def, substs) => {
-                let item_type = self.tcx().lookup_item_type(def.did);
-
-                // All type parameters on enums and structs should be
-                // in the TypeSpace.
-                assert!(item_type.generics.types.is_empty_in(subst::SelfSpace));
-                assert!(item_type.generics.types.is_empty_in(subst::FnSpace));
-                assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace));
-                assert!(item_type.generics.regions.is_empty_in(subst::FnSpace));
-
-                self.add_constraints_from_substs(
-                    generics,
-                    def.did,
-                    item_type.generics.types.get_slice(subst::TypeSpace),
-                    item_type.generics.regions.get_slice(subst::TypeSpace),
-                    substs,
-                    variance);
-            }
-
-            ty::TyProjection(ref data) => {
-                let trait_ref = &data.trait_ref;
-                let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
-                self.add_constraints_from_substs(
-                    generics,
-                    trait_ref.def_id,
-                    trait_def.generics.types.as_slice(),
-                    trait_def.generics.regions.as_slice(),
-                    trait_ref.substs,
-                    variance);
-            }
-
-            ty::TyTrait(ref data) => {
-                let poly_trait_ref =
-                    data.principal_trait_ref_with_self_ty(self.tcx(),
-                                                          self.tcx().types.err);
-
-                // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
-                let contra = self.contravariant(variance);
-                self.add_constraints_from_region(generics, data.bounds.region_bound, contra);
-
-                // Ignore the SelfSpace, it is erased.
-                self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
-
-                let projections = data.projection_bounds_with_self_ty(self.tcx(),
-                                                                      self.tcx().types.err);
-                for projection in &projections {
-                    self.add_constraints_from_ty(generics, projection.0.ty, self.invariant);
-                }
-            }
-
-            ty::TyParam(ref data) => {
-                let def_id = generics.types.get(data.space, data.idx as usize).def_id;
-                let node_id = self.tcx().map.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.
-                    }
-                }
-            }
-
-            ty::TyBareFn(_, &ty::BareFnTy { ref sig, .. }) => {
-                self.add_constraints_from_sig(generics, sig, variance);
-            }
-
-            ty::TyError => {
-                // we encounter this when walking the trait references for object
-                // types, where we use TyError as the Self type
-            }
-
-            ty::TyInfer(..) => {
-                self.tcx().sess.bug(
-                    &format!("unexpected type encountered in \
-                              variance inference: {}", ty));
-            }
-        }
-    }
-
-
-    /// Adds constraints appropriate for a nominal type (enum, struct,
-    /// object, etc) appearing in a context with ambient variance `variance`
-    fn add_constraints_from_substs(&mut self,
-                                   generics: &ty::Generics<'tcx>,
-                                   def_id: DefId,
-                                   type_param_defs: &[ty::TypeParameterDef<'tcx>],
-                                   region_param_defs: &[ty::RegionParameterDef],
-                                   substs: &subst::Substs<'tcx>,
-                                   variance: VarianceTermPtr<'a>) {
-        debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
-               def_id,
-               substs,
-               variance);
-
-        for p in type_param_defs {
-            let variance_decl =
-                self.declared_variance(p.def_id, def_id, TypeParam,
-                                       p.space, p.index as usize);
-            let variance_i = self.xform(variance, variance_decl);
-            let substs_ty = *substs.types.get(p.space, p.index as usize);
-            debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
-                   variance_decl, variance_i);
-            self.add_constraints_from_ty(generics, substs_ty, variance_i);
-        }
-
-        for p in region_param_defs {
-            let variance_decl =
-                self.declared_variance(p.def_id, def_id,
-                                       RegionParam, p.space, p.index as usize);
-            let variance_i = self.xform(variance, variance_decl);
-            let substs_r = *substs.regions().get(p.space, p.index as usize);
-            self.add_constraints_from_region(generics, substs_r, variance_i);
-        }
-    }
-
-    /// Adds constraints appropriate for a function with signature
-    /// `sig` appearing in a context with ambient variance `variance`
-    fn add_constraints_from_sig(&mut self,
-                                generics: &ty::Generics<'tcx>,
-                                sig: &ty::PolyFnSig<'tcx>,
-                                variance: VarianceTermPtr<'a>) {
-        let contra = self.contravariant(variance);
-        for &input in &sig.0.inputs {
-            self.add_constraints_from_ty(generics, input, contra);
-        }
-        if let ty::FnConverging(result_type) = sig.0.output {
-            self.add_constraints_from_ty(generics, result_type, variance);
-        }
-    }
-
-    /// Adds constraints appropriate for a region appearing in a
-    /// context with ambient variance `variance`
-    fn add_constraints_from_region(&mut self,
-                                   generics: &ty::Generics<'tcx>,
-                                   region: ty::Region,
-                                   variance: VarianceTermPtr<'a>) {
-        match region {
-            ty::ReEarlyBound(ref data) => {
-                let def_id =
-                    generics.regions.get(data.space, data.index as usize).def_id;
-                let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
-                if self.is_to_be_inferred(node_id) {
-                    let index = self.inferred_index(node_id);
-                    self.add_constraint(index, variance);
-                }
-            }
-
-            ty::ReStatic => { }
-
-            ty::ReLateBound(..) => {
-                // We do not infer variance for region parameters on
-                // methods or in fn types.
-            }
-
-            ty::ReFree(..) | ty::ReScope(..) | ty::ReVar(..) |
-            ty::ReSkolemized(..) | ty::ReEmpty => {
-                // We don't expect to see anything but 'static or bound
-                // regions when visiting member types or method types.
-                self.tcx()
-                    .sess
-                    .bug(&format!("unexpected region encountered in variance \
-                                  inference: {:?}",
-                                 region));
-            }
-        }
-    }
-
-    /// Adds constraints appropriate for a mutability-type pair
-    /// appearing in a context with ambient variance `variance`
-    fn add_constraints_from_mt(&mut self,
-                               generics: &ty::Generics<'tcx>,
-                               mt: &ty::TypeAndMut<'tcx>,
-                               variance: VarianceTermPtr<'a>) {
-        match mt.mutbl {
-            hir::MutMutable => {
-                let invar = self.invariant(variance);
-                self.add_constraints_from_ty(generics, mt.ty, invar);
-            }
-
-            hir::MutImmutable => {
-                self.add_constraints_from_ty(generics, mt.ty, variance);
-            }
-        }
-    }
-}
-
-// Constraint solving
-//
-// The final phase iterates over the constraints, refining the variance
-// for each inferred until a fixed point is reached. This will be the
-// optimal solution to the constraints. The final variance for each
-// inferred is then written into the `variance_map` in the tcx.
-
-struct SolveContext<'a, 'tcx: 'a> {
-    terms_cx: TermsContext<'a, 'tcx>,
-    constraints: Vec<Constraint<'a>> ,
-
-    // Maps from an InferredIndex to the inferred value for that variable.
-    solutions: Vec<ty::Variance> }
-
-fn solve_constraints(constraints_cx: ConstraintContext) {
-    let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
-
-    let solutions =
-        terms_cx.inferred_infos.iter()
-                               .map(|ii| ii.initial_variance)
-                               .collect();
-
-    let mut solutions_cx = SolveContext {
-        terms_cx: terms_cx,
-        constraints: constraints,
-        solutions: solutions
-    };
-    solutions_cx.solve();
-    solutions_cx.write();
-}
-
-impl<'a, 'tcx> SolveContext<'a, 'tcx> {
-    fn solve(&mut self) {
-        // Propagate constraints until a fixed point is reached.  Note
-        // that the maximum number of iterations is 2C where C is the
-        // number of constraints (each variable can change values at most
-        // twice). Since number of constraints is linear in size of the
-        // input, so is the inference process.
-        let mut changed = true;
-        while changed {
-            changed = false;
-
-            for constraint in &self.constraints {
-                let Constraint { inferred, variance: term } = *constraint;
-                let InferredIndex(inferred) = inferred;
-                let variance = self.evaluate(term);
-                let old_value = self.solutions[inferred];
-                let new_value = glb(variance, old_value);
-                if old_value != new_value {
-                    debug!("Updating inferred {} (node {}) \
-                            from {:?} to {:?} due to {:?}",
-                            inferred,
-                            self.terms_cx
-                                .inferred_infos[inferred]
-                                .param_id,
-                            old_value,
-                            new_value,
-                            term);
-
-                    self.solutions[inferred] = new_value;
-                    changed = true;
-                }
-            }
-        }
-    }
-
-    fn write(&self) {
-        // 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 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 types = VecPerParamSpace::empty();
-            let mut regions = VecPerParamSpace::empty();
-
-            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, info.kind, info.space, variance);
-                match info.kind {
-                    TypeParam => { types.push(info.space, variance); }
-                    RegionParam => { regions.push(info.space, variance); }
-                }
-
-                index += 1;
-            }
-
-            let item_variances = ty::ItemVariances {
-                types: types,
-                regions: regions
-            };
-            debug!("item_id={} item_variances={:?}",
-                    item_id,
-                    item_variances);
-
-            let item_def_id = tcx.map.local_def_id(item_id);
-
-            // For unit testing: check for a special "rustc_variance"
-            // attribute and report an error with various results if found.
-            if tcx.has_attr(item_def_id, "rustc_variance") {
-                span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{:?}", item_variances);
-            }
-
-            let newly_added = tcx.item_variance_map.borrow_mut()
-                                 .insert(item_def_id, Rc::new(item_variances)).is_none();
-            assert!(newly_added);
-        }
-    }
-
-    fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
-        match *term {
-            ConstantTerm(v) => {
-                v
-            }
-
-            TransformTerm(t1, t2) => {
-                let v1 = self.evaluate(t1);
-                let v2 = self.evaluate(t2);
-                v1.xform(v2)
-            }
-
-            InferredTerm(InferredIndex(index)) => {
-                self.solutions[index]
-            }
-        }
-    }
-}
-
-// Miscellany transformations on variance
-
-trait Xform {
-    fn xform(self, v: Self) -> Self;
-}
-
-impl Xform for ty::Variance {
-    fn xform(self, v: ty::Variance) -> ty::Variance {
-        // "Variance transformation", Figure 1 of The Paper
-        match (self, v) {
-            // Figure 1, column 1.
-            (ty::Covariant, ty::Covariant) => ty::Covariant,
-            (ty::Covariant, ty::Contravariant) => ty::Contravariant,
-            (ty::Covariant, ty::Invariant) => ty::Invariant,
-            (ty::Covariant, ty::Bivariant) => ty::Bivariant,
-
-            // Figure 1, column 2.
-            (ty::Contravariant, ty::Covariant) => ty::Contravariant,
-            (ty::Contravariant, ty::Contravariant) => ty::Covariant,
-            (ty::Contravariant, ty::Invariant) => ty::Invariant,
-            (ty::Contravariant, ty::Bivariant) => ty::Bivariant,
-
-            // Figure 1, column 3.
-            (ty::Invariant, _) => ty::Invariant,
-
-            // Figure 1, column 4.
-            (ty::Bivariant, _) => ty::Bivariant,
-        }
-    }
-}
-
-fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
-    // Greatest lower bound of the variance lattice as
-    // defined in The Paper:
-    //
-    //       *
-    //    -     +
-    //       o
-    match (v1, v2) {
-        (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
-
-        (ty::Covariant, ty::Contravariant) => ty::Invariant,
-        (ty::Contravariant, ty::Covariant) => ty::Invariant,
-
-        (ty::Covariant, ty::Covariant) => ty::Covariant,
-
-        (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
-
-        (x, ty::Bivariant) | (ty::Bivariant, x) => x,
-    }
-}
diff --git a/src/librustc_typeck/variance/README.md b/src/librustc_typeck/variance/README.md
new file mode 100644
index 00000000000..94d1ff91c37
--- /dev/null
+++ b/src/librustc_typeck/variance/README.md
@@ -0,0 +1,302 @@
+This file infers the variance of type and lifetime parameters. The
+algorithm is taken from Section 4 of the paper "Taming the Wildcards:
+Combining Definition- and Use-Site Variance" published in PLDI'11 and
+written by Altidor et al., and hereafter referred to as The Paper.
+
+This inference is explicitly designed *not* to consider the uses of
+types within code. To determine the variance of type parameters
+defined on type `X`, we only consider the definition of the type `X`
+and the definitions of any types it references.
+
+We only infer variance for type parameters found on *data types*
+like structs and enums. In these cases, there is fairly straightforward
+explanation for what variance means. The variance of the type
+or lifetime parameters defines whether `T<A>` is a subtype of `T<B>`
+(resp. `T<'a>` and `T<'b>`) based on the relationship of `A` and `B`
+(resp. `'a` and `'b`).
+
+We do not infer variance for type parameters found on traits, fns,
+or impls. Variance on trait parameters can make indeed make sense
+(and we used to compute it) but it is actually rather subtle in
+meaning and not that useful in practice, so we removed it. See the
+addendum for some details. Variances on fn/impl parameters, otoh,
+doesn't make sense because these parameters are instantiated and
+then forgotten, they don't persist in types or compiled
+byproducts.
+
+### The algorithm
+
+The basic idea is quite straightforward. We iterate over the types
+defined and, for each use of a type parameter X, accumulate a
+constraint indicating that the variance of X must be valid for the
+variance of that use site. We then iteratively refine the variance of
+X until all constraints are met. There is *always* a sol'n, because at
+the limit we can declare all type parameters to be invariant and all
+constraints will be satisfied.
+
+As a simple example, consider:
+
+    enum Option<A> { Some(A), None }
+    enum OptionalFn<B> { Some(|B|), None }
+    enum OptionalMap<C> { Some(|C| -> C), None }
+
+Here, we will generate the constraints:
+
+    1. V(A) <= +
+    2. V(B) <= -
+    3. V(C) <= +
+    4. V(C) <= -
+
+These indicate that (1) the variance of A must be at most covariant;
+(2) the variance of B must be at most contravariant; and (3, 4) the
+variance of C must be at most covariant *and* contravariant. All of these
+results are based on a variance lattice defined as follows:
+
+      *      Top (bivariant)
+   -     +
+      o      Bottom (invariant)
+
+Based on this lattice, the solution V(A)=+, V(B)=-, V(C)=o is the
+optimal solution. Note that there is always a naive solution which
+just declares all variables to be invariant.
+
+You may be wondering why fixed-point iteration is required. The reason
+is that the variance of a use site may itself be a function of the
+variance of other type parameters. In full generality, our constraints
+take the form:
+
+    V(X) <= Term
+    Term := + | - | * | o | V(X) | Term x Term
+
+Here the notation V(X) indicates the variance of a type/region
+parameter `X` with respect to its defining class. `Term x Term`
+represents the "variance transform" as defined in the paper:
+
+  If the variance of a type variable `X` in type expression `E` is `V2`
+  and the definition-site variance of the [corresponding] type parameter
+  of a class `C` is `V1`, then the variance of `X` in the type expression
+  `C<E>` is `V3 = V1.xform(V2)`.
+
+### Constraints
+
+If I have a struct or enum with where clauses:
+
+    struct Foo<T:Bar> { ... }
+
+you might wonder whether the variance of `T` with respect to `Bar`
+affects the variance `T` with respect to `Foo`. I claim no.  The
+reason: assume that `T` is invariant w/r/t `Bar` but covariant w/r/t
+`Foo`. And then we have a `Foo<X>` that is upcast to `Foo<Y>`, where
+`X <: Y`. However, while `X : Bar`, `Y : Bar` does not hold.  In that
+case, the upcast will be illegal, but not because of a variance
+failure, but rather because the target type `Foo<Y>` is itself just
+not well-formed. Basically we get to assume well-formedness of all
+types involved before considering variance.
+
+#### Dependency graph management
+
+Because variance works in two phases, if we are not careful, we wind
+up with a muddled mess of a dep-graph. Basically, when gathering up
+the constraints, things are fairly well-structured, but then we do a
+fixed-point iteration and write the results back where they
+belong. You can't give this fixed-point iteration a single task
+because it reads from (and writes to) the variance of all types in the
+crate. In principle, we *could* switch the "current task" in a very
+fine-grained way while propagating constraints in the fixed-point
+iteration and everything would be automatically tracked, but that
+would add some overhead and isn't really necessary anyway.
+
+Instead what we do is to add edges into the dependency graph as we
+construct the constraint set: so, if computing the constraints for
+node `X` requires loading the inference variables from node `Y`, then
+we can add an edge `Y -> X`, since the variance we ultimately infer
+for `Y` will affect the variance we ultimately infer for `X`.
+
+At this point, we've basically mirrored the inference graph in the
+dependency graph. This means we can just completely ignore the
+fixed-point iteration, since it is just shuffling values along this
+graph. In other words, if we added the fine-grained switching of tasks
+I described earlier, all it would show is that we repeatedly read the
+values described by the constraints, but those edges were already
+added when building the constraints in the first place.
+
+Here is how this is implemented (at least as of the time of this
+writing). The associated `DepNode` for the variance map is (at least
+presently) `Signature(DefId)`. This means that, in `constraints.rs`,
+when we visit an item to load up its constraints, we set
+`Signature(DefId)` as the current task (the "memoization" pattern
+described in the `dep-graph` README). Then whenever we find an
+embedded type or trait, we add a synthetic read of `Signature(DefId)`,
+which covers the variances we will compute for all of its
+parameters. This read is synthetic (i.e., we call
+`variance_map.read()`) because, in fact, the final variance is not yet
+computed -- the read *will* occur (repeatedly) during the fixed-point
+iteration phase.
+
+In fact, we don't really *need* this synthetic read. That's because we
+do wind up looking up the `TypeScheme` or `TraitDef` for all
+references types/traits, and those reads add an edge from
+`Signature(DefId)` (that is, they share the same dep node as
+variance). However, I've kept the synthetic reads in place anyway,
+just for future-proofing (in case we change the dep-nodes in the
+future), and because it makes the intention a bit clearer I think.
+
+### Addendum: Variance on traits
+
+As mentioned above, we used to permit variance on traits. This was
+computed based on the appearance of trait type parameters in
+method signatures and was used to represent the compatibility of
+vtables in trait objects (and also "virtual" vtables or dictionary
+in trait bounds). One complication was that variance for
+associated types is less obvious, since they can be projected out
+and put to myriad uses, so it's not clear when it is safe to allow
+`X<A>::Bar` to vary (or indeed just what that means). Moreover (as
+covered below) all inputs on any trait with an associated type had
+to be invariant, limiting the applicability. Finally, the
+annotations (`MarkerTrait`, `PhantomFn`) needed to ensure that all
+trait type parameters had a variance were confusing and annoying
+for little benefit.
+
+Just for historical reference,I am going to preserve some text indicating
+how one could interpret variance and trait matching.
+
+#### Variance and object types
+
+Just as with structs and enums, we can decide the subtyping
+relationship between two object types `&Trait<A>` and `&Trait<B>`
+based on the relationship of `A` and `B`. Note that for object
+types we ignore the `Self` type parameter -- it is unknown, and
+the nature of dynamic dispatch ensures that we will always call a
+function that is expected the appropriate `Self` type. However, we
+must be careful with the other type parameters, or else we could
+end up calling a function that is expecting one type but provided
+another.
+
+To see what I mean, consider a trait like so:
+
+    trait ConvertTo<A> {
+        fn convertTo(&self) -> A;
+    }
+
+Intuitively, If we had one object `O=&ConvertTo<Object>` and another
+`S=&ConvertTo<String>`, then `S <: O` because `String <: Object`
+(presuming Java-like "string" and "object" types, my go to examples
+for subtyping). The actual algorithm would be to compare the
+(explicit) type parameters pairwise respecting their variance: here,
+the type parameter A is covariant (it appears only in a return
+position), and hence we require that `String <: Object`.
+
+You'll note though that we did not consider the binding for the
+(implicit) `Self` type parameter: in fact, it is unknown, so that's
+good. The reason we can ignore that parameter is precisely because we
+don't need to know its value until a call occurs, and at that time (as
+you said) the dynamic nature of virtual dispatch means the code we run
+will be correct for whatever value `Self` happens to be bound to for
+the particular object whose method we called. `Self` is thus different
+from `A`, because the caller requires that `A` be known in order to
+know the return type of the method `convertTo()`. (As an aside, we
+have rules preventing methods where `Self` appears outside of the
+receiver position from being called via an object.)
+
+#### Trait variance and vtable resolution
+
+But traits aren't only used with objects. They're also used when
+deciding whether a given impl satisfies a given trait bound. To set the
+scene here, imagine I had a function:
+
+    fn convertAll<A,T:ConvertTo<A>>(v: &[T]) {
+        ...
+    }
+
+Now imagine that I have an implementation of `ConvertTo` for `Object`:
+
+    impl ConvertTo<i32> for Object { ... }
+
+And I want to call `convertAll` on an array of strings. Suppose
+further that for whatever reason I specifically supply the value of
+`String` for the type parameter `T`:
+
+    let mut vector = vec!["string", ...];
+    convertAll::<i32, String>(vector);
+
+Is this legal? To put another way, can we apply the `impl` for
+`Object` to the type `String`? The answer is yes, but to see why
+we have to expand out what will happen:
+
+- `convertAll` will create a pointer to one of the entries in the
+  vector, which will have type `&String`
+- It will then call the impl of `convertTo()` that is intended
+  for use with objects. This has the type:
+
+      fn(self: &Object) -> i32
+
+  It is ok to provide a value for `self` of type `&String` because
+  `&String <: &Object`.
+
+OK, so intuitively we want this to be legal, so let's bring this back
+to variance and see whether we are computing the correct result. We
+must first figure out how to phrase the question "is an impl for
+`Object,i32` usable where an impl for `String,i32` is expected?"
+
+Maybe it's helpful to think of a dictionary-passing implementation of
+type classes. In that case, `convertAll()` takes an implicit parameter
+representing the impl. In short, we *have* an impl of type:
+
+    V_O = ConvertTo<i32> for Object
+
+and the function prototype expects an impl of type:
+
+    V_S = ConvertTo<i32> for String
+
+As with any argument, this is legal if the type of the value given
+(`V_O`) is a subtype of the type expected (`V_S`). So is `V_O <: V_S`?
+The answer will depend on the variance of the various parameters. In
+this case, because the `Self` parameter is contravariant and `A` is
+covariant, it means that:
+
+    V_O <: V_S iff
+        i32 <: i32
+        String <: Object
+
+These conditions are satisfied and so we are happy.
+
+#### Variance and associated types
+
+Traits with associated types -- or at minimum projection
+expressions -- must be invariant with respect to all of their
+inputs. To see why this makes sense, consider what subtyping for a
+trait reference means:
+
+   <T as Trait> <: <U as Trait>
+
+means that if I know that `T as Trait`, I also know that `U as
+Trait`. Moreover, if you think of it as dictionary passing style,
+it means that a dictionary for `<T as Trait>` is safe to use where
+a dictionary for `<U as Trait>` is expected.
+
+The problem is that when you can project types out from `<T as
+Trait>`, the relationship to types projected out of `<U as Trait>`
+is completely unknown unless `T==U` (see #21726 for more
+details). Making `Trait` invariant ensures that this is true.
+
+Another related reason is that if we didn't make traits with
+associated types invariant, then projection is no longer a
+function with a single result. Consider:
+
+```
+trait Identity { type Out; fn foo(&self); }
+impl<T> Identity for T { type Out = T; ... }
+```
+
+Now if I have `<&'static () as Identity>::Out`, this can be
+validly derived as `&'a ()` for any `'a`:
+
+   <&'a () as Identity> <: <&'static () as Identity>
+   if &'static () < : &'a ()   -- Identity is contravariant in Self
+   if 'static : 'a             -- Subtyping rules for relations
+
+This change otoh means that `<'static () as Identity>::Out` is
+always `&'static ()` (which might then be upcast to `'a ()`,
+separately). This was helpful in solving #21750.
+
+
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
new file mode 100644
index 00000000000..2f243d0fd0f
--- /dev/null
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -0,0 +1,553 @@
+// Copyright 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.
+
+//! Constraint construction and representation
+//!
+//! The second pass over the AST determines the set of constraints.
+//! We walk the set of items and, for each member, generate new constraints.
+
+use dep_graph::DepTrackingMapConfig;
+use middle::def_id::DefId;
+use middle::resolve_lifetime as rl;
+use middle::subst;
+use middle::subst::ParamSpace;
+use middle::ty::{self, Ty};
+use middle::ty::maps::ItemVariances;
+use rustc::front::map as hir_map;
+use syntax::ast;
+use rustc_front::hir;
+use rustc_front::intravisit::Visitor;
+
+use super::terms::*;
+use super::terms::VarianceTerm::*;
+use super::terms::ParamKind::*;
+use super::xform::*;
+
+pub struct ConstraintContext<'a, 'tcx: 'a> {
+    pub terms_cx: TermsContext<'a, 'tcx>,
+
+    // These are pointers to common `ConstantTerm` instances
+    covariant: VarianceTermPtr<'a>,
+    contravariant: VarianceTermPtr<'a>,
+    invariant: VarianceTermPtr<'a>,
+    bivariant: VarianceTermPtr<'a>,
+
+    pub constraints: Vec<Constraint<'a>> ,
+}
+
+/// Declares that the variable `decl_id` appears in a location with
+/// variance `variance`.
+#[derive(Copy, Clone)]
+pub struct Constraint<'a> {
+    pub inferred: InferredIndex,
+    pub variance: &'a VarianceTerm<'a>,
+}
+
+pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>)
+                                            -> ConstraintContext<'a, 'tcx>
+{
+    let tcx = terms_cx.tcx;
+    let covariant = terms_cx.arena.alloc(ConstantTerm(ty::Covariant));
+    let contravariant = terms_cx.arena.alloc(ConstantTerm(ty::Contravariant));
+    let invariant = terms_cx.arena.alloc(ConstantTerm(ty::Invariant));
+    let bivariant = terms_cx.arena.alloc(ConstantTerm(ty::Bivariant));
+    let mut constraint_cx = ConstraintContext {
+        terms_cx: terms_cx,
+        covariant: covariant,
+        contravariant: contravariant,
+        invariant: invariant,
+        bivariant: bivariant,
+        constraints: Vec::new(),
+    };
+
+    // See README.md for a discussion on dep-graph management.
+    tcx.visit_all_items_in_krate(|def_id| ItemVariances::to_dep_node(&def_id),
+                                 &mut constraint_cx);
+
+    constraint_cx
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        let tcx = self.terms_cx.tcx;
+        let did = tcx.map.local_def_id(item.id);
+
+        debug!("visit_item item={}", tcx.map.node_to_string(item.id));
+
+        match item.node {
+            hir::ItemEnum(..) | hir::ItemStruct(..) => {
+                let scheme = tcx.lookup_item_type(did);
+
+                // 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(&scheme.generics);
+
+                for field in tcx.lookup_adt_def(did).all_fields() {
+                    self.add_constraints_from_ty(&scheme.generics,
+                                                 field.unsubst_ty(),
+                                                 self.covariant);
+                }
+            }
+            hir::ItemTrait(..) => {
+                let trait_def = tcx.lookup_trait_def(did);
+                self.add_constraints_from_trait_ref(&trait_def.generics,
+                                                    trait_def.trait_ref,
+                                                    self.invariant);
+            }
+
+            hir::ItemExternCrate(_) |
+            hir::ItemUse(_) |
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) |
+            hir::ItemFn(..) |
+            hir::ItemMod(..) |
+            hir::ItemForeignMod(..) |
+            hir::ItemTy(..) |
+            hir::ItemImpl(..) |
+            hir::ItemDefaultImpl(..) => {
+            }
+        }
+    }
+}
+
+/// 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) -> &'a ty::ctxt<'tcx> {
+        self.terms_cx.tcx
+    }
+
+    fn inferred_index(&self, param_id: ast::NodeId) -> InferredIndex {
+        match self.terms_cx.inferred_map.get(&param_id) {
+            Some(&index) => index,
+            None => {
+                self.tcx().sess.bug(&format!(
+                        "no inferred index entry for {}",
+                        self.tcx().map.node_to_string(param_id)));
+            }
+        }
+    }
+
+    fn find_binding_for_lifetime(&self, param_id: ast::NodeId) -> ast::NodeId {
+        let tcx = self.terms_cx.tcx;
+        assert!(is_lifetime(&tcx.map, param_id));
+        match tcx.named_region_map.get(&param_id) {
+            Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id))
+                => lifetime_decl_id,
+            Some(_) => panic!("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.map, param_id));
+            let parent_id = tcx.map.get_parent(decl_id);
+            let parent = tcx.map.find(parent_id).unwrap_or_else(
+                || panic!("tcx.map missing entry for id: {}", parent_id));
+
+            let is_inferred;
+            macro_rules! cannot_happen { () => { {
+                panic!("invalid parent: {} for {}",
+                      tcx.map.node_to_string(parent_id),
+                      tcx.map.node_to_string(param_id));
+            } } }
+
+            match parent {
+                hir_map::NodeItem(p) => {
+                    match p.node {
+                        hir::ItemTy(..) |
+                        hir::ItemEnum(..) |
+                        hir::ItemStruct(..) |
+                        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,
+                         kind: ParamKind,
+                         space: ParamSpace,
+                         index: usize)
+                         -> VarianceTermPtr<'a> {
+        assert_eq!(param_def_id.krate, item_def_id.krate);
+
+        if let Some(param_node_id) = self.tcx().map.as_local_node_id(param_def_id) {
+            // Parameter on an item defined within current crate:
+            // variance not yet inferred, so return a symbolic
+            // variance.
+            let InferredIndex(index) = self.inferred_index(param_node_id);
+            self.terms_cx.inferred_infos[index].term
+        } else {
+            // Parameter on an item defined within another crate:
+            // variance already inferred, just look it up.
+            let variances = self.tcx().item_variances(item_def_id);
+            let variance = match kind {
+                TypeParam => *variances.types.get(space, index),
+                RegionParam => *variances.regions.get(space, index),
+            };
+            self.constant_term(variance)
+        }
+    }
+
+    fn add_constraint(&mut self,
+                      InferredIndex(index): InferredIndex,
+                      variance: VarianceTermPtr<'a>) {
+        debug!("add_constraint(index={}, variance={:?})",
+                index, variance);
+        self.constraints.push(Constraint { inferred: InferredIndex(index),
+                                           variance: variance });
+    }
+
+    fn contravariant(&mut self,
+                     variance: VarianceTermPtr<'a>)
+                     -> VarianceTermPtr<'a> {
+        self.xform(variance, self.contravariant)
+    }
+
+    fn invariant(&mut self,
+                 variance: VarianceTermPtr<'a>)
+                 -> VarianceTermPtr<'a> {
+        self.xform(variance, self.invariant)
+    }
+
+    fn constant_term(&self, v: ty::Variance) -> VarianceTermPtr<'a> {
+        match v {
+            ty::Covariant => self.covariant,
+            ty::Invariant => self.invariant,
+            ty::Contravariant => self.contravariant,
+            ty::Bivariant => self.bivariant,
+        }
+    }
+
+    fn xform(&mut self,
+             v1: VarianceTermPtr<'a>,
+             v2: VarianceTermPtr<'a>)
+             -> VarianceTermPtr<'a> {
+        match (*v1, *v2) {
+            (_, ConstantTerm(ty::Covariant)) => {
+                // Applying a "covariant" transform is always a no-op
+                v1
+            }
+
+            (ConstantTerm(c1), ConstantTerm(c2)) => {
+                self.constant_term(c1.xform(c2))
+            }
+
+            _ => {
+                &*self.terms_cx.arena.alloc(TransformTerm(v1, v2))
+            }
+        }
+    }
+
+    fn add_constraints_from_trait_ref(&mut self,
+                                      generics: &ty::Generics<'tcx>,
+                                      trait_ref: ty::TraitRef<'tcx>,
+                                      variance: VarianceTermPtr<'a>) {
+        debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
+               trait_ref,
+               variance);
+
+        let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
+
+        // This edge is actually implied by the call to
+        // `lookup_trait_def`, but I'm trying to be future-proof. See
+        // README.md for a discussion on dep-graph management.
+        self.tcx().dep_graph.read(ItemVariances::to_dep_node(&trait_ref.def_id));
+
+        self.add_constraints_from_substs(
+            generics,
+            trait_ref.def_id,
+            trait_def.generics.types.as_slice(),
+            trait_def.generics.regions.as_slice(),
+            trait_ref.substs,
+            variance);
+    }
+
+    /// Adds constraints appropriate for an instance of `ty` appearing
+    /// in a context with the generics defined in `generics` and
+    /// ambient variance `variance`
+    fn add_constraints_from_ty(&mut self,
+                               generics: &ty::Generics<'tcx>,
+                               ty: Ty<'tcx>,
+                               variance: VarianceTermPtr<'a>) {
+        debug!("add_constraints_from_ty(ty={:?}, variance={:?})",
+               ty,
+               variance);
+
+        match ty.sty {
+            ty::TyBool |
+            ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
+            ty::TyFloat(_) | ty::TyStr => {
+                /* leaf type -- noop */
+            }
+
+            ty::TyClosure(..) => {
+                self.tcx().sess.bug("Unexpected closure type in variance computation");
+            }
+
+            ty::TyRef(region, ref mt) => {
+                let contra = self.contravariant(variance);
+                self.add_constraints_from_region(generics, *region, contra);
+                self.add_constraints_from_mt(generics, mt, variance);
+            }
+
+            ty::TyBox(typ) | ty::TyArray(typ, _) | ty::TySlice(typ) => {
+                self.add_constraints_from_ty(generics, typ, variance);
+            }
+
+
+            ty::TyRawPtr(ref mt) => {
+                self.add_constraints_from_mt(generics, mt, variance);
+            }
+
+            ty::TyTuple(ref subtys) => {
+                for &subty in subtys {
+                    self.add_constraints_from_ty(generics, subty, variance);
+                }
+            }
+
+            ty::TyEnum(def, substs) |
+            ty::TyStruct(def, substs) => {
+                let item_type = self.tcx().lookup_item_type(def.did);
+
+                // This edge is actually implied by the call to
+                // `lookup_trait_def`, but I'm trying to be future-proof. See
+                // README.md for a discussion on dep-graph management.
+                self.tcx().dep_graph.read(ItemVariances::to_dep_node(&def.did));
+
+                // All type parameters on enums and structs should be
+                // in the TypeSpace.
+                assert!(item_type.generics.types.is_empty_in(subst::SelfSpace));
+                assert!(item_type.generics.types.is_empty_in(subst::FnSpace));
+                assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace));
+                assert!(item_type.generics.regions.is_empty_in(subst::FnSpace));
+
+                self.add_constraints_from_substs(
+                    generics,
+                    def.did,
+                    item_type.generics.types.get_slice(subst::TypeSpace),
+                    item_type.generics.regions.get_slice(subst::TypeSpace),
+                    substs,
+                    variance);
+            }
+
+            ty::TyProjection(ref data) => {
+                let trait_ref = &data.trait_ref;
+                let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
+
+                // This edge is actually implied by the call to
+                // `lookup_trait_def`, but I'm trying to be future-proof. See
+                // README.md for a discussion on dep-graph management.
+                self.tcx().dep_graph.read(ItemVariances::to_dep_node(&trait_ref.def_id));
+
+                self.add_constraints_from_substs(
+                    generics,
+                    trait_ref.def_id,
+                    trait_def.generics.types.as_slice(),
+                    trait_def.generics.regions.as_slice(),
+                    trait_ref.substs,
+                    variance);
+            }
+
+            ty::TyTrait(ref data) => {
+                let poly_trait_ref =
+                    data.principal_trait_ref_with_self_ty(self.tcx(),
+                                                          self.tcx().types.err);
+
+                // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
+                let contra = self.contravariant(variance);
+                self.add_constraints_from_region(generics, data.bounds.region_bound, contra);
+
+                // Ignore the SelfSpace, it is erased.
+                self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
+
+                let projections = data.projection_bounds_with_self_ty(self.tcx(),
+                                                                      self.tcx().types.err);
+                for projection in &projections {
+                    self.add_constraints_from_ty(generics, projection.0.ty, self.invariant);
+                }
+            }
+
+            ty::TyParam(ref data) => {
+                let def_id = generics.types.get(data.space, data.idx as usize).def_id;
+                let node_id = self.tcx().map.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.
+                    }
+                }
+            }
+
+            ty::TyBareFn(_, &ty::BareFnTy { ref sig, .. }) => {
+                self.add_constraints_from_sig(generics, sig, variance);
+            }
+
+            ty::TyError => {
+                // we encounter this when walking the trait references for object
+                // types, where we use TyError as the Self type
+            }
+
+            ty::TyInfer(..) => {
+                self.tcx().sess.bug(
+                    &format!("unexpected type encountered in \
+                              variance inference: {}", ty));
+            }
+        }
+    }
+
+    /// Adds constraints appropriate for a nominal type (enum, struct,
+    /// object, etc) appearing in a context with ambient variance `variance`
+    fn add_constraints_from_substs(&mut self,
+                                   generics: &ty::Generics<'tcx>,
+                                   def_id: DefId,
+                                   type_param_defs: &[ty::TypeParameterDef<'tcx>],
+                                   region_param_defs: &[ty::RegionParameterDef],
+                                   substs: &subst::Substs<'tcx>,
+                                   variance: VarianceTermPtr<'a>) {
+        debug!("add_constraints_from_substs(def_id={:?}, substs={:?}, variance={:?})",
+               def_id,
+               substs,
+               variance);
+
+        for p in type_param_defs {
+            let variance_decl =
+                self.declared_variance(p.def_id, def_id, TypeParam,
+                                       p.space, p.index as usize);
+            let variance_i = self.xform(variance, variance_decl);
+            let substs_ty = *substs.types.get(p.space, p.index as usize);
+            debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
+                   variance_decl, variance_i);
+            self.add_constraints_from_ty(generics, substs_ty, variance_i);
+        }
+
+        for p in region_param_defs {
+            let variance_decl =
+                self.declared_variance(p.def_id, def_id,
+                                       RegionParam, p.space, p.index as usize);
+            let variance_i = self.xform(variance, variance_decl);
+            let substs_r = *substs.regions().get(p.space, p.index as usize);
+            self.add_constraints_from_region(generics, substs_r, variance_i);
+        }
+    }
+
+    /// Adds constraints appropriate for a function with signature
+    /// `sig` appearing in a context with ambient variance `variance`
+    fn add_constraints_from_sig(&mut self,
+                                generics: &ty::Generics<'tcx>,
+                                sig: &ty::PolyFnSig<'tcx>,
+                                variance: VarianceTermPtr<'a>) {
+        let contra = self.contravariant(variance);
+        for &input in &sig.0.inputs {
+            self.add_constraints_from_ty(generics, input, contra);
+        }
+        if let ty::FnConverging(result_type) = sig.0.output {
+            self.add_constraints_from_ty(generics, result_type, variance);
+        }
+    }
+
+    /// Adds constraints appropriate for a region appearing in a
+    /// context with ambient variance `variance`
+    fn add_constraints_from_region(&mut self,
+                                   generics: &ty::Generics<'tcx>,
+                                   region: ty::Region,
+                                   variance: VarianceTermPtr<'a>) {
+        match region {
+            ty::ReEarlyBound(ref data) => {
+                let def_id =
+                    generics.regions.get(data.space, data.index as usize).def_id;
+                let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
+                if self.is_to_be_inferred(node_id) {
+                    let index = self.inferred_index(node_id);
+                    self.add_constraint(index, variance);
+                }
+            }
+
+            ty::ReStatic => { }
+
+            ty::ReLateBound(..) => {
+                // We do not infer variance for region parameters on
+                // methods or in fn types.
+            }
+
+            ty::ReFree(..) | ty::ReScope(..) | ty::ReVar(..) |
+            ty::ReSkolemized(..) | ty::ReEmpty => {
+                // We don't expect to see anything but 'static or bound
+                // regions when visiting member types or method types.
+                self.tcx()
+                    .sess
+                    .bug(&format!("unexpected region encountered in variance \
+                                  inference: {:?}",
+                                 region));
+            }
+        }
+    }
+
+    /// Adds constraints appropriate for a mutability-type pair
+    /// appearing in a context with ambient variance `variance`
+    fn add_constraints_from_mt(&mut self,
+                               generics: &ty::Generics<'tcx>,
+                               mt: &ty::TypeAndMut<'tcx>,
+                               variance: VarianceTermPtr<'a>) {
+        match mt.mutbl {
+            hir::MutMutable => {
+                let invar = self.invariant(variance);
+                self.add_constraints_from_ty(generics, mt.ty, invar);
+            }
+
+            hir::MutImmutable => {
+                self.add_constraints_from_ty(generics, mt.ty, variance);
+            }
+        }
+    }
+}
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
new file mode 100644
index 00000000000..3ce3a868f04
--- /dev/null
+++ b/src/librustc_typeck/variance/mod.rs
@@ -0,0 +1,37 @@
+// Copyright 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.
+
+//! Module for inferring the variance of type and lifetime
+//! parameters. See README.md for details.
+
+use arena;
+use middle::ty;
+
+/// Defines the `TermsContext` basically houses an arena where we can
+/// allocate terms.
+mod terms;
+
+/// Code to gather up constraints.
+mod constraints;
+
+/// Code to solve constraints and write out the results.
+mod solve;
+
+/// Code for transforming variances.
+mod xform;
+
+pub fn infer_variance(tcx: &ty::ctxt) {
+    let mut arena = arena::TypedArena::new();
+    let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena);
+    let constraints_cx = constraints::add_constraints_from_crate(terms_cx);
+    solve::solve_constraints(constraints_cx);
+    tcx.variance_computed.set(true);
+}
+
diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs
new file mode 100644
index 00000000000..fd442a4547c
--- /dev/null
+++ b/src/librustc_typeck/variance/solve.rs
@@ -0,0 +1,167 @@
+// Copyright 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.
+
+//! Constraint solving
+//!
+//! The final phase iterates over the constraints, refining the variance
+//! for each inferred until a fixed point is reached. This will be the
+//! optimal solution to the constraints. The final variance for each
+//! inferred is then written into the `variance_map` in the tcx.
+
+use middle::subst::VecPerParamSpace;
+use middle::ty;
+use std::rc::Rc;
+
+use super::constraints::*;
+use super::terms::*;
+use super::terms::VarianceTerm::*;
+use super::terms::ParamKind::*;
+use super::xform::*;
+
+struct SolveContext<'a, 'tcx: 'a> {
+    terms_cx: TermsContext<'a, 'tcx>,
+    constraints: Vec<Constraint<'a>> ,
+
+    // Maps from an InferredIndex to the inferred value for that variable.
+    solutions: Vec<ty::Variance>
+}
+
+pub fn solve_constraints(constraints_cx: ConstraintContext) {
+    let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
+
+    let solutions =
+        terms_cx.inferred_infos.iter()
+                               .map(|ii| ii.initial_variance)
+                               .collect();
+
+    let mut solutions_cx = SolveContext {
+        terms_cx: terms_cx,
+        constraints: constraints,
+        solutions: solutions
+    };
+    solutions_cx.solve();
+    solutions_cx.write();
+}
+
+impl<'a, 'tcx> SolveContext<'a, 'tcx> {
+    fn solve(&mut self) {
+        // Propagate constraints until a fixed point is reached.  Note
+        // that the maximum number of iterations is 2C where C is the
+        // number of constraints (each variable can change values at most
+        // twice). Since number of constraints is linear in size of the
+        // input, so is the inference process.
+        let mut changed = true;
+        while changed {
+            changed = false;
+
+            for constraint in &self.constraints {
+                let Constraint { inferred, variance: term } = *constraint;
+                let InferredIndex(inferred) = inferred;
+                let variance = self.evaluate(term);
+                let old_value = self.solutions[inferred];
+                let new_value = glb(variance, old_value);
+                if old_value != new_value {
+                    debug!("Updating inferred {} (node {}) \
+                            from {:?} to {:?} due to {:?}",
+                            inferred,
+                            self.terms_cx
+                                .inferred_infos[inferred]
+                                .param_id,
+                            old_value,
+                            new_value,
+                            term);
+
+                    self.solutions[inferred] = new_value;
+                    changed = true;
+                }
+            }
+        }
+    }
+
+    fn write(&self) {
+        // 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;
+
+        // Ignore the writes here because the relevant edges were
+        // already accounted for in `constraints.rs`. See the section
+        // on dependency graph management in README.md for more
+        // information.
+        let _ignore = tcx.dep_graph.in_ignore();
+
+        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 types = VecPerParamSpace::empty();
+            let mut regions = VecPerParamSpace::empty();
+
+            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, info.kind, info.space, variance);
+                match info.kind {
+                    TypeParam => { types.push(info.space, variance); }
+                    RegionParam => { regions.push(info.space, variance); }
+                }
+
+                index += 1;
+            }
+
+            let item_variances = ty::ItemVariances {
+                types: types,
+                regions: regions
+            };
+            debug!("item_id={} item_variances={:?}",
+                    item_id,
+                    item_variances);
+
+            let item_def_id = tcx.map.local_def_id(item_id);
+
+            // For unit testing: check for a special "rustc_variance"
+            // attribute and report an error with various results if found.
+            if tcx.has_attr(item_def_id, "rustc_variance") {
+                span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{:?}", item_variances);
+            }
+
+            let newly_added = tcx.item_variance_map.borrow_mut()
+                                 .insert(item_def_id, Rc::new(item_variances)).is_none();
+            assert!(newly_added);
+        }
+    }
+
+    fn evaluate(&self, term: VarianceTermPtr<'a>) -> ty::Variance {
+        match *term {
+            ConstantTerm(v) => {
+                v
+            }
+
+            TransformTerm(t1, t2) => {
+                let v1 = self.evaluate(t1);
+                let v2 = self.evaluate(t2);
+                v1.xform(v2)
+            }
+
+            InferredTerm(InferredIndex(index)) => {
+                self.solutions[index]
+            }
+        }
+    }
+}
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
new file mode 100644
index 00000000000..aa1e93c3d6b
--- /dev/null
+++ b/src/librustc_typeck/variance/terms.rs
@@ -0,0 +1,287 @@
+// Copyright 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.
+
+// Representing terms
+//
+// Terms are structured as a straightforward tree. Rather than rely on
+// GC, we allocate terms out of a bounded arena (the lifetime of this
+// arena is the lifetime 'a that is threaded around).
+//
+// We assign a unique index to each type/region parameter whose variance
+// is to be inferred. We refer to such variables as "inferreds". An
+// `InferredIndex` is a newtype'd int representing the index of such
+// a variable.
+
+use arena::TypedArena;
+use dep_graph::DepTrackingMapConfig;
+use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace};
+use middle::ty;
+use middle::ty::maps::ItemVariances;
+use std::fmt;
+use std::rc::Rc;
+use syntax::ast;
+use rustc_front::hir;
+use rustc_front::intravisit::Visitor;
+use util::nodemap::NodeMap;
+
+use self::VarianceTerm::*;
+use self::ParamKind::*;
+
+pub type VarianceTermPtr<'a> = &'a VarianceTerm<'a>;
+
+#[derive(Copy, Clone, Debug)]
+pub struct InferredIndex(pub usize);
+
+#[derive(Copy, Clone)]
+pub enum VarianceTerm<'a> {
+    ConstantTerm(ty::Variance),
+    TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>),
+    InferredTerm(InferredIndex),
+}
+
+impl<'a> fmt::Debug for VarianceTerm<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ConstantTerm(c1) => write!(f, "{:?}", c1),
+            TransformTerm(v1, v2) => write!(f, "({:?} \u{00D7} {:?})", v1, v2),
+            InferredTerm(id) => write!(f, "[{}]", { let InferredIndex(i) = id; i })
+        }
+    }
+}
+
+// The first pass over the crate simply builds up the set of inferreds.
+
+pub struct TermsContext<'a, 'tcx: 'a> {
+    pub tcx: &'a ty::ctxt<'tcx>,
+    pub arena: &'a TypedArena<VarianceTerm<'a>>,
+
+    pub empty_variances: Rc<ty::ItemVariances>,
+
+    // 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>> ,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum ParamKind {
+    TypeParam,
+    RegionParam,
+}
+
+pub struct InferredInfo<'a> {
+    pub item_id: ast::NodeId,
+    pub kind: ParamKind,
+    pub space: ParamSpace,
+    pub index: usize,
+    pub param_id: ast::NodeId,
+    pub term: VarianceTermPtr<'a>,
+
+    // 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,
+}
+
+pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
+    tcx: &'a ty::ctxt<'tcx>,
+    arena: &'a mut TypedArena<VarianceTerm<'a>>)
+    -> TermsContext<'a, 'tcx>
+{
+    let mut terms_cx = TermsContext {
+        tcx: tcx,
+        arena: arena,
+        inferred_map: NodeMap(),
+        inferred_infos: Vec::new(),
+
+        lang_items: lang_items(tcx),
+
+        // cache and share the variance struct used for items with
+        // no type/region parameters
+        empty_variances: Rc::new(ty::ItemVariances {
+            types: VecPerParamSpace::empty(),
+            regions: VecPerParamSpace::empty()
+        })
+    };
+
+    // See README.md for a discussion on dep-graph management.
+    tcx.visit_all_items_in_krate(|def_id| ItemVariances::to_dep_node(&def_id),
+                                 &mut terms_cx);
+
+    terms_cx
+}
+
+fn lang_items(tcx: &ty::ctxt) -> Vec<(ast::NodeId,Vec<ty::Variance>)> {
+    let all = vec![
+        (tcx.lang_items.phantom_data(), vec![ty::Covariant]),
+        (tcx.lang_items.unsafe_cell_type(), vec![ty::Invariant]),
+
+        // Deprecated:
+        (tcx.lang_items.covariant_type(), vec![ty::Covariant]),
+        (tcx.lang_items.contravariant_type(), vec![ty::Contravariant]),
+        (tcx.lang_items.invariant_type(), vec![ty::Invariant]),
+        (tcx.lang_items.covariant_lifetime(), vec![ty::Covariant]),
+        (tcx.lang_items.contravariant_lifetime(), vec![ty::Contravariant]),
+        (tcx.lang_items.invariant_lifetime(), vec![ty::Invariant]),
+
+        ];
+
+    all.into_iter() // iterating over (Option<DefId>, Variance)
+       .filter(|&(ref d,_)| d.is_some())
+       .map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
+       .filter_map(|(d, v)| tcx.map.as_local_node_id(d).map(|n| (n, v))) // (NodeId, Variance)
+       .collect()
+}
+
+impl<'a, 'tcx> TermsContext<'a, 'tcx> {
+    fn add_inferreds_for_item(&mut self,
+                              item_id: ast::NodeId,
+                              has_self: bool,
+                              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.
+         */
+
+        // NB: In the code below for writing the results back into the
+        // tcx, we rely on the fact that all inferreds for a particular
+        // item are assigned continuous indices.
+
+        let inferreds_on_entry = self.num_inferred();
+
+        if has_self {
+            self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id);
+        }
+
+        for (i, p) in generics.lifetimes.iter().enumerate() {
+            let id = p.lifetime.id;
+            self.add_inferred(item_id, RegionParam, TypeSpace, i, id);
+        }
+
+        for (i, p) in generics.ty_params.iter().enumerate() {
+            self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id);
+        }
+
+        // If this item has no type or lifetime parameters,
+        // then there are no variances to infer, so just
+        // insert an empty entry into the variance map.
+        // Arguably we could just leave the map empty in this
+        // case but it seems cleaner to be able to distinguish
+        // "invalid item id" from "item id with no
+        // parameters".
+        if self.num_inferred() == inferreds_on_entry {
+            let item_def_id = self.tcx.map.local_def_id(item_id);
+            let newly_added =
+                self.tcx.item_variance_map.borrow_mut().insert(
+                    item_def_id,
+                    self.empty_variances.clone()).is_none();
+            assert!(newly_added);
+        }
+    }
+
+    fn add_inferred(&mut self,
+                    item_id: ast::NodeId,
+                    kind: ParamKind,
+                    space: ParamSpace,
+                    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, space, index);
+        self.inferred_infos.push(InferredInfo { item_id: item_id,
+                                                kind: kind,
+                                                space: space,
+                                                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();
+        assert!(newly_added);
+
+        debug!("add_inferred(item_path={}, \
+                item_id={}, \
+                kind={:?}, \
+                space={:?}, \
+                index={}, \
+                param_id={}, \
+                inf_index={:?}, \
+                initial_variance={:?})",
+               self.tcx.item_path_str(self.tcx.map.local_def_id(item_id)),
+               item_id, kind, space, index, param_id, inf_index,
+               initial_variance);
+    }
+
+    fn pick_initial_variance(&self,
+                             item_id: ast::NodeId,
+                             space: ParamSpace,
+                             index: usize)
+                             -> ty::Variance
+    {
+        match space {
+            SelfSpace | FnSpace => {
+                ty::Bivariant
+            }
+
+            TypeSpace => {
+                match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
+                    Some(&(_, ref variances)) => variances[index],
+                    None => ty::Bivariant
+                }
+            }
+        }
+    }
+
+    pub fn num_inferred(&self) -> usize {
+        self.inferred_infos.len()
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        debug!("add_inferreds for item {}", self.tcx.map.node_to_string(item.id));
+
+        match item.node {
+            hir::ItemEnum(_, ref generics) |
+            hir::ItemStruct(_, ref generics) => {
+                self.add_inferreds_for_item(item.id, false, generics);
+            }
+            hir::ItemTrait(_, ref generics, _, _) => {
+                // Note: all inputs for traits are ultimately
+                // constrained to be invariant. See `visit_item` in
+                // the impl for `ConstraintContext` in `constraints.rs`.
+                self.add_inferreds_for_item(item.id, true, generics);
+            }
+
+            hir::ItemExternCrate(_) |
+            hir::ItemUse(_) |
+            hir::ItemDefaultImpl(..) |
+            hir::ItemImpl(..) |
+            hir::ItemStatic(..) |
+            hir::ItemConst(..) |
+            hir::ItemFn(..) |
+            hir::ItemMod(..) |
+            hir::ItemForeignMod(..) |
+            hir::ItemTy(..) => {
+            }
+        }
+    }
+}
+
diff --git a/src/librustc_typeck/variance/xform.rs b/src/librustc_typeck/variance/xform.rs
new file mode 100644
index 00000000000..2749dce5c73
--- /dev/null
+++ b/src/librustc_typeck/variance/xform.rs
@@ -0,0 +1,61 @@
+// Copyright 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.
+
+use middle::ty;
+
+pub trait Xform {
+    fn xform(self, v: Self) -> Self;
+}
+
+impl Xform for ty::Variance {
+    fn xform(self, v: ty::Variance) -> ty::Variance {
+        // "Variance transformation", Figure 1 of The Paper
+        match (self, v) {
+            // Figure 1, column 1.
+            (ty::Covariant, ty::Covariant) => ty::Covariant,
+            (ty::Covariant, ty::Contravariant) => ty::Contravariant,
+            (ty::Covariant, ty::Invariant) => ty::Invariant,
+            (ty::Covariant, ty::Bivariant) => ty::Bivariant,
+
+            // Figure 1, column 2.
+            (ty::Contravariant, ty::Covariant) => ty::Contravariant,
+            (ty::Contravariant, ty::Contravariant) => ty::Covariant,
+            (ty::Contravariant, ty::Invariant) => ty::Invariant,
+            (ty::Contravariant, ty::Bivariant) => ty::Bivariant,
+
+            // Figure 1, column 3.
+            (ty::Invariant, _) => ty::Invariant,
+
+            // Figure 1, column 4.
+            (ty::Bivariant, _) => ty::Bivariant,
+        }
+    }
+}
+
+pub fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance {
+    // Greatest lower bound of the variance lattice as
+    // defined in The Paper:
+    //
+    //       *
+    //    -     +
+    //       o
+    match (v1, v2) {
+        (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
+
+        (ty::Covariant, ty::Contravariant) => ty::Invariant,
+        (ty::Contravariant, ty::Covariant) => ty::Invariant,
+
+        (ty::Covariant, ty::Covariant) => ty::Covariant,
+
+        (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
+
+        (x, ty::Bivariant) | (ty::Bivariant, x) => x,
+    }
+}
diff --git a/src/librustc_unicode/char.rs b/src/librustc_unicode/char.rs
index 9386453d660..11500286755 100644
--- a/src/librustc_unicode/char.rs
+++ b/src/librustc_unicode/char.rs
@@ -457,16 +457,16 @@ impl char {
     ///
     /// # Examples
     ///
-    /// In both of these examples, 'ß' takes one `u16` to encode.
+    /// In both of these examples, '𝕊' takes two `u16`s to encode.
     ///
     /// ```
     /// #![feature(unicode)]
     ///
-    /// let mut b = [0; 1];
+    /// let mut b = [0; 2];
     ///
-    /// let result = 'ß'.encode_utf16(&mut b);
+    /// let result = '𝕊'.encode_utf16(&mut b);
     ///
-    /// assert_eq!(result, Some(1));
+    /// assert_eq!(result, Some(2));
     /// ```
     ///
     /// A buffer that's too small:
@@ -474,9 +474,9 @@ impl char {
     /// ```
     /// #![feature(unicode)]
     ///
-    /// let mut b = [0; 0];
+    /// let mut b = [0; 1];
     ///
-    /// let result = 'ß'.encode_utf8(&mut b);
+    /// let result = '𝕊'.encode_utf16(&mut b);
     ///
     /// assert_eq!(result, None);
     /// ```
@@ -776,13 +776,13 @@ impl char {
     /// Basic usage:
     ///
     /// ```
-    /// let c = 'c';
+    /// let c = 'C';
     ///
-    /// assert_eq!(c.to_uppercase().next(), Some('C'));
+    /// assert_eq!(c.to_lowercase().next(), Some('c'));
     ///
     /// // Japanese scripts do not have case, and so:
     /// let c = '山';
-    /// assert_eq!(c.to_uppercase().next(), Some('山'));
+    /// assert_eq!(c.to_lowercase().next(), Some('山'));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
diff --git a/src/librustc_unicode/u_str.rs b/src/librustc_unicode/u_str.rs
index f65c05672f6..9a6700ad47c 100644
--- a/src/librustc_unicode/u_str.rs
+++ b/src/librustc_unicode/u_str.rs
@@ -30,9 +30,9 @@ pub trait UnicodeStr {
     fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
     fn is_whitespace(&self) -> bool;
     fn is_alphanumeric(&self) -> bool;
-    fn trim<'a>(&'a self) -> &'a str;
-    fn trim_left<'a>(&'a self) -> &'a str;
-    fn trim_right<'a>(&'a self) -> &'a str;
+    fn trim(&self) -> &str;
+    fn trim_left(&self) -> &str;
+    fn trim_right(&self) -> &str;
 }
 
 impl UnicodeStr for str {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 9eac2fd41fa..8f878264769 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -260,6 +260,11 @@ pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
             match def {
                 cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
                 cstore::DlDef(Def::Mod(did)) => {
+                    // Don't recurse if this is a #[doc(hidden)] module
+                    if load_attrs(cx, tcx, did).iter().any(|a| is_doc_hidden(a)) {
+                        return;
+                    }
+
                     for item in tcx.sess.cstore.item_children(did) {
                         populate_impls(cx, tcx, item.def, impls)
                     }
@@ -423,19 +428,19 @@ pub fn build_impl(cx: &DocContext,
         deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
         def_id: did,
     });
+}
 
-    fn is_doc_hidden(a: &clean::Attribute) -> bool {
-        match *a {
-            clean::List(ref name, ref inner) if *name == "doc" => {
-                inner.iter().any(|a| {
-                    match *a {
-                        clean::Word(ref s) => *s == "hidden",
-                        _ => false,
-                    }
-                })
-            }
-            _ => false
+fn is_doc_hidden(a: &clean::Attribute) -> bool {
+    match *a {
+        clean::List(ref name, ref inner) if *name == "doc" => {
+            inner.iter().any(|a| {
+                match *a {
+                    clean::Word(ref s) => *s == "hidden",
+                    _ => false,
+                }
+            })
         }
+        _ => false
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index d6e4b7e4a51..1ff88f1d127 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -48,6 +48,7 @@ use std::collections::HashMap;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::u32;
+use std::env::current_dir;
 
 use core::DocContext;
 use doctree;
@@ -201,7 +202,13 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
         }
 
         let src = match cx.input {
-            Input::File(ref path) => path.clone(),
+            Input::File(ref path) => {
+                if path.is_absolute() {
+                    path.clone()
+                } else {
+                    current_dir().unwrap().join(path)
+                }
+            },
             Input::Str(_) => PathBuf::new() // FIXME: this is wrong
         };
 
@@ -2552,12 +2559,12 @@ fn name_from_pat(p: &hir::Pat) -> String {
     debug!("Trying to get a name from pattern: {:?}", p);
 
     match p.node {
-        PatWild => "_".to_string(),
-        PatIdent(_, ref p, _) => p.node.to_string(),
-        PatEnum(ref p, _) => path_to_string(p),
-        PatQPath(..) => panic!("tried to get argument name from PatQPath, \
+        PatKind::Wild => "_".to_string(),
+        PatKind::Ident(_, ref p, _) => p.node.to_string(),
+        PatKind::TupleStruct(ref p, _) | PatKind::Path(ref p) => path_to_string(p),
+        PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \
                                 which is not allowed in function arguments"),
-        PatStruct(ref name, ref fields, etc) => {
+        PatKind::Struct(ref name, ref fields, etc) => {
             format!("{} {{ {}{} }}", path_to_string(name),
                 fields.iter().map(|&Spanned { node: ref fp, .. }|
                                   format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
@@ -2565,18 +2572,18 @@ fn name_from_pat(p: &hir::Pat) -> String {
                 if etc { ", ..." } else { "" }
             )
         },
-        PatTup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
+        PatKind::Tup(ref elts) => format!("({})", elts.iter().map(|p| name_from_pat(&**p))
                                             .collect::<Vec<String>>().join(", ")),
-        PatBox(ref p) => name_from_pat(&**p),
-        PatRegion(ref p, _) => name_from_pat(&**p),
-        PatLit(..) => {
-            warn!("tried to get argument name from PatLit, \
+        PatKind::Box(ref p) => name_from_pat(&**p),
+        PatKind::Ref(ref p, _) => name_from_pat(&**p),
+        PatKind::Lit(..) => {
+            warn!("tried to get argument name from PatKind::Lit, \
                   which is silly in function arguments");
             "()".to_string()
         },
-        PatRange(..) => panic!("tried to get argument name from PatRange, \
+        PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \
                               which is not allowed in function arguments"),
-        PatVec(ref begin, ref mid, ref end) => {
+        PatKind::Vec(ref begin, ref mid, ref end) => {
             let begin = begin.iter().map(|p| name_from_pat(&**p));
             let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
             let end = end.iter().map(|p| name_from_pat(&**p));
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index ffcd22fa820..975b4d3636f 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -122,7 +122,7 @@ r##"<!DOCTYPE html>
 
                 <p>
                     Search functions by type signature (e.g.
-                    <code>vec -> usize</code>)
+                    <code>vec -> usize</code> or <code>* -> vec</code>)
                 </p>
             </div>
         </div>
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 8633d2a1c2e..9fd476bfbab 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -250,7 +250,9 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
             let text = lines.collect::<Vec<&str>>().join("\n");
             if rendered { return }
             PLAYGROUND_KRATE.with(|krate| {
-                let mut s = String::new();
+                // insert newline to clearly separate it from the
+                // previous block so we can shorten the html output
+                let mut s = String::from("\n");
                 krate.borrow().as_ref().map(|krate| {
                     let test = origtext.lines().map(|l| {
                         stripped_filtered_line(l).unwrap_or(l)
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 2053fc73e8f..af6dec8dc86 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -46,13 +46,13 @@ use std::io::prelude::*;
 use std::io::{self, BufWriter, BufReader};
 use std::iter::repeat;
 use std::mem;
-use std::path::{PathBuf, Path};
+use std::path::{PathBuf, Path, Component};
 use std::str;
 use std::sync::Arc;
 
 use externalfiles::ExternalHtml;
 
-use serialize::json::{self, ToJson};
+use serialize::json::{ToJson, Json, as_json};
 use syntax::{abi, ast};
 use syntax::feature_gate::UnstableFeatures;
 use rustc::middle::cstore::LOCAL_CRATE;
@@ -243,6 +243,7 @@ pub struct Cache {
 
     stack: Vec<String>,
     parent_stack: Vec<DefId>,
+    parent_is_trait_impl: bool,
     search_index: Vec<IndexItem>,
     privmod: bool,
     remove_priv: bool,
@@ -290,22 +291,40 @@ struct IndexItem {
     path: String,
     desc: String,
     parent: Option<DefId>,
+    parent_idx: Option<usize>,
     search_type: Option<IndexItemFunctionType>,
 }
 
+impl ToJson for IndexItem {
+    fn to_json(&self) -> Json {
+        assert_eq!(self.parent.is_some(), self.parent_idx.is_some());
+
+        let mut data = Vec::with_capacity(6);
+        data.push((self.ty as usize).to_json());
+        data.push(self.name.to_json());
+        data.push(self.path.to_json());
+        data.push(self.desc.to_json());
+        data.push(self.parent_idx.to_json());
+        data.push(self.search_type.to_json());
+
+        Json::Array(data)
+    }
+}
+
 /// A type used for the search index.
 struct Type {
     name: Option<String>,
 }
 
-impl fmt::Display for Type {
-    /// Formats type as {name: $name}.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        // Wrapping struct fmt should never call us when self.name is None,
-        // but just to be safe we write `null` in that case.
+impl ToJson for Type {
+    fn to_json(&self) -> Json {
         match self.name {
-            Some(ref n) => write!(f, "{{\"name\":\"{}\"}}", n),
-            None => write!(f, "null")
+            Some(ref name) => {
+                let mut data = BTreeMap::new();
+                data.insert("name".to_owned(), name.to_json());
+                Json::Object(data)
+            },
+            None => Json::Null
         }
     }
 }
@@ -316,26 +335,17 @@ struct IndexItemFunctionType {
     output: Option<Type>
 }
 
-impl fmt::Display for IndexItemFunctionType {
-    /// Formats a full fn type as a JSON {inputs: [Type], outputs: Type/null}.
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+impl ToJson for IndexItemFunctionType {
+    fn to_json(&self) -> Json {
         // If we couldn't figure out a type, just write `null`.
-        if self.inputs.iter().any(|ref i| i.name.is_none()) ||
-           (self.output.is_some() && self.output.as_ref().unwrap().name.is_none()) {
-            return write!(f, "null")
+        if self.inputs.iter().chain(self.output.iter()).any(|ref i| i.name.is_none()) {
+            Json::Null
+        } else {
+            let mut data = BTreeMap::new();
+            data.insert("inputs".to_owned(), self.inputs.to_json());
+            data.insert("output".to_owned(), self.output.to_json());
+            Json::Object(data)
         }
-
-        let inputs: Vec<String> = self.inputs.iter().map(|ref t| {
-            format!("{}", t)
-        }).collect();
-        try!(write!(f, "{{\"inputs\":[{}],\"output\":", inputs.join(",")));
-
-        match self.output {
-            Some(ref t) => try!(write!(f, "{}", t)),
-            None => try!(write!(f, "null"))
-        };
-
-        Ok(try!(write!(f, "}}")))
     }
 }
 
@@ -478,6 +488,7 @@ pub fn run(mut krate: clean::Crate,
         stack: Vec::new(),
         parent_stack: Vec::new(),
         search_index: Vec::new(),
+        parent_is_trait_impl: false,
         extern_locations: HashMap::new(),
         primitive_locations: HashMap::new(),
         remove_priv: cx.passes.contains("strip-private"),
@@ -534,101 +545,79 @@ pub fn run(mut krate: clean::Crate,
     cx.krate(krate)
 }
 
+/// Build the search index from the collected metadata
 fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
-    // Build the search index from the collected metadata
     let mut nodeid_to_pathid = HashMap::new();
-    let mut pathid_to_nodeid = Vec::new();
-    {
-        let Cache { ref mut search_index,
-                    ref orphan_methods,
-                    ref mut paths, .. } = *cache;
-
-        // Attach all orphan methods to the type's definition if the type
-        // has since been learned.
-        for &(did, ref item) in orphan_methods {
-            match paths.get(&did) {
-                Some(&(ref fqp, _)) => {
-                    // Needed to determine `self` type.
-                    let parent_basename = Some(fqp[fqp.len() - 1].clone());
-                    search_index.push(IndexItem {
-                        ty: shortty(item),
-                        name: item.name.clone().unwrap(),
-                        path: fqp[..fqp.len() - 1].join("::"),
-                        desc: Escape(&shorter(item.doc_value())).to_string(),
-                        parent: Some(did),
-                        search_type: get_index_search_type(&item, parent_basename),
-                    });
-                },
-                None => {}
-            }
-        }
-
-        // Reduce `NodeId` in paths into smaller sequential numbers,
-        // and prune the paths that do not appear in the index.
-        for item in search_index.iter() {
-            match item.parent {
-                Some(nodeid) => {
-                    if !nodeid_to_pathid.contains_key(&nodeid) {
-                        let pathid = pathid_to_nodeid.len();
-                        nodeid_to_pathid.insert(nodeid, pathid);
-                        pathid_to_nodeid.push(nodeid);
-                    }
-                }
-                None => {}
-            }
+    let mut crate_items = Vec::with_capacity(cache.search_index.len());
+    let mut crate_paths = Vec::<Json>::new();
+
+    let Cache { ref mut search_index,
+                ref orphan_methods,
+                ref mut paths, .. } = *cache;
+
+    // Attach all orphan methods to the type's definition if the type
+    // has since been learned.
+    for &(did, ref item) in orphan_methods {
+        match paths.get(&did) {
+            Some(&(ref fqp, _)) => {
+                // Needed to determine `self` type.
+                let parent_basename = Some(fqp[fqp.len() - 1].clone());
+                search_index.push(IndexItem {
+                    ty: shortty(item),
+                    name: item.name.clone().unwrap(),
+                    path: fqp[..fqp.len() - 1].join("::"),
+                    desc: Escape(&shorter(item.doc_value())).to_string(),
+                    parent: Some(did),
+                    parent_idx: None,
+                    search_type: get_index_search_type(&item, parent_basename),
+                });
+            },
+            None => {}
         }
-        assert_eq!(nodeid_to_pathid.len(), pathid_to_nodeid.len());
     }
 
-    // Collect the index into a string
-    let mut w = io::Cursor::new(Vec::new());
-    write!(&mut w, r#"searchIndex['{}'] = {{"items":["#, krate.name).unwrap();
+    // Reduce `NodeId` in paths into smaller sequential numbers,
+    // and prune the paths that do not appear in the index.
+    let mut lastpath = String::new();
+    let mut lastpathid = 0usize;
 
-    let mut lastpath = "".to_string();
-    for (i, item) in cache.search_index.iter().enumerate() {
-        // Omit the path if it is same to that of the prior item.
-        let path;
-        if lastpath == item.path {
-            path = "";
-        } else {
-            lastpath = item.path.to_string();
-            path = &item.path;
-        };
+    for item in search_index {
+        item.parent_idx = item.parent.map(|nodeid| {
+            if nodeid_to_pathid.contains_key(&nodeid) {
+                *nodeid_to_pathid.get(&nodeid).unwrap()
+            } else {
+                let pathid = lastpathid;
+                nodeid_to_pathid.insert(nodeid, pathid);
+                lastpathid += 1;
 
-        if i > 0 {
-            write!(&mut w, ",").unwrap();
-        }
-        write!(&mut w, r#"[{},"{}","{}",{}"#,
-               item.ty as usize, item.name, path,
-               item.desc.to_json().to_string()).unwrap();
-        match item.parent {
-            Some(nodeid) => {
-                let pathid = *nodeid_to_pathid.get(&nodeid).unwrap();
-                write!(&mut w, ",{}", pathid).unwrap();
+                let &(ref fqp, short) = paths.get(&nodeid).unwrap();
+                crate_paths.push(((short as usize), fqp.last().unwrap().clone()).to_json());
+                pathid
             }
-            None => write!(&mut w, ",null").unwrap()
-        }
-        match item.search_type {
-            Some(ref t) => write!(&mut w, ",{}", t).unwrap(),
-            None => write!(&mut w, ",null").unwrap()
-        }
-        write!(&mut w, "]").unwrap();
-    }
-
-    write!(&mut w, r#"],"paths":["#).unwrap();
+        });
 
-    for (i, &did) in pathid_to_nodeid.iter().enumerate() {
-        let &(ref fqp, short) = cache.paths.get(&did).unwrap();
-        if i > 0 {
-            write!(&mut w, ",").unwrap();
+        // Omit the parent path if it is same to that of the prior item.
+        if lastpath == item.path {
+            item.path.clear();
+        } else {
+            lastpath = item.path.clone();
         }
-        write!(&mut w, r#"[{},"{}"]"#,
-               short as usize, *fqp.last().unwrap()).unwrap();
+        crate_items.push(item.to_json());
     }
 
-    write!(&mut w, "]}};").unwrap();
+    let crate_doc = krate.module.as_ref().map(|module| {
+        Escape(&shorter(module.doc_value())).to_string()
+    }).unwrap_or(String::new());
+
+    let mut crate_data = BTreeMap::new();
+    crate_data.insert("doc".to_owned(), Json::String(crate_doc));
+    crate_data.insert("items".to_owned(), Json::Array(crate_items));
+    crate_data.insert("paths".to_owned(), Json::Array(crate_paths));
 
-    String::from_utf8(w.into_inner()).unwrap()
+    // Collect the index into a string
+    format!("searchIndex[{}] = {};",
+            as_json(&krate.name),
+            Json::Object(crate_data))
 }
 
 fn write_shared(cx: &Context,
@@ -693,7 +682,7 @@ fn write_shared(cx: &Context,
                 if !line.starts_with(key) {
                     continue
                 }
-                if line.starts_with(&format!("{}['{}']", key, krate)) {
+                if line.starts_with(&format!(r#"{}["{}"]"#, key, krate)) {
                     continue
                 }
                 ret.push(line.to_string());
@@ -823,16 +812,17 @@ fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) wh
     // make it relative, if possible
     let p = p.strip_prefix(src_root).unwrap_or(p);
 
-    let mut iter = p.iter().map(|x| x.to_str().unwrap()).peekable();
+    let mut iter = p.components().peekable();
+
     while let Some(c) = iter.next() {
         if !keep_filename && iter.peek().is_none() {
             break;
         }
 
-        if ".." == c {
-            f("up");
-        } else {
-            f(c)
+        match c {
+            Component::ParentDir => f("up"),
+            Component::Normal(c) => f(c.to_str().unwrap()),
+            _ => continue,
         }
     }
 }
@@ -884,7 +874,7 @@ impl<'a> DocFolder for SourceCollector<'a> {
             // entire crate. The other option is maintaining this mapping on a
             // per-file basis, but that's probably not worth it...
             self.cx
-                .include_sources = match self.emit_source(&item.source .filename) {
+                .include_sources = match self.emit_source(&item.source.filename) {
                 Ok(()) => true,
                 Err(e) => {
                     println!("warning: source code was requested to be rendered, \
@@ -1008,6 +998,11 @@ impl DocFolder for Cache {
         // Index this method for searching later on
         if let Some(ref s) = item.name {
             let (parent, is_method) = match item.inner {
+                clean::AssociatedConstItem(..) |
+                clean::TypedefItem(_, true) if self.parent_is_trait_impl => {
+                    // skip associated items in trait impls
+                    ((None, None), false)
+                }
                 clean::AssociatedTypeItem(..) |
                 clean::AssociatedConstItem(..) |
                 clean::TyMethodItem(..) |
@@ -1039,10 +1034,6 @@ impl DocFolder for Cache {
                         ((Some(*last), path), true)
                     }
                 }
-                clean::TypedefItem(_, true) => {
-                    // skip associated types in impls
-                    ((None, None), false)
-                }
                 _ => ((None, Some(&*self.stack)), false)
             };
             let hidden_field = match item.inner {
@@ -1067,6 +1058,7 @@ impl DocFolder for Cache {
                             path: path.join("::").to_string(),
                             desc: Escape(&shorter(item.doc_value())).to_string(),
                             parent: parent,
+                            parent_idx: None,
                             search_type: get_index_search_type(&item, parent_basename),
                         });
                     }
@@ -1127,12 +1119,15 @@ impl DocFolder for Cache {
         }
 
         // Maintain the parent stack
+        let orig_parent_is_trait_impl = self.parent_is_trait_impl;
         let parent_pushed = match item.inner {
             clean::TraitItem(..) | clean::EnumItem(..) | clean::StructItem(..) => {
                 self.parent_stack.push(item.def_id);
+                self.parent_is_trait_impl = false;
                 true
             }
             clean::ImplItem(ref i) => {
+                self.parent_is_trait_impl = i.trait_.is_some();
                 match i.for_ {
                     clean::ResolvedPath{ did, .. } => {
                         self.parent_stack.push(did);
@@ -1213,6 +1208,7 @@ impl DocFolder for Cache {
         if pushed { self.stack.pop().unwrap(); }
         if parent_pushed { self.parent_stack.pop().unwrap(); }
         self.privmod = orig_privmod;
+        self.parent_is_trait_impl = orig_parent_is_trait_impl;
         return ret;
     }
 }
@@ -1387,7 +1383,7 @@ impl Context {
                         let js_dst = this.dst.join("sidebar-items.js");
                         let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst));
                         try_err!(write!(&mut js_out, "initSidebarItems({});",
-                                    json::as_json(&items)), &js_dst);
+                                    as_json(&items)), &js_dst);
                     }
 
                     for item in m.items {
@@ -1501,9 +1497,11 @@ impl<'a> Item<'a> {
                           true, |component| {
                 path.push(component.to_string());
             });
+
             // If the span points into an external macro the
             // source-file will be bogus, i.e `<foo macros>`
-            if Path::new(&self.item.source.filename).is_file() {
+            let filename = &self.item.source.filename;
+            if !(filename.starts_with("<") && filename.ends_with("macros>")) {
                 Some(format!("{root}src/{krate}/{path}.html#{href}",
                              root = self.cx.root_path,
                              krate = self.cx.layout.krate,
@@ -1659,8 +1657,8 @@ fn shorter<'a>(s: Option<&'a str>) -> String {
 
 #[inline]
 fn plain_summary_line(s: Option<&str>) -> String {
-    let md = markdown::plain_summary_line(s.unwrap_or(""));
-    shorter(Some(&md)).replace("\n", " ")
+    let line = shorter(s).replace("\n", " ");
+    markdown::plain_summary_line(&line[..])
 }
 
 fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Result {
@@ -2746,18 +2744,19 @@ fn make_item_keywords(it: &clean::Item) -> String {
 
 fn get_index_search_type(item: &clean::Item,
                          parent: Option<String>) -> Option<IndexItemFunctionType> {
-    let decl = match item.inner {
-        clean::FunctionItem(ref f) => &f.decl,
-        clean::MethodItem(ref m) => &m.decl,
-        clean::TyMethodItem(ref m) => &m.decl,
+    let (decl, selfty) = match item.inner {
+        clean::FunctionItem(ref f) => (&f.decl, None),
+        clean::MethodItem(ref m) => (&m.decl, Some(&m.self_)),
+        clean::TyMethodItem(ref m) => (&m.decl, Some(&m.self_)),
         _ => return None
     };
 
     let mut inputs = Vec::new();
 
     // Consider `self` an argument as well.
-    if let Some(name) = parent {
-        inputs.push(Type { name: Some(name.to_ascii_lowercase()) });
+    match parent.and_then(|p| selfty.map(|s| (p, s)) ) {
+        Some((_, &clean::SelfStatic)) | None => (),
+        Some((name, _)) => inputs.push(Type { name: Some(name.to_ascii_lowercase()) }),
     }
 
     inputs.extend(&mut decl.inputs.values.iter().map(|arg| {
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 8844ed82bb5..f3efbcb1db3 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -280,7 +280,7 @@
                 var parts = val.split("->").map(trimmer);
                 var input = parts[0];
                 // sort inputs so that order does not matter
-                var inputs = input.split(",").map(trimmer).sort();
+                var inputs = input.split(",").map(trimmer).sort().toString();
                 var output = parts[1];
 
                 for (var i = 0; i < nSearchWords; ++i) {
@@ -296,8 +296,8 @@
 
                     // allow searching for void (no output) functions as well
                     var typeOutput = type.output ? type.output.name : "";
-                    if (inputs.toString() === typeInputs.toString() &&
-                        output == typeOutput) {
+                    if ((inputs === "*" || inputs === typeInputs.toString()) &&
+                        (output === "*" || output == typeOutput)) {
                         results.push({id: i, index: -1, dontValidate: true});
                     }
                 }
@@ -580,6 +580,9 @@
                         displayPath = "";
                         href = rootPath + item.path.replace(/::/g, '/') +
                                '/' + type + '.' + name + '.html';
+                    } else if (type === "externcrate") {
+                        displayPath = "";
+                        href = rootPath + name + '/index.html';
                     } else if (item.parent !== undefined) {
                         var myparent = item.parent;
                         var anchor = '#' + type + '.' + name;
@@ -678,6 +681,16 @@
             for (var crate in rawSearchIndex) {
                 if (!rawSearchIndex.hasOwnProperty(crate)) { continue; }
 
+                searchWords.push(crate);
+                searchIndex.push({
+                    crate: crate,
+                    ty: 1, // == ExternCrate
+                    name: crate,
+                    path: "",
+                    desc: rawSearchIndex[crate].doc,
+                    type: null,
+                });
+
                 // an array of [(Number) item type,
                 //              (String) name,
                 //              (String) full path or empty string for previous path,
diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css
index 02bb5221886..5c073860f08 100644
--- a/src/librustdoc/html/static/styles/main.css
+++ b/src/librustdoc/html/static/styles/main.css
@@ -82,7 +82,7 @@ pre {
 }
 
 .content a.primitive { color: #39a7bf; }
-.content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
+.content span.externcrate, span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
 .content span.fn, .content a.fn, .block a.current.fn,
 .content span.method, .content a.method, .block a.current.method,
 .content span.tymethod, .content a.tymethod, .block a.current.tymethod,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 6cad0d7d940..ffb15d157b0 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -385,9 +385,8 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
         *s.borrow_mut() = analysis.take();
     });
 
-    match matches.opt_str("crate-name") {
-        Some(name) => krate.name = name,
-        None => {}
+    if let Some(name) = matches.opt_str("crate-name") {
+        krate.name = name
     }
 
     // Process all of the crate attributes, extracting plugin metadata along
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index 2310a8237f4..b95eddbc661 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -1227,7 +1227,7 @@ impl<'a> Index<&'a str>  for Json {
 impl Index<usize> for Json {
     type Output = Json;
 
-    fn index<'a>(&'a self, idx: usize) -> &'a Json {
+    fn index(&self, idx: usize) -> &Json {
         match *self {
             Json::Array(ref v) => &v[idx],
             _ => panic!("can only index Json with usize if it is an array")
@@ -1309,7 +1309,7 @@ impl Stack {
     /// Provides access to the StackElement at a given index.
     /// lower indices are at the bottom of the stack while higher indices are
     /// at the top.
-    pub fn get<'l>(&'l self, idx: usize) -> StackElement<'l> {
+    pub fn get(&self, idx: usize) -> StackElement {
         match self.stack[idx] {
             InternalIndex(i) => StackElement::Index(i),
             InternalKey(start, size) => {
@@ -1351,7 +1351,7 @@ impl Stack {
     }
 
     /// Returns the top-most element (if any).
-    pub fn top<'l>(&'l self) -> Option<StackElement<'l>> {
+    pub fn top(&self) -> Option<StackElement> {
         match self.stack.last() {
             None => None,
             Some(&InternalIndex(i)) => Some(StackElement::Index(i)),
@@ -1463,7 +1463,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
 
     /// Provides access to the current position in the logical structure of the
     /// JSON stream.
-    pub fn stack<'l>(&'l self) -> &'l Stack {
+    pub fn stack(&self) -> &Stack {
         &self.stack
     }
 
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 390c64d7408..29bd28b6160 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -18,7 +18,6 @@ collections = { path = "../libcollections" }
 core = { path = "../libcore" }
 libc = { path = "../rustc/libc_shim" }
 rand = { path = "../librand" }
-rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_unicode = { path = "../librustc_unicode" }
 
 [build-dependencies]
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 586fafc2b4a..051829fbafb 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1157,9 +1157,10 @@ impl<K, V, S> HashMap<K, V, S>
     ///
     /// If the map did not have this key present, `None` is returned.
     ///
-    /// If the map did have this key present, the key is not updated, the
-    /// value is updated and the old value is returned.
-    /// See the [module-level documentation] for more.
+    /// If the map did have this key present, the value is updated, and the old
+    /// value is returned. The key is not updated, though; this matters for
+    /// types that can be `==` without being identical. See the [module-level
+    /// documentation] for more.
     ///
     /// [module-level documentation]: index.html#insert-and-complex-keys
     ///
@@ -1401,13 +1402,13 @@ pub enum Entry<'a, K: 'a, V: 'a> {
     /// An occupied Entry.
     #[stable(feature = "rust1", since = "1.0.0")]
     Occupied(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] OccupiedEntry<'a, K, V>
+        #[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V>
     ),
 
     /// A vacant Entry.
     #[stable(feature = "rust1", since = "1.0.0")]
     Vacant(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] VacantEntry<'a, K, V>
+        #[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V>
     ),
 }
 
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 316c7595266..97cab94b67b 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -12,6 +12,7 @@ use alloc::heap::{allocate, deallocate, EMPTY};
 
 use cmp;
 use hash::{Hash, Hasher, BuildHasher};
+use intrinsics::needs_drop;
 use marker;
 use mem::{align_of, size_of};
 use mem;
@@ -1009,7 +1010,9 @@ impl<K, V> Drop for RawTable<K, V> {
         // dropping empty tables such as on resize.
         // Also avoid double drop of elements that have been already moved out.
         unsafe {
-            for _ in self.rev_move_buckets() {}
+            if needs_drop::<(K, V)>() { // avoid linear runtime for types that don't need drop
+                for _ in self.rev_move_buckets() {}
+            }
         }
 
         let hashes_size = self.capacity * size_of::<u64>();
diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs
index 417261cf4c3..06c14157606 100644
--- a/src/libstd/collections/mod.rs
+++ b/src/libstd/collections/mod.rs
@@ -397,12 +397,15 @@
 //! }
 //!
 //! let mut map = BTreeMap::new();
-//! map.insert(Foo { a: 1, b: "baz" }, ());
+//! map.insert(Foo { a: 1, b: "baz" }, 99);
 //!
 //! // We already have a Foo with an a of 1, so this will be updating the value.
-//! map.insert(Foo { a: 1, b: "xyz" }, ());
+//! map.insert(Foo { a: 1, b: "xyz" }, 100);
 //!
-//! // ... but the key hasn't changed. b is still "baz", not "xyz"
+//! // The value has been updated...
+//! assert_eq!(map.values().next().unwrap(), &100);
+//!
+//! // ...but the key hasn't changed. b is still "baz", not "xyz".
 //! assert_eq!(map.keys().next().unwrap().b, "baz");
 //! ```
 
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index fa48efb2788..749e58c1196 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -218,7 +218,7 @@ pub enum VarError {
     /// valid unicode data. The found data is returned as a payload of this
     /// variant.
     #[stable(feature = "env", since = "1.0.0")]
-    NotUnicode(#[cfg_attr(not(stage0), stable(feature = "env", since = "1.0.0"))] OsString),
+    NotUnicode(#[stable(feature = "env", since = "1.0.0")] OsString),
 }
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -441,8 +441,8 @@ impl Error for JoinPathsError {
 /// use std::env;
 ///
 /// match env::home_dir() {
-///     Some(ref p) => println!("{}", p.display()),
-///     None => println!("Impossible to get your home dir!")
+///     Some(path) => println!("{}", path.display()),
+///     None => println!("Impossible to get your home dir!"),
 /// }
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
@@ -482,8 +482,7 @@ pub fn temp_dir() -> PathBuf {
     os_imp::temp_dir()
 }
 
-/// Returns the filesystem path to the current executable which is running but
-/// with the executable name.
+/// Returns the full filesystem path to the current running executable.
 ///
 /// The path returned is not necessarily a "real path" to the executable as
 /// there may be intermediate symlinks.
@@ -492,7 +491,7 @@ pub fn temp_dir() -> PathBuf {
 ///
 /// Acquiring the path to the current executable is a platform-specific operation
 /// that can fail for a good number of reasons. Some errors can include, but not
-/// be limited to filesystem operations failing or general syscall failures.
+/// be limited to, filesystem operations failing or general syscall failures.
 ///
 /// # Examples
 ///
@@ -528,13 +527,13 @@ pub struct ArgsOs { inner: os_imp::Args }
 /// via the command line).
 ///
 /// The first element is traditionally the path to the executable, but it can be
-/// set to arbitrary text, and it may not even exist, so this property should
+/// set to arbitrary text, and may not even exist. This means this property should
 /// not be relied upon for security purposes.
 ///
 /// # Panics
 ///
 /// The returned iterator will panic during iteration if any argument to the
-/// process is not valid unicode. If this is not desired it is recommended to
+/// process is not valid unicode. If this is not desired,
 /// use the `args_os` function instead.
 ///
 /// # Examples
@@ -603,7 +602,7 @@ impl ExactSizeIterator for ArgsOs {
 /// Constants associated with the current target
 #[stable(feature = "env", since = "1.0.0")]
 pub mod consts {
-    /// A string describing the architecture of the CPU that this is currently
+    /// A string describing the architecture of the CPU that is currently
     /// in use.
     ///
     /// Some possible values:
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index ee744b868dd..1db45764552 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -436,6 +436,57 @@ impl CStr {
         mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
     }
 
+    /// Creates a C string wrapper from a byte slice.
+    ///
+    /// This function will cast the provided `bytes` to a `CStr` wrapper after
+    /// ensuring that it is null terminated and does not contain any interior
+    /// nul bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(cstr_from_bytes)]
+    /// use std::ffi::CStr;
+    ///
+    /// # fn main() {
+    /// let cstr = CStr::from_bytes_with_nul(b"hello\0");
+    /// assert!(cstr.is_some());
+    /// # }
+    /// ```
+    #[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")]
+    pub fn from_bytes_with_nul(bytes: &[u8]) -> Option<&CStr> {
+        if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) {
+            None
+        } else {
+            Some(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
+        }
+    }
+
+    /// Unsafely creates a C string wrapper from a byte slice.
+    ///
+    /// This function will cast the provided `bytes` to a `CStr` wrapper without
+    /// performing any sanity checks. The provided slice must be null terminated
+    /// and not contain any interior nul bytes.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(cstr_from_bytes)]
+    /// use std::ffi::{CStr, CString};
+    ///
+    /// # fn main() {
+    /// unsafe {
+    ///     let cstring = CString::new("hello").unwrap();
+    ///     let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
+    ///     assert_eq!(cstr, &*cstring);
+    /// }
+    /// # }
+    /// ```
+    #[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")]
+    pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
+        mem::transmute(bytes)
+    }
+
     /// Returns the inner pointer to this C string.
     ///
     /// The returned pointer will be valid for as long as `self` is and points
@@ -670,4 +721,31 @@ mod tests {
 
         assert_eq!(cstr_hash, cstring_hash);
     }
+
+    #[test]
+    fn from_bytes_with_nul() {
+        let data = b"123\0";
+        let cstr = CStr::from_bytes_with_nul(data);
+        assert_eq!(cstr.map(CStr::to_bytes), Some(&b"123"[..]));
+        assert_eq!(cstr.map(CStr::to_bytes_with_nul), Some(&b"123\0"[..]));
+
+        unsafe {
+            let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data);
+            assert_eq!(cstr, Some(cstr_unchecked));
+        }
+    }
+
+    #[test]
+    fn from_bytes_with_nul_unterminated() {
+        let data = b"123";
+        let cstr = CStr::from_bytes_with_nul(data);
+        assert!(cstr.is_none());
+    }
+
+    #[test]
+    fn from_bytes_with_nul_interior() {
+        let data = b"1\023\0";
+        let cstr = CStr::from_bytes_with_nul(data);
+        assert!(cstr.is_none());
+    }
 }
diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs
index eb5ddecbd05..cf4f4bdf291 100644
--- a/src/libstd/ffi/os_str.rs
+++ b/src/libstd/ffi/os_str.rs
@@ -102,6 +102,58 @@ impl OsString {
     pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
         self.inner.push_slice(&s.as_ref().inner)
     }
+
+    /// Creates a new `OsString` with the given capacity. The string will be
+    /// able to hold exactly `capacity` bytes without reallocating. If
+    /// `capacity` is 0, the string will not allocate.
+    ///
+    /// See main `OsString` documentation information about encoding.
+    #[unstable(feature = "osstring_simple_functions",
+               reason = "recently added", issue = "29453")]
+    pub fn with_capacity(capacity: usize) -> OsString {
+        OsString {
+            inner: Buf::with_capacity(capacity)
+        }
+    }
+
+    /// Truncates the `OsString` to zero length.
+    #[unstable(feature = "osstring_simple_functions",
+               reason = "recently added", issue = "29453")]
+    pub fn clear(&mut self) {
+        self.inner.clear()
+    }
+
+    /// Returns the number of bytes this `OsString` can hold without
+    /// reallocating.
+    ///
+    /// See `OsString` introduction for information about encoding.
+    #[unstable(feature = "osstring_simple_functions",
+               reason = "recently added", issue = "29453")]
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
+    }
+
+    /// Reserves capacity for at least `additional` more bytes to be inserted
+    /// in the given `OsString`. The collection may reserve more space to avoid
+    /// frequent reallocations.
+    #[unstable(feature = "osstring_simple_functions",
+               reason = "recently added", issue = "29453")]
+    pub fn reserve(&mut self, additional: usize) {
+        self.inner.reserve(additional)
+    }
+
+    /// Reserves the minimum capacity for exactly `additional` more bytes to be
+    /// inserted in the given `OsString`. Does nothing if the capacity is
+    /// already sufficient.
+    ///
+    /// Note that the allocator may give the collection more space than it
+    /// requests. Therefore capacity can not be relied upon to be precisely
+    /// minimal. Prefer reserve if future insertions are expected.
+    #[unstable(feature = "osstring_simple_functions",
+               reason = "recently added", issue = "29453")]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.inner.reserve_exact(additional)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -277,6 +329,22 @@ impl OsStr {
         self.to_bytes().and_then(|b| CString::new(b).ok())
     }
 
+    /// Checks whether the `OsStr` is empty.
+    #[unstable(feature = "osstring_simple_functions",
+               reason = "recently added", issue = "29453")]
+    pub fn is_empty(&self) -> bool {
+        self.inner.inner.is_empty()
+    }
+
+    /// Returns the number of bytes in this `OsStr`.
+    ///
+    /// See `OsStr` introduction for information about encoding.
+    #[unstable(feature = "osstring_simple_functions",
+               reason = "recently added", issue = "29453")]
+    pub fn len(&self) -> usize {
+        self.inner.inner.len()
+    }
+
     /// Gets the underlying byte representation.
     ///
     /// Note: it is *crucial* that this API is private, to avoid
@@ -343,6 +411,44 @@ impl Ord for OsStr {
     fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
 }
 
+macro_rules! impl_cmp {
+    ($lhs:ty, $rhs: ty) => {
+        #[stable(feature = "cmp_os_str", since = "1.8.0")]
+        impl<'a, 'b> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
+        }
+
+        #[stable(feature = "cmp_os_str", since = "1.8.0")]
+        impl<'a, 'b> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool { <OsStr as PartialEq>::eq(self, other) }
+        }
+
+        #[stable(feature = "cmp_os_str", since = "1.8.0")]
+        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
+                <OsStr as PartialOrd>::partial_cmp(self, other)
+            }
+        }
+
+        #[stable(feature = "cmp_os_str", since = "1.8.0")]
+        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
+                <OsStr as PartialOrd>::partial_cmp(self, other)
+            }
+        }
+    }
+}
+
+impl_cmp!(OsString, OsStr);
+impl_cmp!(OsString, &'a OsStr);
+impl_cmp!(Cow<'a, OsStr>, OsStr);
+impl_cmp!(Cow<'a, OsStr>, &'b OsStr);
+impl_cmp!(Cow<'a, OsStr>, OsString);
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Hash for OsStr {
     #[inline]
@@ -414,3 +520,113 @@ impl AsInner<Slice> for OsStr {
         &self.inner
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use sys_common::{AsInner, IntoInner};
+
+    #[test]
+    fn test_os_string_with_capacity() {
+        let os_string = OsString::with_capacity(0);
+        assert_eq!(0, os_string.inner.into_inner().capacity());
+
+        let os_string = OsString::with_capacity(10);
+        assert_eq!(10, os_string.inner.into_inner().capacity());
+
+        let mut os_string = OsString::with_capacity(0);
+        os_string.push("abc");
+        assert!(os_string.inner.into_inner().capacity() >= 3);
+    }
+
+    #[test]
+    fn test_os_string_clear() {
+        let mut os_string = OsString::from("abc");
+        assert_eq!(3, os_string.inner.as_inner().len());
+
+        os_string.clear();
+        assert_eq!(&os_string, "");
+        assert_eq!(0, os_string.inner.as_inner().len());
+    }
+
+    #[test]
+    fn test_os_string_capacity() {
+        let os_string = OsString::with_capacity(0);
+        assert_eq!(0, os_string.capacity());
+
+        let os_string = OsString::with_capacity(10);
+        assert_eq!(10, os_string.capacity());
+
+        let mut os_string = OsString::with_capacity(0);
+        os_string.push("abc");
+        assert!(os_string.capacity() >= 3);
+    }
+
+    #[test]
+    fn test_os_string_reserve() {
+        let mut os_string = OsString::new();
+        assert_eq!(os_string.capacity(), 0);
+
+        os_string.reserve(2);
+        assert!(os_string.capacity() >= 2);
+
+        for _ in 0..16 {
+            os_string.push("a");
+        }
+
+        assert!(os_string.capacity() >= 16);
+        os_string.reserve(16);
+        assert!(os_string.capacity() >= 32);
+
+        os_string.push("a");
+
+        os_string.reserve(16);
+        assert!(os_string.capacity() >= 33)
+    }
+
+    #[test]
+    fn test_os_string_reserve_exact() {
+        let mut os_string = OsString::new();
+        assert_eq!(os_string.capacity(), 0);
+
+        os_string.reserve_exact(2);
+        assert!(os_string.capacity() >= 2);
+
+        for _ in 0..16 {
+            os_string.push("a");
+        }
+
+        assert!(os_string.capacity() >= 16);
+        os_string.reserve_exact(16);
+        assert!(os_string.capacity() >= 32);
+
+        os_string.push("a");
+
+        os_string.reserve_exact(16);
+        assert!(os_string.capacity() >= 33)
+    }
+
+    #[test]
+    fn test_os_str_is_empty() {
+        let mut os_string = OsString::new();
+        assert!(os_string.is_empty());
+
+        os_string.push("abc");
+        assert!(!os_string.is_empty());
+
+        os_string.clear();
+        assert!(os_string.is_empty());
+    }
+
+    #[test]
+    fn test_os_str_len() {
+        let mut os_string = OsString::new();
+        assert_eq!(0, os_string.len());
+
+        os_string.push("abc");
+        assert_eq!(3, os_string.len());
+
+        os_string.clear();
+        assert_eq!(0, os_string.len());
+    }
+}
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index 4573f465819..420fede34d2 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -256,7 +256,7 @@ impl Write for Cursor<Vec<u8>> {
             let pos = pos as usize;
             let space = self.inner.len() - pos;
             let (left, right) = buf.split_at(cmp::min(space, buf.len()));
-            self.inner[pos..pos + left.len()].clone_from_slice(left);
+            self.inner[pos..pos + left.len()].copy_from_slice(left);
             self.inner.extend_from_slice(right);
         }
 
diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs
index 592e16b0a3c..ec63f14d453 100644
--- a/src/libstd/io/impls.rs
+++ b/src/libstd/io/impls.rs
@@ -156,7 +156,7 @@ impl<'a> Read for &'a [u8] {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         let amt = cmp::min(buf.len(), self.len());
         let (a, b) = self.split_at(amt);
-        buf[..amt].clone_from_slice(a);
+        buf[..amt].copy_from_slice(a);
         *self = b;
         Ok(amt)
     }
@@ -168,7 +168,7 @@ impl<'a> Read for &'a [u8] {
                                   "failed to fill whole buffer"));
         }
         let (a, b) = self.split_at(buf.len());
-        buf.clone_from_slice(a);
+        buf.copy_from_slice(a);
         *self = b;
         Ok(())
     }
@@ -189,7 +189,7 @@ impl<'a> Write for &'a mut [u8] {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         let amt = cmp::min(data.len(), self.len());
         let (a, b) = mem::replace(self, &mut []).split_at_mut(amt);
-        a.clone_from_slice(&data[..amt]);
+        a.copy_from_slice(&data[..amt]);
         *self = b;
         Ok(amt)
     }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index abb47b69418..61334f30924 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1055,7 +1055,14 @@ pub trait Write {
         let mut output = Adaptor { inner: self, error: Ok(()) };
         match fmt::write(&mut output, fmt) {
             Ok(()) => Ok(()),
-            Err(..) => output.error
+            Err(..) => {
+                // check if the error came from the underlying `Write` or not
+                if output.error.is_err() {
+                    output.error
+                } else {
+                    Err(Error::new(ErrorKind::Other, "formatter error"))
+                }
+            }
         }
     }
 
@@ -1175,7 +1182,7 @@ pub trait Seek {
 pub enum SeekFrom {
     /// Set the offset to the provided number of bytes.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Start(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u64),
+    Start(#[stable(feature = "rust1", since = "1.0.0")] u64),
 
     /// Set the offset to the size of this object plus the specified number of
     /// bytes.
@@ -1183,7 +1190,7 @@ pub enum SeekFrom {
     /// It is possible to seek beyond the end of an object, but it's an error to
     /// seek before byte 0.
     #[stable(feature = "rust1", since = "1.0.0")]
-    End(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] i64),
+    End(#[stable(feature = "rust1", since = "1.0.0")] i64),
 
     /// Set the offset to the current position plus the specified number of
     /// bytes.
@@ -1191,7 +1198,7 @@ pub enum SeekFrom {
     /// It is possible to seek beyond the end of an object, but it's an error to
     /// seek before byte 0.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Current(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] i64),
+    Current(#[stable(feature = "rust1", since = "1.0.0")] i64),
 }
 
 fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>)
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 416c01b539f..e062f9040af 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -222,10 +222,10 @@
 #![feature(collections)]
 #![feature(collections_bound)]
 #![feature(const_fn)]
+#![feature(copy_from_slice)]
 #![feature(core_float)]
 #![feature(core_intrinsics)]
 #![feature(decode_utf16)]
-#![feature(drop_in_place)]
 #![feature(dropck_parametricity)]
 #![feature(float_extras)]
 #![feature(float_from_str_radix)]
@@ -269,6 +269,10 @@
 #![feature(vec_push_all)]
 #![feature(zero_one)]
 
+// Issue# 30592: Systematically use alloc_system during stage0 since jemalloc
+// might be unavailable or disabled
+#![cfg_attr(stage0, feature(alloc_system))]
+
 // Don't link to std. We are std.
 #![no_std]
 
@@ -295,6 +299,9 @@ extern crate alloc;
 extern crate rustc_unicode;
 extern crate libc;
 
+#[cfg(stage0)]
+extern crate alloc_system;
+
 // Make std testable by not duplicating lang items and other globals. See #2912
 #[cfg(test)] extern crate std as realstd;
 
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index 89c51c70843..78da9412212 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -32,10 +32,10 @@ use slice;
 pub enum SocketAddr {
     /// An IPv4 socket address which is a (ip, port) combination.
     #[stable(feature = "rust1", since = "1.0.0")]
-    V4(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] SocketAddrV4),
+    V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
     /// An IPv6 socket address
     #[stable(feature = "rust1", since = "1.0.0")]
-    V6(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] SocketAddrV6),
+    V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
 }
 
 /// An IPv4 socket address which is a (ip, port) combination.
@@ -467,9 +467,8 @@ impl ToSocketAddrs for str {
     type Iter = vec::IntoIter<SocketAddr>;
     fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
         // try to parse as a regular SocketAddr first
-        match self.parse().ok() {
-            Some(addr) => return Ok(vec![addr].into_iter()),
-            None => {}
+        if let Some(addr) = self.parse().ok() {
+            return Ok(vec![addr].into_iter());
         }
 
         macro_rules! try_opt {
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index 8a4d7e3e2c2..68075af61cf 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -27,10 +27,10 @@ use sys_common::{AsInner, FromInner};
 pub enum IpAddr {
     /// Representation of an IPv4 address.
     #[stable(feature = "ip_addr", since = "1.7.0")]
-    V4(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.7.0"))] Ipv4Addr),
+    V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
     /// Representation of an IPv6 address.
     #[stable(feature = "ip_addr", since = "1.7.0")]
-    V6(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.7.0"))] Ipv6Addr),
+    V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
 }
 
 /// Representation of an IPv4 address.
diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs
index 46a0309dbb5..5851ce7135d 100644
--- a/src/libstd/net/parser.rs
+++ b/src/libstd/net/parser.rs
@@ -66,9 +66,8 @@ impl<'a> Parser<'a> {
     fn read_or<T>(&mut self, parsers: &mut [Box<FnMut(&mut Parser) -> Option<T> + 'static>])
                -> Option<T> {
         for pf in parsers {
-            match self.read_atomically(|p: &mut Parser| pf(p)) {
-                Some(r) => return Some(r),
-                None => {}
+            if let Some(r) = self.read_atomically(|p: &mut Parser| pf(p)) {
+                return Some(r);
             }
         }
         None
@@ -192,8 +191,8 @@ impl<'a> Parser<'a> {
         fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> Ipv6Addr {
             assert!(head.len() + tail.len() <= 8);
             let mut gs = [0; 8];
-            gs[..head.len()].clone_from_slice(head);
-            gs[(8 - tail.len()) .. 8].clone_from_slice(tail);
+            gs[..head.len()].copy_from_slice(head);
+            gs[(8 - tail.len()) .. 8].copy_from_slice(tail);
             Ipv6Addr::new(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
         }
 
diff --git a/src/libstd/os/dragonfly/raw.rs b/src/libstd/os/dragonfly/raw.rs
index f3bde9cd1f3..83e0be0d158 100644
--- a/src/libstd/os/dragonfly/raw.rs
+++ b/src/libstd/os/dragonfly/raw.rs
@@ -19,7 +19,6 @@
 #![allow(deprecated)]
 
 use os::raw::c_long;
-use os::unix::raw::{uid_t, gid_t};
 
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
@@ -52,17 +51,17 @@ pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_rdev: u32,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_atime: i64,
+    pub st_atime: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_atime_nsec: i64,
+    pub st_atime_nsec: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mtime: i64,
+    pub st_mtime: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_mtime_nsec: i64,
+    pub st_mtime_nsec: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ctime: i64,
+    pub st_ctime: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_ctime_nsec: i64,
+    pub st_ctime_nsec: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_size: i64,
     #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -76,7 +75,7 @@ pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_lspare: i32,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_birthtime: i64,
+    pub st_birthtime: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_birthtime_nsec: i64,
+    pub st_birthtime_nsec: c_long,
 }
diff --git a/src/libstd/os/freebsd/raw.rs b/src/libstd/os/freebsd/raw.rs
index 073ddf10d1c..989eef63d82 100644
--- a/src/libstd/os/freebsd/raw.rs
+++ b/src/libstd/os/freebsd/raw.rs
@@ -18,134 +18,67 @@
                               definitions")]
 #![allow(deprecated)]
 
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
+use os::raw::c_long;
+
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type nlink_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = u64;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type off_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
 #[unstable(feature = "pthread_t", issue = "29791")] pub type pthread_t = usize;
 
-#[doc(inline)]
+#[repr(C)]
+#[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
-pub use self::arch::{stat, time_t};
-
-#[cfg(target_arch = "x86")]
-mod arch {
-    use super::{off_t, dev_t, ino_t, mode_t, nlink_t, blksize_t, blkcnt_t, fflags_t};
-    use os::raw::c_long;
-    use os::unix::raw::{uid_t, gid_t};
-
-    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
-
-    #[repr(C)]
-    #[derive(Clone)]
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub struct stat {
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_dev: dev_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ino: ino_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mode: mode_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_nlink: nlink_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_uid: uid_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_gid: gid_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_rdev: dev_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime: time_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime_nsec: c_long,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime: time_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime_nsec: c_long,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime: time_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime_nsec: c_long,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_size: off_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blocks: blkcnt_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blksize: blksize_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_flags: fflags_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_gen: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_lspare: i32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_birthtime: time_t,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_birthtime_nsec: c_long,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub __unused: [u8; 8],
-    }
-}
-
-#[cfg(target_arch = "x86_64")]
-mod arch {
-    use super::{off_t, dev_t, ino_t, mode_t, nlink_t, blksize_t, blkcnt_t, fflags_t};
-    use os::raw::c_long;
-    use os::unix::raw::{uid_t, gid_t};
-
-    #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
-
-    #[repr(C)]
-    #[derive(Clone)]
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub struct stat {
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_dev: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ino: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mode: u16,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_nlink: u16,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_uid: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_gid: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_rdev: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime_nsec: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime_nsec: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime_nsec: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_size: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blocks: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blksize: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_flags: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_gen: u32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_lspare: i32,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_birthtime: i64,
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_birthtime_nsec: i64,
-    }
+pub struct stat {
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_dev: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ino: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mode: u16,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_nlink: u16,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_uid: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gid: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_rdev: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_size: i64,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blocks: i64,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blksize: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_flags: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gen: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_lspare: i32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime_nsec: c_long,
+    #[cfg(target_arch = "x86")]
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub __unused: [u8; 8],
 }
-
diff --git a/src/libstd/os/netbsd/fs.rs b/src/libstd/os/netbsd/fs.rs
index f11e23138b0..cd7d5fafd1c 100644
--- a/src/libstd/os/netbsd/fs.rs
+++ b/src/libstd/os/netbsd/fs.rs
@@ -74,8 +74,6 @@ pub trait MetadataExt {
     fn st_flags(&self) -> u32;
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_gen(&self) -> u32;
-    #[stable(feature = "metadata_ext2", since = "1.8.0")]
-    fn st_spare(&self) -> u32;
 }
 
 #[stable(feature = "metadata_ext", since = "1.1.0")]
@@ -115,25 +113,25 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_atime as i64
     }
     fn st_atime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_atime_nsec as i64
+        self.as_inner().as_inner().st_atimensec as i64
     }
     fn st_mtime(&self) -> i64 {
         self.as_inner().as_inner().st_mtime as i64
     }
     fn st_mtime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_mtime_nsec as i64
+        self.as_inner().as_inner().st_mtimensec as i64
     }
     fn st_ctime(&self) -> i64 {
         self.as_inner().as_inner().st_ctime as i64
     }
     fn st_ctime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_ctime_nsec as i64
+        self.as_inner().as_inner().st_ctimensec as i64
     }
     fn st_birthtime(&self) -> i64 {
         self.as_inner().as_inner().st_birthtime as i64
     }
     fn st_birthtime_nsec(&self) -> i64 {
-        self.as_inner().as_inner().st_birthtime_nsec as i64
+        self.as_inner().as_inner().st_birthtimensec as i64
     }
     fn st_blksize(&self) -> u64 {
         self.as_inner().as_inner().st_blksize as u64
@@ -147,8 +145,5 @@ impl MetadataExt for Metadata {
     fn st_flags(&self) -> u32 {
         self.as_inner().as_inner().st_flags as u32
     }
-    fn st_spare(&self) -> u32 {
-        self.as_inner().as_inner().st_spare as u32
-    }
 }
 
diff --git a/src/libstd/os/netbsd/raw.rs b/src/libstd/os/netbsd/raw.rs
index 7eb3f6d47d1..bc30c1a7f48 100644
--- a/src/libstd/os/netbsd/raw.rs
+++ b/src/libstd/os/netbsd/raw.rs
@@ -46,9 +46,9 @@ pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_nlink: u32,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_uid: u32,
+    pub st_uid: uid_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_gid: u32,
+    pub st_gid: gid_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_rdev: u64,
     #[stable(feature = "raw_ext", since = "1.1.0")]
diff --git a/src/libstd/os/solaris/fs.rs b/src/libstd/os/solaris/fs.rs
index 1c043af735a..5dc43d03a86 100644
--- a/src/libstd/os/solaris/fs.rs
+++ b/src/libstd/os/solaris/fs.rs
@@ -73,7 +73,7 @@ impl MetadataExt for Metadata {
     #[allow(deprecated)]
     fn as_raw_stat(&self) -> &raw::stat {
         unsafe {
-            &*(self.as_inner().as_inner() as *const libc::stat64
+            &*(self.as_inner().as_inner() as *const libc::stat
                                           as *const raw::stat)
         }
     }
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index 83df54f1830..69a1b57a0c5 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -193,6 +193,12 @@ impl<T> AssertRecoverSafe<T> {
     pub fn new(t: T) -> AssertRecoverSafe<T> {
         AssertRecoverSafe(t)
     }
+
+    /// Consumes the `AssertRecoverSafe`, returning the wrapped value.
+    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
+    pub fn into_inner(self) -> T {
+        self.0
+    }
 }
 
 impl<T> Deref for AssertRecoverSafe<T> {
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 10ecaed3aef..94967bfb96a 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -226,7 +226,7 @@ mod platform {
                     }
                     _ => (),
                 }
-            } else if path.len() > 1 && path[1] == b':' {
+            } else if path.get(1) == Some(& b':') {
                 // C:
                 let c = path[0];
                 if c.is_ascii() && (c as char).is_alphabetic() {
@@ -268,33 +268,33 @@ mod platform {
 pub enum Prefix<'a> {
     /// Prefix `\\?\`, together with the given component immediately following it.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Verbatim(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr),
+    Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
 
     /// Prefix `\\?\UNC\`, with the "server" and "share" components following it.
     #[stable(feature = "rust1", since = "1.0.0")]
     VerbatimUNC(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
+        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
+        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
     ),
 
     /// Prefix like `\\?\C:\`, for the given drive letter
     #[stable(feature = "rust1", since = "1.0.0")]
-    VerbatimDisk(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u8),
+    VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),
 
     /// Prefix `\\.\`, together with the given component immediately following it.
     #[stable(feature = "rust1", since = "1.0.0")]
-    DeviceNS(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr),
+    DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
 
     /// Prefix `\\server\share`, with the given "server" and "share" components.
     #[stable(feature = "rust1", since = "1.0.0")]
     UNC(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr,
+        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
+        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
     ),
 
     /// Prefix `C:` for the given disk drive.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Disk(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] u8),
+    Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),
 }
 
 impl<'a> Prefix<'a> {
@@ -393,11 +393,8 @@ fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>
     loop {
         let mut iter_next = iter.clone();
         match (iter_next.next(), prefix.next()) {
-            (Some(x), Some(y)) => {
-                if x != y {
-                    return None;
-                }
-            }
+            (Some(ref x), Some(ref y)) if x == y => (),
+            (Some(_), Some(_)) => return None,
             (Some(_), None) => return Some(iter),
             (None, None) => return Some(iter),
             (None, Some(_)) => return None,
@@ -537,7 +534,7 @@ pub enum Component<'a> {
     /// Does not occur on Unix.
     #[stable(feature = "rust1", since = "1.0.0")]
     Prefix(
-        #[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] PrefixComponent<'a>
+        #[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>
     ),
 
     /// The root directory component, appears after any prefix and before anything else
@@ -554,7 +551,7 @@ pub enum Component<'a> {
 
     /// A normal component, i.e. `a` and `b` in `a/b`
     #[stable(feature = "rust1", since = "1.0.0")]
-    Normal(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] &'a OsStr),
+    Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
 }
 
 impl<'a> Component<'a> {
@@ -1582,8 +1579,10 @@ impl Path {
 
     /// Returns a path that, when joined onto `base`, yields `self`.
     ///
+    /// # Errors
+    ///
     /// If `base` is not a prefix of `self` (i.e. `starts_with`
-    /// returns false), then `relative_from` returns `None`.
+    /// returns `false`), returns `Err`.
     #[stable(since = "1.7.0", feature = "path_strip_prefix")]
     pub fn strip_prefix<'a, P: ?Sized>(&'a self, base: &'a P)
                                        -> Result<&'a Path, StripPrefixError>
@@ -2002,6 +2001,13 @@ impl AsRef<Path> for OsStr {
     }
 }
 
+#[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
+impl<'a> AsRef<Path> for Cow<'a, OsStr> {
+    fn as_ref(&self) -> &Path {
+        Path::new(self)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<Path> for OsString {
     fn as_ref(&self) -> &Path {
@@ -2044,7 +2050,7 @@ impl<'a> IntoIterator for &'a Path {
     fn into_iter(self) -> Iter<'a> { self.iter() }
 }
 
-macro_rules! impl_eq {
+macro_rules! impl_cmp {
     ($lhs:ty, $rhs: ty) => {
         #[stable(feature = "partialeq_path", since = "1.6.0")]
         impl<'a, 'b> PartialEq<$rhs> for $lhs {
@@ -2058,14 +2064,76 @@ macro_rules! impl_eq {
             fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) }
         }
 
+        #[stable(feature = "cmp_path", since = "1.8.0")]
+        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self, other)
+            }
+        }
+
+        #[stable(feature = "cmp_path", since = "1.8.0")]
+        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self, other)
+            }
+        }
+    }
+}
+
+impl_cmp!(PathBuf, Path);
+impl_cmp!(PathBuf, &'a Path);
+impl_cmp!(Cow<'a, Path>, Path);
+impl_cmp!(Cow<'a, Path>, &'b Path);
+impl_cmp!(Cow<'a, Path>, PathBuf);
+
+macro_rules! impl_cmp_os_str {
+    ($lhs:ty, $rhs: ty) => {
+        #[stable(feature = "cmp_path", since = "1.8.0")]
+        impl<'a, 'b> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other.as_ref()) }
+        }
+
+        #[stable(feature = "cmp_path", since = "1.8.0")]
+        impl<'a, 'b> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self.as_ref(), other) }
+        }
+
+        #[stable(feature = "cmp_path", since = "1.8.0")]
+        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self, other.as_ref())
+            }
+        }
+
+        #[stable(feature = "cmp_path", since = "1.8.0")]
+        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
+            }
+        }
     }
 }
 
-impl_eq!(PathBuf, Path);
-impl_eq!(PathBuf, &'a Path);
-impl_eq!(Cow<'a, Path>, Path);
-impl_eq!(Cow<'a, Path>, &'b Path);
-impl_eq!(Cow<'a, Path>, PathBuf);
+impl_cmp_os_str!(PathBuf, OsStr);
+impl_cmp_os_str!(PathBuf, &'a OsStr);
+impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
+impl_cmp_os_str!(PathBuf, OsString);
+impl_cmp_os_str!(Path, OsStr);
+impl_cmp_os_str!(Path, &'a OsStr);
+impl_cmp_os_str!(Path, Cow<'a, OsStr>);
+impl_cmp_os_str!(Path, OsString);
+impl_cmp_os_str!(&'a Path, OsStr);
+impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
+impl_cmp_os_str!(&'a Path, OsString);
+impl_cmp_os_str!(Cow<'a, Path>, OsStr);
+impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr);
+impl_cmp_os_str!(Cow<'a, Path>, OsString);
 
 #[stable(since = "1.7.0", feature = "strip_prefix")]
 impl fmt::Display for StripPrefixError {
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index ad93fe0094a..839287d1321 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -12,6 +12,50 @@
 //
 /// The boolean type.
 ///
+/// The `bool` represents a value, which could only be either `true` or `false`.
+///
+/// # Basic usage
+///
+/// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
+/// which allow us to perform boolean operations using `&`, `|` and `!`.
+///
+/// [`if`] always demands a `bool` value. [`assert!`], being an important macro in testing,
+/// checks whether an expression returns `true`.
+///
+/// ```
+/// let bool_val = true & false | false;
+/// assert!(!bool_val);
+/// ```
+///
+/// [`assert!`]: std/macro.assert!.html
+/// [`if` conditionals]: ../../book/if.html
+/// [`BitAnd`]: ../ops/trait.BitAnd.html
+/// [`BitOr`]: ../ops/trait.BitOr.html
+/// [`Not`]: ../ops/trait.Not.html
+///
+/// # Examples
+///
+/// A trivial example of the usage of `bool`,
+///
+/// ```
+/// let praise_the_borrow_checker = true;
+///
+/// // using the `if` conditional
+/// if praise_the_borrow_checker {
+///     println!("oh, yeah!");
+/// } else {
+///     println!("what?!!");
+/// }
+///
+/// // ... or, a match pattern
+/// match praise_the_borrow_checker {
+///     true => println!("keep praising!"),
+///     false => println!("you should praise!"),
+/// }
+/// ```
+///
+/// Also, since `bool` implements the [`Copy`](../marker/trait.Copy.html) trait, we don't
+/// have to worry about the move semantics (just like the integer and float primitives).
 mod prim_bool { }
 
 #[doc(primitive = "char")]
@@ -50,18 +94,21 @@ mod prim_bool { }
 /// [`String`]: string/struct.String.html
 ///
 /// As always, remember that a human intuition for 'character' may not map to
-/// Unicode's definitions. For example, emoji symbols such as '❤️' are more than
-/// one byte; ❤️ in particular is six:
+/// Unicode's definitions. For example, emoji symbols such as '❤️' can be more
+/// than one Unicode code point; this ❤️ in particular is two:
 ///
 /// ```
 /// let s = String::from("❤️");
 ///
-/// // six bytes times one byte for each element
-/// assert_eq!(6, s.len() * std::mem::size_of::<u8>());
+/// // we get two chars out of a single ❤️
+/// let mut iter = s.chars();
+/// assert_eq!(Some('\u{2764}'), iter.next());
+/// assert_eq!(Some('\u{fe0f}'), iter.next());
+/// assert_eq!(None, iter.next());
 /// ```
 ///
-/// This also means it won't fit into a `char`, and so trying to create a
-/// literal with `let heart = '❤️';` gives an error:
+/// This means it won't fit into a `char`. Trying to create a literal with
+/// `let heart = '❤️';` gives an error:
 ///
 /// ```text
 /// error: character literal may only contain one codepoint: '❤
@@ -69,8 +116,8 @@ mod prim_bool { }
 ///             ^~
 /// ```
 ///
-/// Another implication of this is that if you want to do per-`char`acter
-/// processing, it can end up using a lot more memory:
+/// Another implication of the 4-byte fixed size of a `char`, is that
+/// per-`char`acter processing can end up using a lot more memory:
 ///
 /// ```
 /// let s = String::from("love: ❤️");
@@ -79,19 +126,6 @@ mod prim_bool { }
 /// assert_eq!(12, s.len() * std::mem::size_of::<u8>());
 /// assert_eq!(32, v.len() * std::mem::size_of::<char>());
 /// ```
-///
-/// Or may give you results you may not expect:
-///
-/// ```
-/// let s = String::from("❤️");
-///
-/// let mut iter = s.chars();
-///
-/// // we get two chars out of a single ❤️
-/// assert_eq!(Some('\u{2764}'), iter.next());
-/// assert_eq!(Some('\u{fe0f}'), iter.next());
-/// assert_eq!(None, iter.next());
-/// ```
 mod prim_char { }
 
 #[doc(primitive = "unit")]
@@ -454,6 +488,9 @@ mod prim_tuple { }
 ///
 /// *[See also the `std::f32` module](f32/index.html).*
 ///
+/// However, please note that examples are shared between the `f64` and `f32`
+/// primitive types. So it's normal if you see usage of `f64` in there.
+///
 mod prim_f32 { }
 
 #[doc(primitive = "f64")]
@@ -462,6 +499,9 @@ mod prim_f32 { }
 ///
 /// *[See also the `std::f64` module](f64/index.html).*
 ///
+/// However, please note that examples are shared between the `f64` and `f32`
+/// primitive types. So it's normal if you see usage of `f32` in there.
+///
 mod prim_f64 { }
 
 #[doc(primitive = "i8")]
@@ -543,4 +583,3 @@ mod prim_isize { }
 /// *[See also the `std::usize` module](usize/index.html).*
 ///
 mod prim_usize { }
-
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 21e60420c18..3f14fcd239f 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -62,6 +62,7 @@ use cell::RefCell;
 use io;
 use mem;
 use rc::Rc;
+use sys;
 
 #[cfg(target_pointer_width = "32")]
 use core_rand::IsaacRng as IsaacWordRng;
@@ -71,9 +72,7 @@ use core_rand::Isaac64Rng as IsaacWordRng;
 pub use core_rand::{Rand, Rng, SeedableRng};
 pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng};
 pub use core_rand::reseeding;
-pub use rand::os::OsRng;
 
-pub mod os;
 pub mod reader;
 
 /// The standard RNG. This is designed to be efficient on the current
@@ -185,3 +184,95 @@ impl Rng for ThreadRng {
         self.rng.borrow_mut().fill_bytes(bytes)
     }
 }
+
+/// A random number generator that retrieves randomness straight from
+/// the operating system. Platform sources:
+///
+/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
+///   `/dev/urandom`, or from `getrandom(2)` system call if available.
+/// - Windows: calls `CryptGenRandom`, using the default cryptographic
+///   service provider with the `PROV_RSA_FULL` type.
+/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
+/// - OpenBSD: uses the `getentropy(2)` system call.
+///
+/// This does not block.
+pub struct OsRng(sys::rand::OsRng);
+
+impl OsRng {
+    /// Create a new `OsRng`.
+    pub fn new() -> io::Result<OsRng> {
+        sys::rand::OsRng::new().map(OsRng)
+    }
+}
+
+impl Rng for OsRng {
+    #[inline]
+    fn next_u32(&mut self) -> u32 {
+        self.0.next_u32()
+    }
+
+    #[inline]
+    fn next_u64(&mut self) -> u64 {
+        self.0.next_u64()
+    }
+
+    #[inline]
+    fn fill_bytes(&mut self, bytes: &mut [u8]) {
+        self.0.fill_bytes(bytes)
+    }
+}
+
+
+#[cfg(test)]
+mod tests {
+    use sync::mpsc::channel;
+    use rand::Rng;
+    use super::OsRng;
+    use thread;
+
+    #[test]
+    fn test_os_rng() {
+        let mut r = OsRng::new().unwrap();
+
+        r.next_u32();
+        r.next_u64();
+
+        let mut v = [0; 1000];
+        r.fill_bytes(&mut v);
+    }
+
+    #[test]
+    fn test_os_rng_tasks() {
+
+        let mut txs = vec!();
+        for _ in 0..20 {
+            let (tx, rx) = channel();
+            txs.push(tx);
+
+            thread::spawn(move|| {
+                // wait until all the threads are ready to go.
+                rx.recv().unwrap();
+
+                // deschedule to attempt to interleave things as much
+                // as possible (XXX: is this a good test?)
+                let mut r = OsRng::new().unwrap();
+                thread::yield_now();
+                let mut v = [0; 1000];
+
+                for _ in 0..100 {
+                    r.next_u32();
+                    thread::yield_now();
+                    r.next_u64();
+                    thread::yield_now();
+                    r.fill_bytes(&mut v);
+                    thread::yield_now();
+                }
+            });
+        }
+
+        // start all the threads
+        for tx in &txs {
+            tx.send(()).unwrap();
+        }
+    }
+}
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 9a786752365..0ff3a690702 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -209,6 +209,9 @@ impl Condvar {
     #[unstable(feature = "wait_timeout_with",
                reason = "unsure if this API is broadly needed or what form it should take",
                issue = "27748")]
+    #[rustc_deprecated(since = "1.8.0",
+                       reason = "wonky signature and questionable \
+                                 implementation didn't justify existence")]
     pub fn wait_timeout_with<'a, T, F>(&self,
                                        guard: MutexGuard<'a, T>,
                                        dur: Duration,
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index 64230c9e016..fadca390986 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -385,12 +385,12 @@ pub enum TrySendError<T> {
     /// this is not a buffered channel, then there is no receiver available to
     /// acquire the data.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Full(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T),
+    Full(#[stable(feature = "rust1", since = "1.0.0")] T),
 
     /// This channel's receiving half has disconnected, so the data could not be
     /// sent. The data is returned back to the callee in this case.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Disconnected(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] T),
+    Disconnected(#[stable(feature = "rust1", since = "1.0.0")] T),
 }
 
 enum Flavor<T> {
@@ -403,10 +403,10 @@ enum Flavor<T> {
 #[doc(hidden)]
 trait UnsafeFlavor<T> {
     fn inner_unsafe(&self) -> &UnsafeCell<Flavor<T>>;
-    unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
+    unsafe fn inner_mut(&self) -> &mut Flavor<T> {
         &mut *self.inner_unsafe().get()
     }
-    unsafe fn inner<'a>(&'a self) -> &'a Flavor<T> {
+    unsafe fn inner(&self) -> &Flavor<T> {
         &*self.inner_unsafe().get()
     }
 }
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index fd538d52fb2..0603dad4528 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -457,6 +457,10 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
                reason = "recently added, needs RFC for stabilization,
                          questionable interaction with Condvar",
                issue = "27746")]
+    #[rustc_deprecated(since = "1.8.0",
+                       reason = "unsound on Mutex because of Condvar and \
+                                 RwLock may also with to be used with Condvar \
+                                 one day")]
     pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockReadGuard<'rwlock, U>
         where F: FnOnce(&T) -> &U
     {
@@ -508,6 +512,10 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
                reason = "recently added, needs RFC for stabilization,
                          questionable interaction with Condvar",
                issue = "27746")]
+    #[rustc_deprecated(since = "1.8.0",
+                       reason = "unsound on Mutex because of Condvar and \
+                                 RwLock may also with to be used with Condvar \
+                                 one day")]
     pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockWriteGuard<'rwlock, U>
         where F: FnOnce(&mut T) -> &mut U
     {
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index 7e05895b2cc..1cb9303a9fc 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -10,6 +10,7 @@
 
 use prelude::v1::*;
 
+use cmp;
 use ffi::{CStr, CString};
 use fmt;
 use io::{self, Error, ErrorKind};
@@ -198,10 +199,11 @@ impl TcpStream {
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
         let ret = try!(cvt(unsafe {
             c::send(*self.inner.as_inner(),
                     buf.as_ptr() as *const c_void,
-                    buf.len() as wrlen_t,
+                    len,
                     0)
         }));
         Ok(ret as usize)
@@ -358,21 +360,23 @@ impl UdpSocket {
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
         let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
+        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
 
         let n = try!(cvt(unsafe {
             c::recvfrom(*self.inner.as_inner(),
                         buf.as_mut_ptr() as *mut c_void,
-                        buf.len() as wrlen_t, 0,
+                        len, 0,
                         &mut storage as *mut _ as *mut _, &mut addrlen)
         }));
         Ok((n as usize, try!(sockaddr_to_addr(&storage, addrlen as usize))))
     }
 
     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
+        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
         let (dstp, dstlen) = dst.into_inner();
         let ret = try!(cvt(unsafe {
             c::sendto(*self.inner.as_inner(),
-                      buf.as_ptr() as *const c_void, buf.len() as wrlen_t,
+                      buf.as_ptr() as *const c_void, len,
                       0, dstp, dstlen)
         }));
         Ok(ret as usize)
diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys/common/poison.rs
index d858c002755..83780a31cce 100644
--- a/src/libstd/sys/common/poison.rs
+++ b/src/libstd/sys/common/poison.rs
@@ -71,7 +71,7 @@ pub enum TryLockError<T> {
     /// The lock could not be acquired because another thread failed while holding
     /// the lock.
     #[stable(feature = "rust1", since = "1.0.0")]
-    Poisoned(#[cfg_attr(not(stage0), stable(feature = "rust1", since = "1.0.0"))] PoisonError<T>),
+    Poisoned(#[stable(feature = "rust1", since = "1.0.0")] PoisonError<T>),
     /// The lock could not be acquired at this time because the operation would
     /// otherwise block.
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/sys/common/unwind/gcc.rs b/src/libstd/sys/common/unwind/gcc.rs
index 7cf9e2a54bd..ff6a11951dc 100644
--- a/src/libstd/sys/common/unwind/gcc.rs
+++ b/src/libstd/sys/common/unwind/gcc.rs
@@ -41,7 +41,6 @@ pub unsafe fn panic(data: Box<Any + Send + 'static>) -> ! {
     }
 }
 
-#[cfg(not(stage0))]
 pub fn payload() -> *mut u8 {
     0 as *mut u8
 }
diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs
index d9641e63760..527c2e63030 100644
--- a/src/libstd/sys/common/unwind/mod.rs
+++ b/src/libstd/sys/common/unwind/mod.rs
@@ -128,7 +128,6 @@ pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
     }
 }
 
-#[cfg(not(stage0))]
 unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
                     -> Result<(), Box<Any + Send>> {
     PANIC_COUNT.with(|s| {
@@ -156,22 +155,6 @@ unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
     })
 }
 
-#[cfg(stage0)]
-unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
-                    -> Result<(), Box<Any + Send>> {
-    PANIC_COUNT.with(|s| {
-        let prev = s.get();
-        s.set(0);
-        let ep = intrinsics::try(f, data);
-        s.set(prev);
-        if ep.is_null() {
-            Ok(())
-        } else {
-            Err(imp::cleanup(ep))
-        }
-    })
-}
-
 /// Determines whether the current thread is unwinding because of panic.
 pub fn panicking() -> bool {
     PANIC_COUNT.with(|s| s.get() != 0)
diff --git a/src/libstd/sys/common/unwind/seh.rs b/src/libstd/sys/common/unwind/seh.rs
index f8d3a92b3b6..94da42f0092 100644
--- a/src/libstd/sys/common/unwind/seh.rs
+++ b/src/libstd/sys/common/unwind/seh.rs
@@ -65,35 +65,6 @@ const RUST_PANIC: c::DWORD = 0x00525354;
 
 pub use self::imp::*;
 
-#[cfg(stage0)]
-mod imp {
-    use prelude::v1::*;
-    use any::Any;
-
-    pub unsafe fn panic(_data: Box<Any + Send + 'static>) -> ! {
-        rtabort!("cannot unwind SEH in stage0")
-    }
-
-    pub unsafe fn cleanup(_ptr: *mut u8) -> Box<Any + Send + 'static> {
-        rtabort!("can't cleanup SEH in stage0")
-    }
-
-    #[lang = "msvc_try_filter"]
-    #[linkage = "external"]
-    unsafe extern fn __rust_try_filter() -> i32 {
-        0
-    }
-
-    #[lang = "eh_unwind_resume"]
-    #[unwind]
-    unsafe extern fn rust_eh_unwind_resume(_ptr: *mut u8) -> ! {
-        rtabort!("can't resume unwind SEH in stage0")
-    }
-    #[lang = "eh_personality_catch"]
-    unsafe extern fn rust_eh_personality_catch() {}
-}
-
-#[cfg(not(stage0))]
 mod imp {
     use prelude::v1::*;
 
diff --git a/src/libstd/sys/common/unwind/seh64_gnu.rs b/src/libstd/sys/common/unwind/seh64_gnu.rs
index 8afef081673..57281d67ebb 100644
--- a/src/libstd/sys/common/unwind/seh64_gnu.rs
+++ b/src/libstd/sys/common/unwind/seh64_gnu.rs
@@ -50,7 +50,6 @@ pub unsafe fn panic(data: Box<Any + Send + 'static>) -> ! {
     rtabort!("could not unwind stack");
 }
 
-#[cfg(not(stage0))]
 pub fn payload() -> *mut u8 {
     0 as *mut u8
 }
diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs
index bc997af3a27..48e9adb9296 100644
--- a/src/libstd/sys/common/wtf8.rs
+++ b/src/libstd/sys/common/wtf8.rs
@@ -178,6 +178,10 @@ impl Wtf8Buf {
         Wtf8Buf { bytes: <[_]>::to_vec(str.as_bytes()) }
     }
 
+    pub fn clear(&mut self) {
+        self.bytes.clear()
+    }
+
     /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units.
     ///
     /// This is lossless: calling `.encode_wide()` on the resulting string
@@ -234,6 +238,11 @@ impl Wtf8Buf {
         self.bytes.reserve(additional)
     }
 
+    #[inline]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.bytes.reserve_exact(additional)
+    }
+
     /// Returns the number of bytes that this string buffer can hold without reallocating.
     #[inline]
     pub fn capacity(&self) -> usize {
@@ -332,7 +341,7 @@ impl Wtf8Buf {
                 Some((surrogate_pos, _)) => {
                     pos = surrogate_pos + 3;
                     self.bytes[surrogate_pos..pos]
-                        .clone_from_slice(UTF8_REPLACEMENT_CHARACTER);
+                        .copy_from_slice(UTF8_REPLACEMENT_CHARACTER);
                 },
                 None => return unsafe { String::from_utf8_unchecked(self.bytes) }
             }
@@ -443,6 +452,11 @@ impl Wtf8 {
         self.bytes.len()
     }
 
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.bytes.is_empty()
+    }
+
     /// Returns the code point at `position` if it is in the ASCII range,
     /// or `b'\xFF' otherwise.
     ///
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 14f30a62576..250b1b015a0 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -15,7 +15,7 @@ use os::unix::prelude::*;
 use ffi::{CString, CStr, OsString, OsStr};
 use fmt;
 use io::{self, Error, ErrorKind, SeekFrom};
-use libc::{self, dirent, c_int, off_t, mode_t};
+use libc::{self, c_int, mode_t};
 use mem;
 use path::{Path, PathBuf};
 use ptr;
@@ -26,9 +26,15 @@ use sys::{cvt, cvt_r};
 use sys_common::{AsInner, FromInner};
 
 #[cfg(target_os = "linux")]
-use libc::{stat64, fstat64, lstat64};
-#[cfg(not(target_os = "linux"))]
-use libc::{stat as stat64, fstat as fstat64, lstat as lstat64};
+use libc::{stat64, fstat64, lstat64, off64_t, ftruncate64, lseek64, dirent64, readdir64_r, open64};
+#[cfg(target_os = "android")]
+use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off64_t, ftruncate64, lseek64,
+           dirent as dirent64, open as open64};
+#[cfg(not(any(target_os = "linux", target_os = "android")))]
+use libc::{stat as stat64, fstat as fstat64, lstat as lstat64, off_t as off64_t,
+           ftruncate as ftruncate64, lseek as lseek64, dirent as dirent64, open as open64};
+#[cfg(not(any(target_os = "linux", target_os = "solaris")))]
+use libc::{readdir_r as readdir64_r};
 
 pub struct File(FileDesc);
 
@@ -48,7 +54,7 @@ unsafe impl Send for Dir {}
 unsafe impl Sync for Dir {}
 
 pub struct DirEntry {
-    entry: dirent,
+    entry: dirent64,
     root: Arc<PathBuf>,
     // We need to store an owned copy of the directory name
     // on Solaris because a) it uses a zero-length array to
@@ -116,7 +122,31 @@ impl FileAttr {
     }
 }
 
-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
+#[cfg(target_os = "netbsd")]
+impl FileAttr {
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(libc::timespec {
+            tv_sec: self.stat.st_mtime as libc::time_t,
+            tv_nsec: self.stat.st_mtimensec as libc::c_long,
+        }))
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(libc::timespec {
+            tv_sec: self.stat.st_atime as libc::time_t,
+            tv_nsec: self.stat.st_atimensec as libc::c_long,
+        }))
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(libc::timespec {
+            tv_sec: self.stat.st_birthtime as libc::time_t,
+            tv_nsec: self.stat.st_birthtimensec as libc::c_long,
+        }))
+    }
+}
+
+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "netbsd")))]
 impl FileAttr {
     pub fn modified(&self) -> io::Result<SystemTime> {
         Ok(SystemTime::from(libc::timespec {
@@ -223,7 +253,7 @@ impl Iterator for ReadDir {
             };
             let mut entry_ptr = ptr::null_mut();
             loop {
-                if libc::readdir_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                if readdir64_r(self.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
                     return Some(Err(Error::last_os_error()))
                 }
                 if entry_ptr.is_null() {
@@ -394,7 +424,7 @@ impl File {
                     try!(opts.get_creation_mode()) |
                     (opts.custom_flags as c_int & !libc::O_ACCMODE);
         let fd = try!(cvt_r(|| unsafe {
-            libc::open(path.as_ptr(), flags, opts.mode as c_int)
+            open64(path.as_ptr(), flags, opts.mode as c_int)
         }));
         let fd = FileDesc::new(fd);
 
@@ -443,7 +473,7 @@ impl File {
 
     pub fn truncate(&self, size: u64) -> io::Result<()> {
         try!(cvt_r(|| unsafe {
-            libc::ftruncate(self.0.raw(), size as libc::off_t)
+            ftruncate64(self.0.raw(), size as off64_t)
         }));
         Ok(())
     }
@@ -460,11 +490,11 @@ impl File {
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
         let (whence, pos) = match pos {
-            SeekFrom::Start(off) => (libc::SEEK_SET, off as off_t),
-            SeekFrom::End(off) => (libc::SEEK_END, off as off_t),
-            SeekFrom::Current(off) => (libc::SEEK_CUR, off as off_t),
+            SeekFrom::Start(off) => (libc::SEEK_SET, off as off64_t),
+            SeekFrom::End(off) => (libc::SEEK_END, off as off64_t),
+            SeekFrom::Current(off) => (libc::SEEK_CUR, off as off64_t),
         };
-        let n = try!(cvt(unsafe { libc::lseek(self.0.raw(), pos, whence) }));
+        let n = try!(cvt(unsafe { lseek64(self.0.raw(), pos, whence) }));
         Ok(n as u64)
     }
 
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 9cae36fb726..c332d6035ee 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -42,6 +42,7 @@ pub mod os;
 pub mod os_str;
 pub mod pipe;
 pub mod process;
+pub mod rand;
 pub mod rwlock;
 pub mod stack_overflow;
 pub mod thread;
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index 507cc0f4ea4..16c369674f0 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -21,7 +21,7 @@ use sys_common::net::{getsockopt, setsockopt};
 use time::Duration;
 
 pub use sys::{cvt, cvt_r};
-pub use libc as netc;
+pub extern crate libc as netc;
 
 pub type wrlen_t = size_t;
 
diff --git a/src/libstd/sys/unix/os_str.rs b/src/libstd/sys/unix/os_str.rs
index 0524df218a1..d5eea5d1f3b 100644
--- a/src/libstd/sys/unix/os_str.rs
+++ b/src/libstd/sys/unix/os_str.rs
@@ -17,6 +17,7 @@ use vec::Vec;
 use str;
 use string::String;
 use mem;
+use sys_common::{AsInner, IntoInner};
 
 #[derive(Clone, Hash)]
 pub struct Buf {
@@ -39,11 +40,51 @@ impl Debug for Buf {
     }
 }
 
+impl IntoInner<Vec<u8>> for Buf {
+    fn into_inner(self) -> Vec<u8> {
+        self.inner
+    }
+}
+
+impl AsInner<[u8]> for Buf {
+    fn as_inner(&self) -> &[u8] {
+        &self.inner
+    }
+}
+
+
 impl Buf {
     pub fn from_string(s: String) -> Buf {
         Buf { inner: s.into_bytes() }
     }
 
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Buf {
+        Buf {
+            inner: Vec::with_capacity(capacity)
+        }
+    }
+
+    #[inline]
+    pub fn clear(&mut self) {
+        self.inner.clear()
+    }
+
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
+    }
+
+    #[inline]
+    pub fn reserve(&mut self, additional: usize) {
+        self.inner.reserve(additional)
+    }
+
+    #[inline]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.inner.reserve_exact(additional)
+    }
+
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
diff --git a/src/libstd/rand/os.rs b/src/libstd/sys/unix/rand.rs
index 8a422246514..fa504ade084 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Interfaces to the operating system provided random number
-//! generators.
-
 pub use self::imp::OsRng;
 
 #[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
@@ -125,17 +122,6 @@ mod imp {
                       target_arch = "powerpc64"))))]
     fn is_getrandom_available() -> bool { false }
 
-    /// A random number generator that retrieves randomness straight from
-    /// the operating system. Platform sources:
-    ///
-    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
-    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
-    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
-    ///   service provider with the `PROV_RSA_FULL` type.
-    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
-    /// - OpenBSD: uses the `getentropy(2)` system call.
-    ///
-    /// This does not block.
     pub struct OsRng {
         inner: OsRngInner,
     }
@@ -189,17 +175,6 @@ mod imp {
     use sys::os::errno;
     use rand::Rng;
 
-    /// A random number generator that retrieves randomness straight from
-    /// the operating system. Platform sources:
-    ///
-    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
-    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
-    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
-    ///   service provider with the `PROV_RSA_FULL` type.
-    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
-    /// - OpenBSD: uses the `getentropy(2)` system call.
-    ///
-    /// This does not block.
     pub struct OsRng {
         // dummy field to ensure that this struct cannot be constructed outside
         // of this module
@@ -246,17 +221,6 @@ mod imp {
     use rand::Rng;
     use libc::{c_int, size_t};
 
-    /// A random number generator that retrieves randomness straight from
-    /// the operating system. Platform sources:
-    ///
-    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
-    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
-    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
-    ///   service provider with the `PROV_RSA_FULL` type.
-    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
-    /// - OpenBSD: uses the `getentropy(2)` system call.
-    ///
-    /// This does not block.
     pub struct OsRng {
         // dummy field to ensure that this struct cannot be constructed outside
         // of this module
@@ -307,133 +271,3 @@ mod imp {
         }
     }
 }
-
-#[cfg(windows)]
-mod imp {
-    use io;
-    use mem;
-    use rand::Rng;
-    use sys::c;
-
-    /// A random number generator that retrieves randomness straight from
-    /// the operating system. Platform sources:
-    ///
-    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
-    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
-    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
-    ///   service provider with the `PROV_RSA_FULL` type.
-    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
-    /// - OpenBSD: uses the `getentropy(2)` system call.
-    ///
-    /// This does not block.
-    pub struct OsRng {
-        hcryptprov: c::HCRYPTPROV
-    }
-
-    impl OsRng {
-        /// Create a new `OsRng`.
-        pub fn new() -> io::Result<OsRng> {
-            let mut hcp = 0;
-            let ret = unsafe {
-                c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
-                                        c::PROV_RSA_FULL,
-                                        c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
-            };
-
-            if ret == 0 {
-                Err(io::Error::last_os_error())
-            } else {
-                Ok(OsRng { hcryptprov: hcp })
-            }
-        }
-    }
-
-    impl Rng for OsRng {
-        fn next_u32(&mut self) -> u32 {
-            let mut v = [0; 4];
-            self.fill_bytes(&mut v);
-            unsafe { mem::transmute(v) }
-        }
-        fn next_u64(&mut self) -> u64 {
-            let mut v = [0; 8];
-            self.fill_bytes(&mut v);
-            unsafe { mem::transmute(v) }
-        }
-        fn fill_bytes(&mut self, v: &mut [u8]) {
-            let ret = unsafe {
-                c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD,
-                                  v.as_mut_ptr())
-            };
-            if ret == 0 {
-                panic!("couldn't generate random bytes: {}",
-                       io::Error::last_os_error());
-            }
-        }
-    }
-
-    impl Drop for OsRng {
-        fn drop(&mut self) {
-            let ret = unsafe {
-                c::CryptReleaseContext(self.hcryptprov, 0)
-            };
-            if ret == 0 {
-                panic!("couldn't release context: {}",
-                       io::Error::last_os_error());
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use sync::mpsc::channel;
-    use rand::Rng;
-    use super::OsRng;
-    use thread;
-
-    #[test]
-    fn test_os_rng() {
-        let mut r = OsRng::new().unwrap();
-
-        r.next_u32();
-        r.next_u64();
-
-        let mut v = [0; 1000];
-        r.fill_bytes(&mut v);
-    }
-
-    #[test]
-    fn test_os_rng_tasks() {
-
-        let mut txs = vec!();
-        for _ in 0..20 {
-            let (tx, rx) = channel();
-            txs.push(tx);
-
-            thread::spawn(move|| {
-                // wait until all the threads are ready to go.
-                rx.recv().unwrap();
-
-                // deschedule to attempt to interleave things as much
-                // as possible (XXX: is this a good test?)
-                let mut r = OsRng::new().unwrap();
-                thread::yield_now();
-                let mut v = [0; 1000];
-
-                for _ in 0..100 {
-                    r.next_u32();
-                    thread::yield_now();
-                    r.next_u64();
-                    thread::yield_now();
-                    r.fill_bytes(&mut v);
-                    thread::yield_now();
-                }
-            });
-        }
-
-        // start all the threads
-        for tx in &txs {
-            tx.send(()).unwrap();
-        }
-    }
-}
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index a868abbb731..1553aba35a2 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -46,7 +46,7 @@ mod imp {
     use super::Handler;
     use mem;
     use ptr;
-    use libc::{sigaltstack, SIGSTKSZ};
+    use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
     use libc::{sigaction, SIGBUS, SIG_DFL,
                SA_SIGINFO, SA_ONSTACK, sighandler_t};
     use libc;
@@ -157,7 +157,8 @@ mod imp {
               target_os = "macos",
               target_os = "bitrig",
               target_os = "netbsd",
-              target_os = "openbsd"))]
+              target_os = "openbsd",
+              target_os = "solaris"))]
     unsafe fn get_stack() -> libc::stack_t {
         libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ }
     }
@@ -169,13 +170,32 @@ mod imp {
     }
 
     pub unsafe fn make_handler() -> Handler {
-        let stack = get_stack();
-        sigaltstack(&stack, ptr::null_mut());
-        Handler { _data: stack.ss_sp as *mut libc::c_void }
+        let mut stack = mem::zeroed();
+        sigaltstack(ptr::null(), &mut stack);
+        // Configure alternate signal stack, if one is not already set.
+        if stack.ss_flags & SS_DISABLE != 0 {
+            stack = get_stack();
+            sigaltstack(&stack, ptr::null_mut());
+            Handler { _data: stack.ss_sp as *mut libc::c_void }
+        } else {
+            Handler { _data: ptr::null_mut() }
+        }
     }
 
     pub unsafe fn drop_handler(handler: &mut Handler) {
-        munmap(handler._data, SIGSTKSZ);
+        if !handler._data.is_null() {
+            let stack =  libc::stack_t {
+                ss_sp: ptr::null_mut(),
+                ss_flags: SS_DISABLE,
+                // Workaround for bug in MacOS implementation of sigaltstack
+                // UNIX2003 which returns ENOMEM when disabling a stack while
+                // passing ss_size smaller than MINSIGSTKSZ. According to POSIX
+                // both ss_sp and ss_size should be ignored in this case.
+                ss_size: SIGSTKSZ,
+            };
+            sigaltstack(&stack, ptr::null_mut());
+            munmap(handler._data, SIGSTKSZ);
+        }
     }
 }
 
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
index d106bc3285c..80ff0cb0453 100644
--- a/src/libstd/sys/windows/backtrace.rs
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -22,7 +22,7 @@
 //! copy of that function in my mingw install (maybe it was broken?). Instead,
 //! this takes the route of using StackWalk64 in order to walk the stack.
 
-#![allow(dead_code, deprecated)]
+#![allow(deprecated)] // dynamic_lib
 
 use io::prelude::*;
 
@@ -51,12 +51,6 @@ mod printing;
 #[path = "printing/gnu.rs"]
 mod printing;
 
-type SymFromAddrFn =
-    extern "system" fn(c::HANDLE, u64, *mut u64,
-                       *mut c::SYMBOL_INFO) -> c::BOOL;
-type SymGetLineFromAddr64Fn =
-    extern "system" fn(c::HANDLE, u64, *mut u32,
-                       *mut c::IMAGEHLP_LINE64) -> c::BOOL;
 type SymInitializeFn =
     extern "system" fn(c::HANDLE, *mut c_void,
                        c::BOOL) -> c::BOOL;
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index d25d8e0b804..5cbfec01bed 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -10,18 +10,19 @@
 
 //! C definitions used by libnative that don't belong in liblibc
 
-#![allow(bad_style, overflowing_literals, dead_code, deprecated, unused_imports)]
+#![allow(bad_style)]
+#![cfg_attr(test, allow(dead_code))]
 
 use os::raw::{c_int, c_uint, c_ulong, c_long, c_longlong, c_ushort};
-use os::raw::{c_char, c_short, c_ulonglong};
+use os::raw::{c_char, c_ulonglong};
 use libc::{wchar_t, size_t, c_void};
 use ptr;
 
 #[repr(simd)]
 #[repr(C)]
+#[cfg(target_arch = "x86_64")]
 struct u64x2(u64, u64);
 
-pub use self::GET_FILEEX_INFO_LEVELS::*;
 pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
 pub use self::EXCEPTION_DISPOSITION::*;
 
@@ -64,7 +65,6 @@ pub type LPVOID = *mut c_void;
 pub type LPWCH = *mut WCHAR;
 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
 pub type LPWSADATA = *mut WSADATA;
-pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS;
 pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
 pub type LPWSTR = *mut WCHAR;
@@ -83,56 +83,35 @@ pub const FALSE: BOOL = 0;
 
 pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1;
 pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10;
-pub const FILE_ATTRIBUTE_NORMAL: DWORD = 0x80;
 pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400;
+
 pub const FILE_SHARE_DELETE: DWORD = 0x4;
 pub const FILE_SHARE_READ: DWORD = 0x1;
 pub const FILE_SHARE_WRITE: DWORD = 0x2;
+
 pub const CREATE_ALWAYS: DWORD = 2;
 pub const CREATE_NEW: DWORD = 1;
 pub const OPEN_ALWAYS: DWORD = 4;
 pub const OPEN_EXISTING: DWORD = 3;
 pub const TRUNCATE_EXISTING: DWORD = 5;
 
-pub const FILE_READ_DATA: DWORD = 0x00000001;
 pub const FILE_WRITE_DATA: DWORD = 0x00000002;
 pub const FILE_APPEND_DATA: DWORD = 0x00000004;
-pub const FILE_READ_EA: DWORD = 0x00000008;
 pub const FILE_WRITE_EA: DWORD = 0x00000010;
-pub const FILE_EXECUTE: DWORD = 0x00000020;
-pub const FILE_READ_ATTRIBUTES: DWORD = 0x00000080;
 pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
-
-pub const DELETE: DWORD = 0x00008000;
 pub const READ_CONTROL: DWORD = 0x00020000;
-pub const WRITE_DAC: DWORD = 0x00040000;
-pub const WRITE_OWNER: DWORD = 0x00080000;
 pub const SYNCHRONIZE: DWORD = 0x00100000;
-
 pub const GENERIC_READ: DWORD = 0x80000000;
 pub const GENERIC_WRITE: DWORD = 0x40000000;
-pub const GENERIC_EXECUTE: DWORD = 0x20000000;
-pub const GENERIC_ALL: DWORD = 0x10000000;
-
-pub const STANDARD_RIGHTS_READ: DWORD = READ_CONTROL;
 pub const STANDARD_RIGHTS_WRITE: DWORD = READ_CONTROL;
-pub const STANDARD_RIGHTS_EXECUTE: DWORD = READ_CONTROL;
-pub const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA |
-                                     FILE_READ_ATTRIBUTES |
-                                     FILE_READ_EA |
-                                     SYNCHRONIZE;
 pub const FILE_GENERIC_WRITE: DWORD = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA |
                                       FILE_WRITE_ATTRIBUTES |
                                       FILE_WRITE_EA |
                                       FILE_APPEND_DATA |
                                       SYNCHRONIZE;
 
-pub const SECURITY_ANONYMOUS: DWORD = 0 << 16;
-pub const SECURITY_IDENTIFICATION: DWORD = 1 << 16;
-pub const SECURITY_IMPERSONATION: DWORD = 2 << 16;
-pub const SECURITY_DELEGATION: DWORD = 3 << 16;
-pub const SECURITY_CONTEXT_TRACKING: DWORD = 0x00040000;
-pub const SECURITY_EFFECTIVE_ONLY: DWORD = 0x00080000;
+pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
+pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
 pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
 
 #[repr(C)]
@@ -153,96 +132,36 @@ impl Clone for WIN32_FIND_DATAW {
     fn clone(&self) -> Self { *self }
 }
 
-pub const FIONBIO: c_long = 0x8004667e;
-pub const FD_SETSIZE: usize = 64;
-pub const MSG_DONTWAIT: c_int = 0;
-pub const ENABLE_ECHO_INPUT: DWORD = 0x4;
-pub const ENABLE_EXTENDED_FLAGS: DWORD = 0x80;
-pub const ENABLE_INSERT_MODE: DWORD = 0x20;
-pub const ENABLE_LINE_INPUT: DWORD = 0x2;
-pub const ENABLE_PROCESSED_INPUT: DWORD = 0x1;
-pub const ENABLE_QUICK_EDIT_MODE: DWORD = 0x40;
-
-pub const FD_ACCEPT: c_long = 0x08;
-pub const FD_MAX_EVENTS: usize = 10;
-
-pub const WSA_INVALID_EVENT: WSAEVENT = 0 as WSAEVENT;
-pub const WSA_INFINITE: DWORD = INFINITE;
-pub const WSA_WAIT_TIMEOUT: DWORD = WAIT_TIMEOUT;
-pub const WSA_WAIT_EVENT_0: DWORD = WAIT_OBJECT_0;
-pub const WSA_WAIT_FAILED: DWORD = WAIT_FAILED;
 pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
-pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80;
 
 pub const WSADESCRIPTION_LEN: usize = 256;
 pub const WSASYS_STATUS_LEN: usize = 128;
 pub const WSAPROTOCOL_LEN: DWORD = 255;
 pub const INVALID_SOCKET: SOCKET = !0;
 
-pub const WSAEINTR: c_int = 10004;
-pub const WSAEBADF: c_int = 10009;
 pub const WSAEACCES: c_int = 10013;
-pub const WSAEFAULT: c_int = 10014;
 pub const WSAEINVAL: c_int = 10022;
-pub const WSAEMFILE: c_int = 10024;
 pub const WSAEWOULDBLOCK: c_int = 10035;
-pub const WSAEINPROGRESS: c_int = 10036;
-pub const WSAEALREADY: c_int = 10037;
-pub const WSAENOTSOCK: c_int = 10038;
-pub const WSAEDESTADDRREQ: c_int = 10039;
-pub const WSAEMSGSIZE: c_int = 10040;
-pub const WSAEPROTOTYPE: c_int = 10041;
-pub const WSAENOPROTOOPT: c_int = 10042;
-pub const WSAEPROTONOSUPPORT: c_int = 10043;
-pub const WSAESOCKTNOSUPPORT: c_int = 10044;
-pub const WSAEOPNOTSUPP: c_int = 10045;
-pub const WSAEPFNOSUPPORT: c_int = 10046;
-pub const WSAEAFNOSUPPORT: c_int = 10047;
 pub const WSAEADDRINUSE: c_int = 10048;
 pub const WSAEADDRNOTAVAIL: c_int = 10049;
-pub const WSAENETDOWN: c_int = 10050;
-pub const WSAENETUNREACH: c_int = 10051;
-pub const WSAENETRESET: c_int = 10052;
 pub const WSAECONNABORTED: c_int = 10053;
 pub const WSAECONNRESET: c_int = 10054;
-pub const WSAENOBUFS: c_int = 10055;
-pub const WSAEISCONN: c_int = 10056;
 pub const WSAENOTCONN: c_int = 10057;
 pub const WSAESHUTDOWN: c_int = 10058;
-pub const WSAETOOMANYREFS: c_int = 10059;
 pub const WSAETIMEDOUT: c_int = 10060;
 pub const WSAECONNREFUSED: c_int = 10061;
-pub const WSAELOOP: c_int = 10062;
-pub const WSAENAMETOOLONG: c_int = 10063;
-pub const WSAEHOSTDOWN: c_int = 10064;
-pub const WSAEHOSTUNREACH: c_int = 10065;
-pub const WSAENOTEMPTY: c_int = 10066;
-pub const WSAEPROCLIM: c_int = 10067;
-pub const WSAEUSERS: c_int = 10068;
-pub const WSAEDQUOT: c_int = 10069;
-pub const WSAESTALE: c_int = 10070;
-pub const WSAEREMOTE: c_int = 10071;
-pub const WSASYSNOTREADY: c_int = 10091;
-pub const WSAVERNOTSUPPORTED: c_int = 10092;
-pub const WSANOTINITIALISED: c_int = 10093;
-pub const WSAEDISCON: c_int = 10101;
-pub const WSAENOMORE: c_int = 10102;
-pub const WSAECANCELLED: c_int = 10103;
-pub const WSAEINVALIDPROCTABLE: c_int = 10104;
+
 pub const NI_MAXHOST: DWORD = 1025;
 
 pub const MAX_PROTOCOL_CHAIN: DWORD = 7;
 
 pub const TOKEN_READ: DWORD = 0x20008;
-pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
-pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
 pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
 pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
 pub const IO_REPARSE_TAG_SYMLINK: DWORD = 0xa000000c;
 pub const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003;
 pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001;
 pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
-pub const FSCTL_DELETE_REPARSE_POINT: DWORD = 0x900ac;
 
 pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
 
@@ -254,38 +173,19 @@ pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
 pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
 
 pub const PROGRESS_CONTINUE: DWORD = 0;
-pub const PROGRESS_CANCEL: DWORD = 1;
-pub const PROGRESS_STOP: DWORD = 2;
-pub const PROGRESS_QUIET: DWORD = 3;
-
-pub const TOKEN_ADJUST_PRIVILEGES: DWORD = 0x0020;
-pub const SE_PRIVILEGE_ENABLED: DWORD = 2;
 
-
-pub const ERROR_SUCCESS: DWORD = 0;
-pub const ERROR_INVALID_FUNCTION: DWORD = 1;
 pub const ERROR_FILE_NOT_FOUND: DWORD = 2;
 pub const ERROR_PATH_NOT_FOUND: DWORD = 3;
 pub const ERROR_ACCESS_DENIED: DWORD = 5;
 pub const ERROR_INVALID_HANDLE: DWORD = 6;
 pub const ERROR_NO_MORE_FILES: DWORD = 18;
 pub const ERROR_BROKEN_PIPE: DWORD = 109;
-pub const ERROR_DISK_FULL: DWORD = 112;
 pub const ERROR_CALL_NOT_IMPLEMENTED: DWORD = 120;
 pub const ERROR_INSUFFICIENT_BUFFER: DWORD = 122;
-pub const ERROR_INVALID_NAME: DWORD = 123;
 pub const ERROR_ALREADY_EXISTS: DWORD = 183;
-pub const ERROR_PIPE_BUSY: DWORD = 231;
 pub const ERROR_NO_DATA: DWORD = 232;
-pub const ERROR_INVALID_ADDRESS: DWORD = 487;
-pub const ERROR_PIPE_CONNECTED: DWORD = 535;
-pub const ERROR_ILLEGAL_CHARACTER: DWORD = 582;
 pub const ERROR_ENVVAR_NOT_FOUND: DWORD = 203;
-pub const ERROR_NOTHING_TO_TERMINATE: DWORD = 758;
 pub const ERROR_OPERATION_ABORTED: DWORD = 995;
-pub const ERROR_IO_PENDING: DWORD = 997;
-pub const ERROR_FILE_INVALID: DWORD = 1006;
-pub const ERROR_NOT_FOUND: DWORD = 1168;
 pub const ERROR_TIMEOUT: DWORD = 0x5B4;
 
 pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
@@ -307,8 +207,6 @@ pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE {
 };
 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() };
 
-pub const STILL_ACTIVE: DWORD = 259;
-
 pub const DETACHED_PROCESS: DWORD = 0x00000008;
 pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200;
 pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400;
@@ -333,14 +231,13 @@ pub const FILE_BEGIN: DWORD = 0;
 pub const FILE_CURRENT: DWORD = 1;
 pub const FILE_END: DWORD = 2;
 
-pub const WAIT_ABANDONED: DWORD = 0x00000080;
 pub const WAIT_OBJECT_0: DWORD = 0x00000000;
-pub const WAIT_TIMEOUT: DWORD = 0x00000102;
-pub const WAIT_FAILED: DWORD = !0;
 
+#[cfg(target_env = "msvc")]
 pub const MAX_SYM_NAME: usize = 2000;
+#[cfg(target_arch = "x86")]
 pub const IMAGE_FILE_MACHINE_I386: DWORD = 0x014c;
-pub const IMAGE_FILE_MACHINE_IA64: DWORD = 0x0200;
+#[cfg(target_arch = "x86_64")]
 pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
 
 pub const PROV_RSA_FULL: DWORD = 1;
@@ -350,13 +247,17 @@ pub const CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
 pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
 pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub const EXCEPTION_NONCONTINUABLE: DWORD = 0x1;   // Noncontinuable exception
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub const EXCEPTION_UNWINDING: DWORD = 0x2;        // Unwind is in progress
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub const EXCEPTION_EXIT_UNWIND: DWORD = 0x4;      // Exit unwind is in progress
-pub const EXCEPTION_STACK_INVALID: DWORD = 0x8;    // Stack out of limits or unaligned
-pub const EXCEPTION_NESTED_CALL: DWORD = 0x10;     // Nested exception handler call
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub const EXCEPTION_TARGET_UNWIND: DWORD = 0x20;   // Target unwind in progress
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub const EXCEPTION_COLLIDED_UNWIND: DWORD = 0x40; // Collided exception handler call
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub const EXCEPTION_UNWIND: DWORD = EXCEPTION_UNWINDING |
                                     EXCEPTION_EXIT_UNWIND |
                                     EXCEPTION_TARGET_UNWIND |
@@ -385,12 +286,6 @@ pub struct WSADATA {
     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
 }
 
-#[repr(C)]
-pub struct WSANETWORKEVENTS {
-    pub lNetworkEvents: c_long,
-    pub iErrorCode: [c_int; FD_MAX_EVENTS],
-}
-
 pub type WSAEVENT = HANDLE;
 
 #[repr(C)]
@@ -418,43 +313,6 @@ pub struct WSAPROTOCOL_INFO {
 }
 
 #[repr(C)]
-pub struct fd_set {
-    fd_count: c_uint,
-    fd_array: [SOCKET; FD_SETSIZE],
-}
-
-pub fn fd_set(set: &mut fd_set, s: SOCKET) {
-    set.fd_array[set.fd_count as usize] = s;
-    set.fd_count += 1;
-}
-
-pub type SHORT = c_short;
-
-#[repr(C)]
-pub struct COORD {
-    pub X: SHORT,
-    pub Y: SHORT,
-}
-
-#[repr(C)]
-pub struct SMALL_RECT {
-    pub Left: SHORT,
-    pub Top: SHORT,
-    pub Right: SHORT,
-    pub Bottom: SHORT,
-}
-
-#[repr(C)]
-pub struct CONSOLE_SCREEN_BUFFER_INFO {
-    pub dwSize: COORD,
-    pub dwCursorPosition: COORD,
-    pub wAttributes: WORD,
-    pub srWindow: SMALL_RECT,
-    pub dwMaximumWindowSize: COORD,
-}
-pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
-
-#[repr(C)]
 #[derive(Copy, Clone)]
 pub struct WIN32_FILE_ATTRIBUTE_DATA {
     pub dwFileAttributes: DWORD,
@@ -480,12 +338,7 @@ pub struct BY_HANDLE_FILE_INFORMATION {
 }
 
 #[repr(C)]
-pub enum GET_FILEEX_INFO_LEVELS {
-    GetFileExInfoStandard,
-    GetFileExMaxInfoLevel
-}
-
-#[repr(C)]
+#[allow(dead_code)] // we only use some variants
 pub enum FILE_INFO_BY_HANDLE_CLASS {
     FileBasicInfo                   = 0,
     FileStandardInfo                = 1,
@@ -570,28 +423,6 @@ pub struct CRITICAL_SECTION {
 }
 
 #[repr(C)]
-pub struct LUID {
-    pub LowPart: DWORD,
-    pub HighPart: c_long,
-}
-
-pub type PLUID = *mut LUID;
-
-#[repr(C)]
-pub struct TOKEN_PRIVILEGES {
-    pub PrivilegeCount: DWORD,
-    pub Privileges: [LUID_AND_ATTRIBUTES; 1],
-}
-
-pub type PTOKEN_PRIVILEGES = *mut TOKEN_PRIVILEGES;
-
-#[repr(C)]
-pub struct LUID_AND_ATTRIBUTES {
-    pub Luid: LUID,
-    pub Attributes: DWORD,
-}
-
-#[repr(C)]
 pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
     pub ReparseTag: DWORD,
     pub ReparseDataLength: DWORD,
@@ -695,6 +526,7 @@ pub struct OVERLAPPED {
 }
 
 #[repr(C)]
+#[cfg(target_env = "msvc")]
 pub struct SYMBOL_INFO {
     pub SizeOfStruct: c_ulong,
     pub TypeIndex: c_ulong,
@@ -717,6 +549,7 @@ pub struct SYMBOL_INFO {
 }
 
 #[repr(C)]
+#[cfg(target_env = "msvc")]
 pub struct IMAGEHLP_LINE64 {
     pub SizeOfStruct: u32,
     pub Key: *const c_void,
@@ -726,6 +559,7 @@ pub struct IMAGEHLP_LINE64 {
 }
 
 #[repr(C)]
+#[allow(dead_code)] // we only use some variants
 pub enum ADDRESS_MODE {
     AddrMode1616,
     AddrMode1632,
@@ -941,9 +775,11 @@ pub struct in6_addr {
     pub s6_addr: [u8; 16],
 }
 
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub enum UNWIND_HISTORY_TABLE {}
 
 #[repr(C)]
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub struct RUNTIME_FUNCTION {
     pub BeginAddress: DWORD,
     pub EndAddress: DWORD,
@@ -951,6 +787,7 @@ pub struct RUNTIME_FUNCTION {
 }
 
 #[repr(C)]
+#[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
 pub struct DISPATCHER_CONTEXT {
     pub ControlPc: LPVOID,
     pub ImageBase: LPVOID,
@@ -965,6 +802,7 @@ pub struct DISPATCHER_CONTEXT {
 
 #[repr(C)]
 #[derive(Copy, Clone)]
+#[allow(dead_code)] // we only use some variants
 pub enum EXCEPTION_DISPOSITION {
     ExceptionContinueExecution,
     ExceptionContinueSearch,
@@ -1016,9 +854,6 @@ extern "system" {
 
     pub fn GetConsoleMode(hConsoleHandle: HANDLE,
                           lpMode: LPDWORD) -> BOOL;
-    pub fn GetFileAttributesExW(lpFileName: LPCWSTR,
-                                fInfoLevelId: GET_FILEEX_INFO_LEVELS,
-                                lpFileInformation: LPVOID) -> BOOL;
     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
     pub fn SetFileAttributesW(lpFileName: LPCWSTR,
                               dwFileAttributes: DWORD) -> BOOL;
@@ -1076,15 +911,6 @@ extern "system" {
                        lpData: LPVOID,
                        pbCancel: LPBOOL,
                        dwCopyFlags: DWORD) -> BOOL;
-    pub fn LookupPrivilegeValueW(lpSystemName: LPCWSTR,
-                                 lpName: LPCWSTR,
-                                 lpLuid: PLUID) -> BOOL;
-    pub fn AdjustTokenPrivileges(TokenHandle: HANDLE,
-                                 DisableAllPrivileges: BOOL,
-                                 NewState: PTOKEN_PRIVILEGES,
-                                 BufferLength: DWORD,
-                                 PreviousState: PTOKEN_PRIVILEGES,
-                                 ReturnLength: *mut DWORD) -> BOOL;
     pub fn AddVectoredExceptionHandler(FirstHandler: ULONG,
                                        VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
                                        -> LPVOID;
@@ -1260,10 +1086,12 @@ extern "system" {
     pub fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
 
     #[unwind]
+    #[cfg(any(target_arch = "x86_64", target_env = "msvc"))]
     pub fn RaiseException(dwExceptionCode: DWORD,
                           dwExceptionFlags: DWORD,
                           nNumberOfArguments: DWORD,
                           lpArguments: *const ULONG_PTR);
+    #[cfg(all(target_arch = "x86_64", target_env = "gnu"))]
     pub fn RtlUnwindEx(TargetFrame: LPVOID,
                        TargetIp: LPVOID,
                        ExceptionRecord: *const EXCEPTION_RECORD,
diff --git a/src/libstd/sys/windows/compat.rs b/src/libstd/sys/windows/compat.rs
index 780a0d9427d..acbfacce8bd 100644
--- a/src/libstd/sys/windows/compat.rs
+++ b/src/libstd/sys/windows/compat.rs
@@ -28,7 +28,7 @@ use sync::atomic::{AtomicUsize, Ordering};
 use sys::c;
 
 pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
-    let mut module: Vec<u16> = module.utf16_units().collect();
+    let mut module: Vec<u16> = module.encode_utf16().collect();
     module.push(0);
     let symbol = CString::new(symbol).unwrap();
     unsafe {
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index d4d95a12f81..95fb1e7c600 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -30,7 +30,11 @@ pub struct File { handle: Handle }
 
 #[derive(Clone)]
 pub struct FileAttr {
-    data: c::WIN32_FILE_ATTRIBUTE_DATA,
+    attributes: c::DWORD,
+    creation_time: c::FILETIME,
+    last_access_time: c::FILETIME,
+    last_write_time: c::FILETIME,
+    file_size: u64,
     reparse_tag: c::DWORD,
 }
 
@@ -142,14 +146,11 @@ impl DirEntry {
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
         Ok(FileAttr {
-            data: c::WIN32_FILE_ATTRIBUTE_DATA {
-                dwFileAttributes: self.data.dwFileAttributes,
-                ftCreationTime: self.data.ftCreationTime,
-                ftLastAccessTime: self.data.ftLastAccessTime,
-                ftLastWriteTime: self.data.ftLastWriteTime,
-                nFileSizeHigh: self.data.nFileSizeHigh,
-                nFileSizeLow: self.data.nFileSizeLow,
-            },
+            attributes: self.data.dwFileAttributes,
+            creation_time: self.data.ftCreationTime,
+            last_access_time: self.data.ftLastAccessTime,
+            last_write_time: self.data.ftLastWriteTime,
+            file_size: ((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64),
             reparse_tag: if self.data.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
                     // reserved unless this is a reparse point
                     self.data.dwReserved0
@@ -290,14 +291,11 @@ impl File {
             try!(cvt(c::GetFileInformationByHandle(self.handle.raw(),
                                                    &mut info)));
             let mut attr = FileAttr {
-                data: c::WIN32_FILE_ATTRIBUTE_DATA {
-                    dwFileAttributes: info.dwFileAttributes,
-                    ftCreationTime: info.ftCreationTime,
-                    ftLastAccessTime: info.ftLastAccessTime,
-                    ftLastWriteTime: info.ftLastWriteTime,
-                    nFileSizeHigh: info.nFileSizeHigh,
-                    nFileSizeLow: info.nFileSizeLow,
-                },
+                attributes: info.dwFileAttributes,
+                creation_time: info.ftCreationTime,
+                last_access_time: info.ftLastAccessTime,
+                last_write_time: info.ftLastWriteTime,
+                file_size: ((info.nFileSizeHigh as u64) << 32) | (info.nFileSizeLow as u64),
                 reparse_tag: 0,
             };
             if attr.is_reparse_point() {
@@ -420,45 +418,45 @@ impl fmt::Debug for File {
 
 impl FileAttr {
     pub fn size(&self) -> u64 {
-        ((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64)
+        self.file_size
     }
 
     pub fn perm(&self) -> FilePermissions {
-        FilePermissions { attrs: self.data.dwFileAttributes }
+        FilePermissions { attrs: self.attributes }
     }
 
-    pub fn attrs(&self) -> u32 { self.data.dwFileAttributes as u32 }
+    pub fn attrs(&self) -> u32 { self.attributes as u32 }
 
     pub fn file_type(&self) -> FileType {
-        FileType::new(self.data.dwFileAttributes, self.reparse_tag)
+        FileType::new(self.attributes, self.reparse_tag)
     }
 
     pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(self.data.ftLastWriteTime))
+        Ok(SystemTime::from(self.last_write_time))
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(self.data.ftLastAccessTime))
+        Ok(SystemTime::from(self.last_access_time))
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(self.data.ftCreationTime))
+        Ok(SystemTime::from(self.creation_time))
     }
 
     pub fn modified_u64(&self) -> u64 {
-        to_u64(&self.data.ftLastWriteTime)
+        to_u64(&self.last_write_time)
     }
 
     pub fn accessed_u64(&self) -> u64 {
-        to_u64(&self.data.ftLastAccessTime)
+        to_u64(&self.last_access_time)
     }
 
     pub fn created_u64(&self) -> u64 {
-        to_u64(&self.data.ftCreationTime)
+        to_u64(&self.creation_time)
     }
 
     fn is_reparse_point(&self) -> bool {
-        self.data.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0
+        self.attributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0
     }
 }
 
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index cb41b05daae..47676a927f6 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use cmp;
 use io::ErrorKind;
 use io;
 use mem;
@@ -15,6 +16,7 @@ use ops::Deref;
 use ptr;
 use sys::c;
 use sys::cvt;
+use u32;
 
 /// An owned container for `HANDLE` object, closing them on Drop.
 ///
@@ -64,10 +66,12 @@ impl RawHandle {
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let mut read = 0;
+        // ReadFile takes a DWORD (u32) for the length so it only supports
+        // reading u32::MAX bytes at a time.
+        let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
         let res = cvt(unsafe {
-            c::ReadFile(self.0, buf.as_ptr() as c::LPVOID,
-                           buf.len() as c::DWORD, &mut read,
-                           ptr::null_mut())
+            c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
+                        len, &mut read, ptr::null_mut())
         });
 
         match res {
@@ -85,10 +89,12 @@ impl RawHandle {
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let mut amt = 0;
+        // WriteFile takes a DWORD (u32) for the length so it only supports
+        // writing u32::MAX bytes at a time.
+        let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
         try!(cvt(unsafe {
             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
-                            buf.len() as c::DWORD, &mut amt,
-                            ptr::null_mut())
+                         len, &mut amt, ptr::null_mut())
         }));
         Ok(amt as usize)
     }
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 9ecef5ee92c..765e6e09427 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -33,6 +33,7 @@ pub mod os;
 pub mod os_str;
 pub mod pipe;
 pub mod process;
+pub mod rand;
 pub mod rwlock;
 pub mod stack_overflow;
 pub mod thread;
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index 3e69902dcb6..49ba8e9c659 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use cmp;
 use io;
 use libc::{c_int, c_void};
 use mem;
@@ -131,9 +132,9 @@ impl Socket {
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
+        let len = cmp::min(buf.len(), i32::max_value() as usize) as i32;
         unsafe {
-            match c::recv(self.0, buf.as_mut_ptr() as *mut c_void,
-                             buf.len() as i32, 0) {
+            match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, 0) {
                 -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
                 -1 => Err(last_error()),
                 n => Ok(n as usize)
diff --git a/src/libstd/sys/windows/os_str.rs b/src/libstd/sys/windows/os_str.rs
index 91905ae7489..26767a1349e 100644
--- a/src/libstd/sys/windows/os_str.rs
+++ b/src/libstd/sys/windows/os_str.rs
@@ -18,12 +18,25 @@ use string::String;
 use result::Result;
 use option::Option;
 use mem;
+use sys_common::{AsInner, IntoInner};
 
 #[derive(Clone, Hash)]
 pub struct Buf {
     pub inner: Wtf8Buf
 }
 
+impl IntoInner<Wtf8Buf> for Buf {
+    fn into_inner(self) -> Wtf8Buf {
+        self.inner
+    }
+}
+
+impl AsInner<Wtf8> for Buf {
+    fn as_inner(&self) -> &Wtf8 {
+        &self.inner
+    }
+}
+
 impl Debug for Buf {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
         self.as_slice().fmt(formatter)
@@ -41,6 +54,20 @@ impl Debug for Slice {
 }
 
 impl Buf {
+    pub fn with_capacity(capacity: usize) -> Buf {
+        Buf {
+            inner: Wtf8Buf::with_capacity(capacity)
+        }
+    }
+
+    pub fn clear(&mut self) {
+        self.inner.clear()
+    }
+
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
+    }
+
     pub fn from_string(s: String) -> Buf {
         Buf { inner: Wtf8Buf::from_string(s) }
     }
@@ -56,6 +83,14 @@ impl Buf {
     pub fn push_slice(&mut self, s: &Slice) {
         self.inner.push_wtf8(&s.inner)
     }
+
+    pub fn reserve(&mut self, additional: usize) {
+        self.inner.reserve(additional)
+    }
+
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.inner.reserve_exact(additional)
+    }
 }
 
 impl Slice {
diff --git a/src/libstd/sys/windows/printing/msvc.rs b/src/libstd/sys/windows/printing/msvc.rs
index d04691a6a47..255c645c3fb 100644
--- a/src/libstd/sys/windows/printing/msvc.rs
+++ b/src/libstd/sys/windows/printing/msvc.rs
@@ -16,10 +16,16 @@ use io::prelude::*;
 use io;
 use libc::{c_ulong, c_int, c_char, c_void};
 use mem;
-use super::{SymFromAddrFn, SymGetLineFromAddr64Fn};
 use sys::c;
 use sys_common::backtrace::{output, output_fileline};
 
+type SymFromAddrFn =
+    extern "system" fn(c::HANDLE, u64, *mut u64,
+                       *mut c::SYMBOL_INFO) -> c::BOOL;
+type SymGetLineFromAddr64Fn =
+    extern "system" fn(c::HANDLE, u64, *mut u32,
+                       *mut c::IMAGEHLP_LINE64) -> c::BOOL;
+
 pub fn print(w: &mut Write, i: isize, addr: u64, dbghelp: &DynamicLibrary,
              process: c::HANDLE) -> io::Result<()> {
     let SymFromAddr = sym!(dbghelp, "SymFromAddr", SymFromAddrFn);
diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs
new file mode 100644
index 00000000000..10e3d45f9d5
--- /dev/null
+++ b/src/libstd/sys/windows/rand.rs
@@ -0,0 +1,76 @@
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+use io;
+use mem;
+use rand::Rng;
+use sys::c;
+
+pub struct OsRng {
+    hcryptprov: c::HCRYPTPROV
+}
+
+impl OsRng {
+    /// Create a new `OsRng`.
+    pub fn new() -> io::Result<OsRng> {
+        let mut hcp = 0;
+        let ret = unsafe {
+            c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
+                                    c::PROV_RSA_FULL,
+                                    c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
+        };
+
+        if ret == 0 {
+            Err(io::Error::last_os_error())
+        } else {
+            Ok(OsRng { hcryptprov: hcp })
+        }
+    }
+}
+
+impl Rng for OsRng {
+    fn next_u32(&mut self) -> u32 {
+        let mut v = [0; 4];
+        self.fill_bytes(&mut v);
+        unsafe { mem::transmute(v) }
+    }
+    fn next_u64(&mut self) -> u64 {
+        let mut v = [0; 8];
+        self.fill_bytes(&mut v);
+        unsafe { mem::transmute(v) }
+    }
+    fn fill_bytes(&mut self, v: &mut [u8]) {
+        // CryptGenRandom takes a DWORD (u32) for the length so we need to
+        // split up the buffer.
+        for slice in v.chunks_mut(<c::DWORD>::max_value() as usize) {
+            let ret = unsafe {
+                c::CryptGenRandom(self.hcryptprov, slice.len() as c::DWORD,
+                                  slice.as_mut_ptr())
+            };
+            if ret == 0 {
+                panic!("couldn't generate random bytes: {}",
+                       io::Error::last_os_error());
+            }
+        }
+    }
+}
+
+impl Drop for OsRng {
+    fn drop(&mut self) {
+        let ret = unsafe {
+            c::CryptReleaseContext(self.hcryptprov, 0)
+        };
+        if ret == 0 {
+            panic!("couldn't release context: {}",
+                   io::Error::last_os_error());
+        }
+    }
+}
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index 8f37dc02e87..1cd05b61d25 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -56,7 +56,7 @@ fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
         Output::Pipe(ref p) => return p.get().write(data),
     };
     let utf16 = match str::from_utf8(data).ok() {
-        Some(utf8) => utf8.utf16_units().collect::<Vec<u16>>(),
+        Some(utf8) => utf8.encode_utf16().collect::<Vec<u16>>(),
         None => return Err(invalid_encoding()),
     };
     let mut written = 0;
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index db2ad1d89c4..59da74b7287 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -69,9 +69,8 @@ static mut DTORS: *mut Vec<(Key, Dtor)> = ptr::null_mut();
 pub unsafe fn create(dtor: Option<Dtor>) -> Key {
     let key = c::TlsAlloc();
     assert!(key != c::TLS_OUT_OF_INDEXES);
-    match dtor {
-        Some(f) => register_dtor(key, f),
-        None => {}
+    if let Some(f) = dtor {
+        register_dtor(key, f);
     }
     return key;
 }
@@ -233,12 +232,12 @@ unsafe fn unregister_dtor(key: Key) -> bool {
 
 #[link_section = ".CRT$XLB"]
 #[linkage = "external"]
-#[allow(warnings)]
+#[allow(dead_code, unused_variables)]
 pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD,
                                                         c::LPVOID) =
         on_tls_callback;
 
-#[allow(warnings)]
+#[allow(dead_code, unused_variables)]
 unsafe extern "system" fn on_tls_callback(h: c::LPVOID,
                                           dwReason: c::DWORD,
                                           pv: c::LPVOID) {
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 116cd5da2ce..981ba1e36e9 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -188,6 +188,7 @@ pub use self::local::{LocalKey, LocalKeyState};
            reason = "scoped TLS has yet to have wide enough use to fully \
                      consider stabilizing its interface",
            issue = "27715")]
+#[allow(deprecated)]
 pub use self::scoped_tls::ScopedKey;
 
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
diff --git a/src/libstd/thread/scoped_tls.rs b/src/libstd/thread/scoped_tls.rs
index dc0bc6dfe02..dea58d016e4 100644
--- a/src/libstd/thread/scoped_tls.rs
+++ b/src/libstd/thread/scoped_tls.rs
@@ -41,6 +41,7 @@
 //! ```
 
 #![unstable(feature = "thread_local_internals", issue = "0")]
+#![allow(deprecated)]
 
 #[doc(hidden)]
 pub use self::imp::KeyInner as __KeyInner;
@@ -56,6 +57,8 @@ pub use self::imp::KeyInner as __KeyInner;
            reason = "scoped TLS has yet to have wide enough use to fully consider \
                      stabilizing its interface",
            issue = "27715")]
+#[rustc_deprecated(since = "1.8.0",
+                   reason = "hasn't proven itself over LocalKey")]
 pub struct ScopedKey<T:'static> { inner: fn() -> &'static imp::KeyInner<T> }
 
 /// Declare a new scoped thread local storage key.
@@ -68,6 +71,8 @@ pub struct ScopedKey<T:'static> { inner: fn() -> &'static imp::KeyInner<T> }
 #[unstable(feature = "thread_local_internals",
            reason = "should not be necessary",
            issue = "0")]
+#[rustc_deprecated(since = "1.8.0",
+                   reason = "hasn't proven itself over LocalKey")]
 #[macro_export]
 #[allow_internal_unstable]
 macro_rules! scoped_thread_local {
@@ -85,6 +90,8 @@ macro_rules! scoped_thread_local {
 #[unstable(feature = "thread_local_internals",
            reason = "should not be necessary",
            issue = "0")]
+#[rustc_deprecated(since = "1.8.0",
+                   reason = "hasn't proven itself over LocalKey")]
 #[macro_export]
 #[allow_internal_unstable]
 macro_rules! __scoped_thread_local_inner {
@@ -101,6 +108,8 @@ macro_rules! __scoped_thread_local_inner {
            reason = "scoped TLS has yet to have wide enough use to fully consider \
                      stabilizing its interface",
            issue = "27715")]
+#[rustc_deprecated(since = "1.8.0",
+                   reason = "hasn't proven itself over LocalKey")]
 impl<T> ScopedKey<T> {
     #[doc(hidden)]
     pub const fn new(inner: fn() -> &'static imp::KeyInner<T>) -> ScopedKey<T> {
diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs
index a0cf443c0c3..aa0a843dc9a 100644
--- a/src/libstd/time/mod.rs
+++ b/src/libstd/time/mod.rs
@@ -41,7 +41,7 @@ mod duration;
 /// allows measuring the duration between two instants (or comparing two
 /// instants).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 pub struct Instant(time::Instant);
 
 /// A measurement of the system clock, useful for talking to
@@ -64,18 +64,18 @@ pub struct Instant(time::Instant);
 /// fixed point in time, a `SystemTime` can be converted to a human-readable time,
 /// or perhaps some other string representation.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 pub struct SystemTime(time::SystemTime);
 
-/// An error returned from the `duration_from_earlier` method on `SystemTime`,
+/// An error returned from the `duration_since` method on `SystemTime`,
 /// used to learn about why how far in the opposite direction a timestamp lies.
 #[derive(Clone, Debug)]
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 pub struct SystemTimeError(Duration);
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
 impl Instant {
     /// Returns an instant corresponding to "now".
+    #[stable(feature = "time2", since = "1.8.0")]
     pub fn now() -> Instant {
         Instant(time::Instant::now())
     }
@@ -88,6 +88,14 @@ impl Instant {
     /// only be possible if `earlier` was created after `self`. Because
     /// `Instant` is monotonic, the only time that this should happen should be
     /// a bug.
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn duration_since(&self, earlier: Instant) -> Duration {
+        self.0.sub_instant(&earlier.0)
+    }
+
+    /// Deprecated, renamed to `duration_since`
+    #[unstable(feature = "time2_old", issue = "29866")]
+    #[rustc_deprecated(since = "1.8.0", reason = "renamed to duration_since")]
     pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
         self.0.sub_instant(&earlier.0)
     }
@@ -99,12 +107,13 @@ impl Instant {
     /// This function may panic if the current time is earlier than this
     /// instant, which is something that can happen if an `Instant` is
     /// produced synthetically.
+    #[stable(feature = "time2", since = "1.8.0")]
     pub fn elapsed(&self) -> Duration {
-        Instant::now().duration_from_earlier(*self)
+        Instant::now() - *self
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 impl Add<Duration> for Instant {
     type Output = Instant;
 
@@ -113,7 +122,7 @@ impl Add<Duration> for Instant {
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 impl Sub<Duration> for Instant {
     type Output = Instant;
 
@@ -122,16 +131,25 @@ impl Sub<Duration> for Instant {
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
+impl Sub<Instant> for Instant {
+    type Output = Duration;
+
+    fn sub(self, other: Instant) -> Duration {
+        self.duration_since(other)
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
 impl fmt::Debug for Instant {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
 impl SystemTime {
     /// Returns the system time corresponding to "now".
+    #[stable(feature = "time2", since = "1.8.0")]
     pub fn now() -> SystemTime {
         SystemTime(time::SystemTime::now())
     }
@@ -147,6 +165,15 @@ impl SystemTime {
     ///
     /// Returns an `Err` if `earlier` is later than `self`, and the error
     /// contains how far from `self` the time is.
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn duration_since(&self, earlier: SystemTime)
+                          -> Result<Duration, SystemTimeError> {
+        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
+    }
+
+    /// Deprecated, renamed to `duration_since`
+    #[unstable(feature = "time2_old", issue = "29866")]
+    #[rustc_deprecated(since = "1.8.0", reason = "renamed to duration_since")]
     pub fn duration_from_earlier(&self, earlier: SystemTime)
                                  -> Result<Duration, SystemTimeError> {
         self.0.sub_time(&earlier.0).map_err(SystemTimeError)
@@ -162,12 +189,13 @@ impl SystemTime {
     ///
     /// Returns an `Err` if `self` is later than the current system time, and
     /// the error contains how far from the current system time `self` is.
+    #[stable(feature = "time2", since = "1.8.0")]
     pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
-        SystemTime::now().duration_from_earlier(*self)
+        SystemTime::now().duration_since(*self)
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 impl Add<Duration> for SystemTime {
     type Output = SystemTime;
 
@@ -176,7 +204,7 @@ impl Add<Duration> for SystemTime {
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 impl Sub<Duration> for SystemTime {
     type Output = SystemTime;
 
@@ -185,7 +213,7 @@ impl Sub<Duration> for SystemTime {
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 impl fmt::Debug for SystemTime {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
@@ -196,32 +224,32 @@ impl fmt::Debug for SystemTime {
 /// learn about where in time a `SystemTime` lies.
 ///
 /// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
-/// respect to the system clock. Using `duration_from_earlier` on an existing
+/// respect to the system clock. Using `duration_since` on an existing
 /// `SystemTime` instance can tell how far away from this point in time a
 /// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
 /// `SystemTime` instance to represent another fixed point in time.
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
 impl SystemTimeError {
     /// Returns the positive duration which represents how far forward the
     /// second system time was from the first.
     ///
-    /// A `SystemTimeError` is returned from the `duration_from_earlier`
+    /// A `SystemTimeError` is returned from the `duration_since`
     /// operation whenever the second system time represents a point later
     /// in time than the `self` of the method call.
+    #[stable(feature = "time2", since = "1.8.0")]
     pub fn duration(&self) -> Duration {
         self.0
     }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 impl Error for SystemTimeError {
     fn description(&self) -> &str { "other time was not earlier than self" }
 }
 
-#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
+#[stable(feature = "time2", since = "1.8.0")]
 impl fmt::Display for SystemTimeError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "second time provided was later than self")
@@ -265,7 +293,7 @@ mod tests {
     fn instant_math() {
         let a = Instant::now();
         let b = Instant::now();
-        let dur = b.duration_from_earlier(a);
+        let dur = b.duration_since(a);
         assert_almost_eq!(b - dur, a);
         assert_almost_eq!(a + dur, b);
 
@@ -277,14 +305,14 @@ mod tests {
     #[should_panic]
     fn instant_duration_panic() {
         let a = Instant::now();
-        (a - Duration::new(1, 0)).duration_from_earlier(a);
+        (a - Duration::new(1, 0)).duration_since(a);
     }
 
     #[test]
     fn system_time_math() {
         let a = SystemTime::now();
         let b = SystemTime::now();
-        match b.duration_from_earlier(a) {
+        match b.duration_since(a) {
             Ok(dur) if dur == Duration::new(0, 0) => {
                 assert_almost_eq!(a, b);
             }
@@ -302,8 +330,8 @@ mod tests {
         }
 
         let second = Duration::new(1, 0);
-        assert_almost_eq!(a.duration_from_earlier(a - second).unwrap(), second);
-        assert_almost_eq!(a.duration_from_earlier(a + second).unwrap_err()
+        assert_almost_eq!(a.duration_since(a - second).unwrap(), second);
+        assert_almost_eq!(a.duration_since(a + second).unwrap_err()
                            .duration(), second);
 
         assert_almost_eq!(a - second + second, a);
@@ -327,8 +355,8 @@ mod tests {
     #[test]
     fn since_epoch() {
         let ts = SystemTime::now();
-        let a = ts.duration_from_earlier(UNIX_EPOCH).unwrap();
-        let b = ts.duration_from_earlier(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
+        let a = ts.duration_since(UNIX_EPOCH).unwrap();
+        let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
         assert!(b > a);
         assert_eq!(b - a, Duration::new(1, 0));
 
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 3a1d18b85b6..f5ff7fbf610 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -9,8 +9,7 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-arena = { path = "../libarena" }
-fmt_macros = { path = "../libfmt_macros" }
 serialize = { path = "../libserialize" }
 term = { path = "../libterm" }
 log = { path = "../liblog" }
+rustc_bitflags = { path = "../librustc_bitflags" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index cb79c609c1b..23bb6fd141a 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -580,7 +580,7 @@ pub enum PatKind {
     /// An associated const named using the qualified path `<T>::CONST` or
     /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
     /// referred to as simply `T::CONST`, in which case they will end up as
-    /// PatKind::Enum, and the resolver will have to sort that out.
+    /// PatKind::Path, and the resolver will have to sort that out.
     QPath(QSelf, Path),
 
     /// A tuple pattern `(a, b)`
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 8fc72418eb0..2a9d96fa861 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -760,7 +760,12 @@ impl<'a> ExtCtxt<'a> {
                               err: &mut DiagnosticBuilder<'a>) {
         let names = &self.syntax_env.names;
         if let Some(suggestion) = find_best_match_for_name(names.iter(), name, None) {
-            err.fileline_help(span, &format!("did you mean `{}!`?", suggestion));
+            if suggestion != name {
+                err.fileline_help(span, &format!("did you mean `{}!`?", suggestion));
+            } else {
+                err.fileline_help(span, &format!("have you added the `#[macro_use]` on the \
+                                                  module/import?"));
+            }
         }
     }
 }
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 8d857fc8e48..ae99fe81739 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -55,11 +55,11 @@ pub struct TtReader<'a> {
 /// This can do Macro-By-Example transcription. On the other hand, if
 /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can
 /// (and should) be None.
-pub fn new_tt_reader<'a>(sp_diag: &'a Handler,
-                         interp: Option<HashMap<Name, Rc<NamedMatch>>>,
-                         imported_from: Option<Ident>,
-                         src: Vec<ast::TokenTree>)
-                         -> TtReader<'a> {
+pub fn new_tt_reader(sp_diag: &Handler,
+                     interp: Option<HashMap<Name, Rc<NamedMatch>>>,
+                     imported_from: Option<Ident>,
+                     src: Vec<ast::TokenTree>)
+                     -> TtReader {
     new_tt_reader_with_doc_flag(sp_diag, interp, imported_from, src, false)
 }
 
@@ -69,12 +69,12 @@ pub fn new_tt_reader<'a>(sp_diag: &'a Handler,
 /// This can do Macro-By-Example transcription. On the other hand, if
 /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can
 /// (and should) be None.
-pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a Handler,
-                                       interp: Option<HashMap<Name, Rc<NamedMatch>>>,
-                                       imported_from: Option<Ident>,
-                                       src: Vec<ast::TokenTree>,
-                                       desugar_doc_comments: bool)
-                                       -> TtReader<'a> {
+pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler,
+                                   interp: Option<HashMap<Name, Rc<NamedMatch>>>,
+                                   imported_from: Option<Ident>,
+                                   src: Vec<ast::TokenTree>,
+                                   desugar_doc_comments: bool)
+                                   -> TtReader {
     let mut r = TtReader {
         sp_diag: sp_diag,
         stack: vec!(TtFrame {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 70bd85c00d4..3f2fb2d3d17 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -213,10 +213,10 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
     ("unwind_attributes", "1.4.0", None, Active),
 
     // allow empty structs and enum variants with braces
-    ("braced_empty_structs", "1.5.0", Some(29720), Active),
+    ("braced_empty_structs", "1.5.0", Some(29720), Accepted),
 
     // allow overloading augmented assignment operations like `a += b`
-    ("augmented_assignments", "1.5.0", Some(28235), Active),
+    ("augmented_assignments", "1.5.0", Some(28235), Accepted),
 
     // allow `#[no_debug]`
     ("no_debug", "1.5.0", Some(29721), Active),
@@ -563,8 +563,6 @@ pub struct Features {
     pub cfg_target_feature: bool,
     pub cfg_target_vendor: bool,
     pub cfg_target_thread_local: bool,
-    pub augmented_assignments: bool,
-    pub braced_empty_structs: bool,
     pub staged_api: bool,
     pub stmt_expr_attributes: bool,
     pub deprecated: bool,
@@ -597,8 +595,6 @@ impl Features {
             cfg_target_feature: false,
             cfg_target_vendor: false,
             cfg_target_thread_local: false,
-            augmented_assignments: false,
-            braced_empty_structs: false,
             staged_api: false,
             stmt_expr_attributes: false,
             deprecated: false,
@@ -956,10 +952,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
     fn visit_variant_data(&mut self, s: &'v ast::VariantData, _: ast::Ident,
                         _: &'v ast::Generics, _: ast::NodeId, span: Span) {
         if s.fields().is_empty() {
-            if s.is_struct() {
-                self.gate_feature("braced_empty_structs", span,
-                                  "empty structs and enum variants with braces are unstable");
-            } else if s.is_tuple() {
+            if s.is_tuple() {
                 self.context.span_handler.struct_span_err(span, "empty tuple structs and enum \
                                                                  variants are not allowed, use \
                                                                  unit structs and enum variants \
@@ -1196,8 +1189,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
         cfg_target_feature: cx.has_feature("cfg_target_feature"),
         cfg_target_vendor: cx.has_feature("cfg_target_vendor"),
         cfg_target_thread_local: cx.has_feature("cfg_target_thread_local"),
-        augmented_assignments: cx.has_feature("augmented_assignments"),
-        braced_empty_structs: cx.has_feature("braced_empty_structs"),
         staged_api: cx.has_feature("staged_api"),
         stmt_expr_attributes: cx.has_feature("stmt_expr_attributes"),
         deprecated: cx.has_feature("deprecated"),
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 505e543a3fb..0950d6082e7 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -11,7 +11,7 @@
 use attr;
 use ast;
 use codemap::{spanned, Spanned, mk_sp, Span};
-use parse::common::*; //resolve bug?
+use parse::common::SeqSep;
 use parse::PResult;
 use parse::token;
 use parse::parser::{Parser, TokenType};
@@ -200,7 +200,7 @@ impl<'a> Parser<'a> {
     fn parse_meta_seq(&mut self) -> PResult<'a, Vec<P<ast::MetaItem>>> {
         self.parse_unspanned_seq(&token::OpenDelim(token::Paren),
                                  &token::CloseDelim(token::Paren),
-                                 seq_sep_trailing_allowed(token::Comma),
+                                 SeqSep::trailing_allowed(token::Comma),
                                  |p: &mut Parser<'a>| p.parse_meta_item())
     }
 }
diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs
index 060b0b52637..b57708f9193 100644
--- a/src/libsyntax/parse/common.rs
+++ b/src/libsyntax/parse/common.rs
@@ -19,16 +19,18 @@ pub struct SeqSep {
     pub trailing_sep_allowed: bool,
 }
 
-pub fn seq_sep_trailing_allowed(t: token::Token) -> SeqSep {
-    SeqSep {
-        sep: Some(t),
-        trailing_sep_allowed: true,
+impl SeqSep {
+    pub fn trailing_allowed(t: token::Token) -> SeqSep {
+        SeqSep {
+            sep: Some(t),
+            trailing_sep_allowed: true,
+        }
     }
-}
 
-pub fn seq_sep_none() -> SeqSep {
-    SeqSep {
-        sep: None,
-        trailing_sep_allowed: false,
+    pub fn none() -> SeqSep {
+        SeqSep {
+            sep: None,
+            trailing_sep_allowed: false,
+        }
     }
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 59e79200568..b5d29a0d6db 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -50,7 +50,7 @@ use errors::{self, DiagnosticBuilder};
 use ext::tt::macro_parser;
 use parse;
 use parse::classify;
-use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed};
+use parse::common::SeqSep;
 use parse::lexer::{Reader, TokenAndSpan};
 use parse::obsolete::{ParserObsoleteMethods, ObsoleteSyntax};
 use parse::token::{self, intern, MatchNt, SubstNt, SpecialVarNt, InternedString};
@@ -72,6 +72,7 @@ bitflags! {
     flags Restrictions: u8 {
         const RESTRICTION_STMT_EXPR         = 1 << 0,
         const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
+        const NO_NONINLINE_MOD  = 1 << 2,
     }
 }
 
@@ -850,7 +851,7 @@ impl<'a> Parser<'a> {
     /// passes through any errors encountered. Used for error recovery.
     pub fn eat_to_tokens(&mut self, kets: &[&token::Token]) {
         self.parse_seq_to_before_tokens(kets,
-                                        seq_sep_none(),
+                                        SeqSep::none(),
                                         |p| p.parse_token_tree(),
                                         |mut e| e.cancel());
     }
@@ -1234,7 +1235,7 @@ impl<'a> Parser<'a> {
         self.parse_unspanned_seq(
             &token::OpenDelim(token::Brace),
             &token::CloseDelim(token::Brace),
-            seq_sep_none(),
+            SeqSep::none(),
             |p| -> PResult<'a, TraitItem> {
             maybe_whole!(no_clone_from_p p, NtTraitItem);
             let mut attrs = try!(p.parse_outer_attributes());
@@ -1459,7 +1460,7 @@ impl<'a> Parser<'a> {
                 self.bump();
                 let delim = try!(self.expect_open_delim());
                 let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
-                                                     seq_sep_none(),
+                                                     SeqSep::none(),
                                                      |p| p.parse_token_tree()));
                 let hi = self.span.hi;
                 TyKind::Mac(spanned(lo, hi, Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT }))
@@ -1799,7 +1800,7 @@ impl<'a> Parser<'a> {
 
                 let inputs = try!(self.parse_seq_to_end(
                     &token::CloseDelim(token::Paren),
-                    seq_sep_trailing_allowed(token::Comma),
+                    SeqSep::trailing_allowed(token::Comma),
                     |p| p.parse_ty_sum()));
 
                 let output_ty = if self.eat(&token::RArrow) {
@@ -2205,7 +2206,7 @@ impl<'a> Parser<'a> {
                         self.bump();
                         let remaining_exprs = try!(self.parse_seq_to_end(
                             &token::CloseDelim(token::Bracket),
-                            seq_sep_trailing_allowed(token::Comma),
+                            SeqSep::trailing_allowed(token::Comma),
                             |p| Ok(try!(p.parse_expr()))
                                 ));
                         let mut exprs = vec!(first_expr);
@@ -2324,7 +2325,7 @@ impl<'a> Parser<'a> {
                         let delim = try!(self.expect_open_delim());
                         let tts = try!(self.parse_seq_to_end(
                             &token::CloseDelim(delim),
-                            seq_sep_none(),
+                            SeqSep::none(),
                             |p| p.parse_token_tree()));
                         let hi = self.last_span.hi;
 
@@ -2497,7 +2498,7 @@ impl<'a> Parser<'a> {
                 let mut es = try!(self.parse_unspanned_seq(
                     &token::OpenDelim(token::Paren),
                     &token::CloseDelim(token::Paren),
-                    seq_sep_trailing_allowed(token::Comma),
+                    SeqSep::trailing_allowed(token::Comma),
                     |p| Ok(try!(p.parse_expr()))
                 ));
                 let hi = self.last_span.hi;
@@ -2599,7 +2600,7 @@ impl<'a> Parser<'a> {
                 let es = try!(self.parse_unspanned_seq(
                     &token::OpenDelim(token::Paren),
                     &token::CloseDelim(token::Paren),
-                    seq_sep_trailing_allowed(token::Comma),
+                    SeqSep::trailing_allowed(token::Comma),
                     |p| Ok(try!(p.parse_expr()))
                 ));
                 hi = self.last_span.hi;
@@ -2635,7 +2636,7 @@ impl<'a> Parser<'a> {
                     let Spanned { node: seq, span: seq_span } = try!(self.parse_seq(
                         &token::OpenDelim(token::Paren),
                         &token::CloseDelim(token::Paren),
-                        seq_sep_none(),
+                        SeqSep::none(),
                         |p| p.parse_token_tree()
                     ));
                     let (sep, repeat) = try!(self.parse_sep_and_kleene_op());
@@ -2748,7 +2749,7 @@ impl<'a> Parser<'a> {
 
                 // Parse the token trees within the delimiters
                 let tts = self.parse_seq_to_before_end(&token::CloseDelim(delim),
-                                                       seq_sep_none(),
+                                                       SeqSep::none(),
                                                        |p| p.parse_token_tree());
 
                 // Parse the close delimiter.
@@ -3301,8 +3302,8 @@ impl<'a> Parser<'a> {
     /// Evaluate the closure with restrictions in place.
     ///
     /// After the closure is evaluated, restrictions are reset.
-    pub fn with_res<F>(&mut self, r: Restrictions, f: F) -> PResult<'a, P<Expr>>
-        where F: FnOnce(&mut Self) -> PResult<'a,  P<Expr>>
+    pub fn with_res<F, T>(&mut self, r: Restrictions, f: F) -> T
+        where F: FnOnce(&mut Self) -> T
     {
         let old = self.restrictions;
         self.restrictions = r;
@@ -3578,7 +3579,7 @@ impl<'a> Parser<'a> {
                         self.bump();
                         let delim = try!(self.expect_open_delim());
                         let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
-                                seq_sep_none(), |p| p.parse_token_tree()));
+                                SeqSep::none(), |p| p.parse_token_tree()));
                         let mac = Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT };
                         pat = PatKind::Mac(codemap::Spanned {node: mac,
                                                        span: mk_sp(lo, self.last_span.hi)});
@@ -3637,7 +3638,7 @@ impl<'a> Parser<'a> {
                             let args = try!(self.parse_enum_variant_seq(
                                     &token::OpenDelim(token::Paren),
                                     &token::CloseDelim(token::Paren),
-                                    seq_sep_trailing_allowed(token::Comma),
+                                    SeqSep::trailing_allowed(token::Comma),
                                     |p| p.parse_pat()));
                             pat = PatKind::TupleStruct(path, Some(args));
                         }
@@ -3887,7 +3888,7 @@ impl<'a> Parser<'a> {
             let tts = try!(self.parse_unspanned_seq(
                 &token::OpenDelim(delim),
                 &token::CloseDelim(delim),
-                seq_sep_none(),
+                SeqSep::none(),
                 |p| p.parse_token_tree()
             ));
             let hi = self.last_span.hi;
@@ -3926,7 +3927,9 @@ impl<'a> Parser<'a> {
             }
         } else {
             // FIXME: Bad copy of attrs
-            match try!(self.parse_item_(attrs.clone(), false, true)) {
+            let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD;
+            match try!(self.with_res(restrictions,
+                                     |this| this.parse_item_(attrs.clone(), false, true))) {
                 Some(i) => {
                     let hi = i.span.hi;
                     let decl = P(spanned(lo, hi, DeclKind::Item(i)));
@@ -4469,7 +4472,7 @@ impl<'a> Parser<'a> {
             try!(self.parse_unspanned_seq(
                 &token::OpenDelim(token::Paren),
                 &token::CloseDelim(token::Paren),
-                seq_sep_trailing_allowed(token::Comma),
+                SeqSep::trailing_allowed(token::Comma),
                 |p| {
                     if p.token == token::DotDotDot {
                         p.bump();
@@ -4681,7 +4684,7 @@ impl<'a> Parser<'a> {
             match self.token {
                 token::Comma => {
                     self.bump();
-                    let sep = seq_sep_trailing_allowed(token::Comma);
+                    let sep = SeqSep::trailing_allowed(token::Comma);
                     let mut fn_inputs = self.parse_seq_to_before_end(
                         &token::CloseDelim(token::Paren),
                         sep,
@@ -4704,7 +4707,7 @@ impl<'a> Parser<'a> {
 
         let fn_inputs = match explicit_self {
             SelfKind::Static =>  {
-                let sep = seq_sep_trailing_allowed(token::Comma);
+                let sep = SeqSep::trailing_allowed(token::Comma);
                 self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)
             }
             SelfKind::Value(id) => parse_remaining_arguments!(id),
@@ -4738,7 +4741,7 @@ impl<'a> Parser<'a> {
                 try!(self.parse_obsolete_closure_kind());
                 let args = self.parse_seq_to_before_end(
                     &token::BinOp(token::Or),
-                    seq_sep_trailing_allowed(token::Comma),
+                    SeqSep::trailing_allowed(token::Comma),
                     |p| p.parse_fn_block_arg()
                 );
                 self.bump();
@@ -4902,7 +4905,7 @@ impl<'a> Parser<'a> {
             // eat a matched-delimiter token tree:
             let delim = try!(self.expect_open_delim());
             let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
-                                                 seq_sep_none(),
+                                                 SeqSep::none(),
                                                  |p| p.parse_token_tree()));
             let m_ = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
             let m: ast::Mac = codemap::Spanned { node: m_,
@@ -5139,7 +5142,7 @@ impl<'a> Parser<'a> {
         let fields = try!(self.parse_unspanned_seq(
             &token::OpenDelim(token::Paren),
             &token::CloseDelim(token::Paren),
-            seq_sep_trailing_allowed(token::Comma),
+            SeqSep::trailing_allowed(token::Comma),
             |p| {
                 let attrs = try!(p.parse_outer_attributes());
                 let lo = p.span.lo;
@@ -5257,11 +5260,8 @@ impl<'a> Parser<'a> {
             self.push_mod_path(id, outer_attrs);
             try!(self.expect(&token::OpenDelim(token::Brace)));
             let mod_inner_lo = self.span.lo;
-            let old_owns_directory = self.owns_directory;
-            self.owns_directory = true;
             let attrs = try!(self.parse_inner_attributes());
             let m = try!(self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo));
-            self.owns_directory = old_owns_directory;
             self.pop_mod_path();
             Ok((id, ItemKind::Mod(m), Some(attrs)))
         }
@@ -5338,7 +5338,17 @@ impl<'a> Parser<'a> {
 
         let paths = Parser::default_submod_path(id, &dir_path, self.sess.codemap());
 
-        if !self.owns_directory {
+        if self.restrictions.contains(Restrictions::NO_NONINLINE_MOD) {
+            let msg =
+                "Cannot declare a non-inline module inside a block unless it has a path attribute";
+            let mut err = self.diagnostic().struct_span_err(id_sp, msg);
+            if paths.path_exists {
+                let msg = format!("Maybe `use` the module `{}` instead of redeclaring it",
+                                  paths.name);
+                err.span_note(id_sp, &msg);
+            }
+            return Err(err);
+        } else if !self.owns_directory {
             let mut err = self.diagnostic().struct_span_err(id_sp,
                 "cannot declare a new module at this location");
             let this_module = match self.mod_path_stack.last() {
@@ -5477,13 +5487,6 @@ impl<'a> Parser<'a> {
         try!(self.expect(&token::Semi));
 
         let last_span = self.last_span;
-
-        if visibility == ast::Visibility::Public {
-            self.span_warn(mk_sp(lo, last_span.hi),
-                           "`pub extern crate` does not work as expected and should not be used. \
-                            Likely to become an error. Prefer `extern crate` and `pub use`.");
-        }
-
         Ok(self.mk_item(lo,
                         last_span.hi,
                         ident,
@@ -5962,7 +5965,7 @@ impl<'a> Parser<'a> {
             // eat a matched-delimiter token tree:
             let delim = try!(self.expect_open_delim());
             let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
-                                                 seq_sep_none(),
+                                                 SeqSep::none(),
                                                  |p| p.parse_token_tree()));
             // single-variant-enum... :
             let m = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
@@ -6029,7 +6032,7 @@ impl<'a> Parser<'a> {
             let idents = try!(self.parse_unspanned_seq(
                 &token::OpenDelim(token::Brace),
                 &token::CloseDelim(token::Brace),
-                seq_sep_trailing_allowed(token::Comma),
+                SeqSep::trailing_allowed(token::Comma),
                 |p| p.parse_path_list_item()));
             let path = ast::Path {
                 span: mk_sp(lo, self.span.hi),
@@ -6057,7 +6060,7 @@ impl<'a> Parser<'a> {
                     let idents = try!(self.parse_unspanned_seq(
                         &token::OpenDelim(token::Brace),
                         &token::CloseDelim(token::Brace),
-                        seq_sep_trailing_allowed(token::Comma),
+                        SeqSep::trailing_allowed(token::Comma),
                         |p| p.parse_path_list_item()
                     ));
                     let path = ast::Path {
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs
index 1825c3d347e..0085182d1ac 100644
--- a/src/libsyntax_ext/deriving/clone.rs
+++ b/src/libsyntax_ext/deriving/clone.rs
@@ -11,7 +11,7 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr};
+use syntax::ast::{MetaItem, Expr, VariantData};
 use syntax::codemap::Span;
 use syntax::ext::base::{ExtCtxt, Annotatable};
 use syntax::ext::build::AstBuilder;
@@ -66,14 +66,17 @@ fn cs_clone(
         cx.expr_call_global(field.span, fn_path.clone(), args)
     };
 
+    let vdata;
     match *substr.fields {
-        Struct(ref af) => {
+        Struct(vdata_, ref af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident]);
             all_fields = af;
+            vdata = vdata_;
         }
         EnumMatching(_, variant, ref af) => {
             ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
             all_fields = af;
+            vdata = &variant.node.data;
         },
         EnumNonMatchingCollapsed (..) => {
             cx.span_bug(trait_span,
@@ -86,30 +89,29 @@ fn cs_clone(
         }
     }
 
-    if !all_fields.is_empty() && all_fields[0].name.is_none() {
-        // enum-like
-        let subcalls = all_fields.iter().map(subcall).collect();
-        let path = cx.expr_path(ctor_path);
-        cx.expr_call(trait_span, path, subcalls)
-    } else {
-        // struct-like
-        let fields = all_fields.iter().map(|field| {
-            let ident = match field.name {
-                Some(i) => i,
-                None => {
-                    cx.span_bug(trait_span,
-                                &format!("unnamed field in normal struct in \
-                                         `derive({})`", name))
-                }
-            };
-            cx.field_imm(field.span, ident, subcall(field))
-        }).collect::<Vec<_>>();
+    match *vdata {
+        VariantData::Struct(..) => {
+            let fields = all_fields.iter().map(|field| {
+                let ident = match field.name {
+                    Some(i) => i,
+                    None => {
+                        cx.span_bug(trait_span,
+                                    &format!("unnamed field in normal struct in \
+                                             `derive({})`", name))
+                    }
+                };
+                cx.field_imm(field.span, ident, subcall(field))
+            }).collect::<Vec<_>>();
 
-        if fields.is_empty() {
-            // no fields, so construct like `None`
-            cx.expr_path(ctor_path)
-        } else {
             cx.expr_struct(trait_span, ctor_path, fields)
         }
+        VariantData::Tuple(..) => {
+            let subcalls = all_fields.iter().map(subcall).collect();
+            let path = cx.expr_path(ctor_path);
+            cx.expr_call(trait_span, path, subcalls)
+        }
+        VariantData::Unit(..) => {
+            cx.expr_path(ctor_path)
+        }
     }
 }
diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs
index 6439e9aa498..323c6c388fb 100644
--- a/src/libsyntax_ext/deriving/debug.rs
+++ b/src/libsyntax_ext/deriving/debug.rs
@@ -61,9 +61,9 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
     // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
     // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
     // based on the "shape".
-    let ident = match *substr.fields {
-        Struct(_) => substr.type_ident,
-        EnumMatching(_, v, _) => v.node.name,
+    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()),
         EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
             cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
         }
@@ -78,9 +78,9 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
     let fmt = substr.nonself_args[0].clone();
 
     let stmts = match *substr.fields {
-        Struct(ref fields) | EnumMatching(_, _, ref fields) => {
+        Struct(_, ref fields) | EnumMatching(_, _, ref fields) => {
             let mut stmts = vec![];
-            if fields.is_empty() || fields[0].name.is_none() {
+            if !is_struct {
                 // tuple struct/"normal" variant
                 let expr = cx.expr_method_call(span,
                                                fmt,
diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs
index 614a6381962..8262a04e9ce 100644
--- a/src/libsyntax_ext/deriving/encodable.rs
+++ b/src/libsyntax_ext/deriving/encodable.rs
@@ -179,7 +179,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
     let encode = cx.ident_of("encode");
 
     return match *substr.fields {
-        Struct(ref fields) => {
+        Struct(_, ref fields) => {
             let emit_struct_field = cx.ident_of("emit_struct_field");
             let mut stmts = Vec::new();
             for (i, &FieldInfo {
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index bdba49f2f29..c0237a5d29a 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -300,7 +300,7 @@ pub enum StaticFields {
 
 /// A summary of the possible sets of fields.
 pub enum SubstructureFields<'a> {
-    Struct(Vec<FieldInfo<'a>>),
+    Struct(&'a ast::VariantData, Vec<FieldInfo<'a>>),
     /// Matching variants of the enum: variant index, ast::Variant,
     /// fields: the field name is only non-`None` in the case of a struct
     /// variant.
@@ -981,7 +981,7 @@ impl<'a> MethodDef<'a> {
             type_ident,
             self_args,
             nonself_args,
-            &Struct(fields));
+            &Struct(struct_def, fields));
 
         // make a series of nested matches, to destructure the
         // structs. This is actually right-to-left, but it shouldn't
@@ -1460,8 +1460,9 @@ impl<'a> TraitDef<'a> {
                                           fields in generic `derive`"),
             // named fields
             (_, false) => Named(named_idents),
-            // tuple structs (includes empty structs)
-            (_, _)     => Unnamed(just_spans)
+            // empty structs
+            _ if struct_def.is_struct() => Named(named_idents),
+            _ => Unnamed(just_spans),
         }
     }
 
@@ -1486,7 +1487,11 @@ impl<'a> TraitDef<'a> {
                                                    P<Expr>,
                                                    &'a [ast::Attribute])>) {
         if struct_def.fields().is_empty() {
-            return (cx.pat_enum(self.span, struct_path, vec![]), vec![]);
+            if struct_def.is_struct() {
+                return (cx.pat_struct(self.span, struct_path, vec![]), vec![]);
+            } else {
+                return (cx.pat_enum(self.span, struct_path, vec![]), vec![]);
+            }
         }
 
         let mut paths = Vec::new();
@@ -1521,7 +1526,7 @@ impl<'a> TraitDef<'a> {
 
         // struct_type is definitely not Unknown, since struct_def.fields
         // must be nonempty to reach here
-        let pattern = if struct_type == Record {
+        let pattern = if struct_def.is_struct() {
             let field_pats = subpats.into_iter().zip(&ident_expr)
                                     .map(|(pat, &(_, id, _, _))| {
                 // id is guaranteed to be Some
@@ -1566,7 +1571,7 @@ pub fn cs_fold<F>(use_foldl: bool,
     F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>,
 {
     match *substructure.fields {
-        EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
+        EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => {
             if use_foldl {
                 all_fields.iter().fold(base, |old, field| {
                     f(cx,
@@ -1612,7 +1617,7 @@ pub fn cs_same_method<F>(f: F,
     F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>,
 {
     match *substructure.fields {
-        EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => {
+        EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => {
             // call self_n.method(other_1_n, other_2_n, ...)
             let called = all_fields.iter().map(|field| {
                 cx.expr_method_call(field.span,
diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs
index 371ba732b48..bf8aa8fb23d 100644
--- a/src/libsyntax_ext/deriving/hash.rs
+++ b/src/libsyntax_ext/deriving/hash.rs
@@ -76,7 +76,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) => fs,
         EnumMatching(index, variant, ref fs) => {
             // Determine the discriminant. We will feed this value to the byte
             // iteration function.
diff --git a/src/libterm/Cargo.toml b/src/libterm/Cargo.toml
index cdfc957297d..8021e814c08 100644
--- a/src/libterm/Cargo.toml
+++ b/src/libterm/Cargo.toml
@@ -7,6 +7,3 @@ version = "0.0.0"
 name = "term"
 path = "lib.rs"
 crate-type = ["dylib", "rlib"]
-
-[dependencies]
-log = { path = "../liblog" }
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index 771e2470455..01daa938142 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -211,10 +211,10 @@ pub trait Terminal: Write {
     fn reset(&mut self) -> io::Result<bool>;
 
     /// Gets an immutable reference to the stream inside
-    fn get_ref<'a>(&'a self) -> &'a Self::Output;
+    fn get_ref(&self) -> &Self::Output;
 
     /// Gets a mutable reference to the stream inside
-    fn get_mut<'a>(&'a mut self) -> &'a mut Self::Output;
+    fn get_mut(&mut self) -> &mut Self::Output;
 
     /// Returns the contained stream, destroying the `Terminal`
     fn into_inner(self) -> Self::Output where Self: Sized;
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
index 04486132c84..e54f763fd0d 100644
--- a/src/libterm/terminfo/mod.rs
+++ b/src/libterm/terminfo/mod.rs
@@ -205,11 +205,11 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
         self.out.write_all(&cmd).and(Ok(true))
     }
 
-    fn get_ref<'a>(&'a self) -> &'a T {
+    fn get_ref(&self) -> &T {
         &self.out
     }
 
-    fn get_mut<'a>(&'a mut self) -> &'a mut T {
+    fn get_mut(&mut self) -> &mut T {
         &mut self.out
     }
 
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index 5693cc10a0f..7536ab9c5af 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -40,7 +40,6 @@
 #![feature(rustc_private)]
 #![feature(set_stdio)]
 #![feature(staged_api)]
-#![feature(time2)]
 
 extern crate getopts;
 extern crate serialize;
@@ -203,7 +202,12 @@ pub struct TestDesc {
     pub should_panic: ShouldPanic,
 }
 
-unsafe impl Send for TestDesc {}
+#[derive(Clone)]
+pub struct TestPaths {
+    pub file: PathBuf,         // e.g., compile-test/foo/bar/baz.rs
+    pub base: PathBuf,         // e.g., compile-test, auxiliary
+    pub relative_dir: PathBuf, // e.g., foo/bar
+}
 
 #[derive(Debug)]
 pub struct TestDescAndFn {
diff --git a/src/llvm b/src/llvm
-Subproject de5c31045dc0f6da1f65d02ee640ccf99ba90e7
+Subproject 69ef168544e4f15b793dd35d272008fde9a6e83
diff --git a/src/nightlies.txt b/src/nightlies.txt
index 86186222d90..59e2fce6f09 100644
--- a/src/nightlies.txt
+++ b/src/nightlies.txt
@@ -1,2 +1,2 @@
-rustc: 2015-12-19
+rustc: 2016-02-17
 cargo: 2016-01-21
diff --git a/src/rustc/Cargo.lock b/src/rustc/Cargo.lock
index 2a7da33bb68..e4432720ab4 100644
--- a/src/rustc/Cargo.lock
+++ b/src/rustc/Cargo.lock
@@ -86,6 +86,7 @@ dependencies = [
  "log 0.0.0",
  "rbml 0.0.0",
  "rustc_back 0.0.0",
+ "rustc_bitflags 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_front 0.0.0",
  "rustc_llvm 0.0.0",
@@ -105,6 +106,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_bitflags"
+version = "0.0.0"
+
+[[package]]
 name = "rustc_borrowck"
 version = "0.0.0"
 dependencies = [
@@ -156,6 +161,7 @@ name = "rustc_front"
 version = "0.0.0"
 dependencies = [
  "log 0.0.0",
+ "rustc_bitflags 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
 ]
@@ -177,6 +183,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_bitflags 0.0.0",
 ]
 
 [[package]]
@@ -188,6 +195,7 @@ dependencies = [
  "rbml 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
+ "rustc_bitflags 0.0.0",
  "rustc_front 0.0.0",
  "rustc_llvm 0.0.0",
  "serialize 0.0.0",
@@ -231,6 +239,7 @@ version = "0.0.0"
 dependencies = [
  "log 0.0.0",
  "rustc 0.0.0",
+ "rustc_bitflags 0.0.0",
  "rustc_front 0.0.0",
  "rustc_metadata 0.0.0",
  "rustc_mir 0.0.0",
@@ -254,6 +263,7 @@ dependencies = [
  "arena 0.0.0",
  "log 0.0.0",
  "rustc 0.0.0",
+ "rustc_bitflags 0.0.0",
  "rustc_front 0.0.0",
  "syntax 0.0.0",
 ]
@@ -325,9 +335,8 @@ dependencies = [
 name = "syntax"
 version = "0.0.0"
 dependencies = [
- "arena 0.0.0",
- "fmt_macros 0.0.0",
  "log 0.0.0",
+ "rustc_bitflags 0.0.0",
  "serialize 0.0.0",
  "term 0.0.0",
 ]
@@ -343,9 +352,6 @@ dependencies = [
 [[package]]
 name = "term"
 version = "0.0.0"
-dependencies = [
- "log 0.0.0",
-]
 
 [[package]]
 name = "test"
diff --git a/src/rustc/std_shim/Cargo.lock b/src/rustc/std_shim/Cargo.lock
index d88e9c7e5aa..530c04da8a0 100644
--- a/src/rustc/std_shim/Cargo.lock
+++ b/src/rustc/std_shim/Cargo.lock
@@ -18,9 +18,7 @@ dependencies = [
 name = "alloc"
 version = "0.0.0"
 dependencies = [
- "alloc_system 0.0.0",
  "core 0.0.0",
- "libc 0.0.0",
 ]
 
 [[package]]
@@ -82,13 +80,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_bitflags"
-version = "0.0.0"
-dependencies = [
- "core 0.0.0",
-]
-
-[[package]]
 name = "rustc_unicode"
 version = "0.0.0"
 dependencies = [
@@ -108,7 +99,6 @@ dependencies = [
  "gcc 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "rand 0.0.0",
- "rustc_bitflags 0.0.0",
  "rustc_unicode 0.0.0",
 ]
 
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index ecf9146a1d0..4ebe49512d7 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -191,11 +191,15 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
                                                LLVMValueRef old,
                                                LLVMValueRef source,
                                                AtomicOrdering order,
-                                               AtomicOrdering failure_order) {
-    return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
-                                               unwrap(source), order,
-                                               failure_order
-                                               ));
+                                               AtomicOrdering failure_order,
+                                               LLVMBool weak) {
+    AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(unwrap(target),
+                                                             unwrap(old),
+                                                             unwrap(source),
+                                                             order,
+                                                             failure_order);
+    acxi->setWeak(weak);
+    return wrap(acxi);
 }
 extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
                                              AtomicOrdering order,
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index 7df7df505cd..bb34b6f38bf 100644
--- a/src/rustllvm/llvm-auto-clean-trigger
+++ b/src/rustllvm/llvm-auto-clean-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly 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.
-2015-01-25
+2016-02-20
diff --git a/src/snapshots.txt b/src/snapshots.txt
index f64c9d36025..9b3390d7747 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,12 @@
+S 2016-02-17 4d3eebf
+  linux-i386 5f194aa7628c0703f0fd48adc4ec7f3cc64b98c7
+  linux-x86_64 d29b7607d13d64078b6324aec82926fb493f59ba
+  macos-i386 4c8e42dd649e247f3576bf9dfa273327b4907f9c
+  macos-x86_64 411a41363f922d1d93fa62ff2fedf5c35e9cccb2
+  winnt-i386 0c336d794a65f8e285c121866c7d59aa2dd0d1e1
+  winnt-x86_64 27e75b1bf99770b3564bcebd7f3230be01135a92
+  openbsd-x86_64 ac957c6b84de2bd67f01df085d9ea515f96e22f3
+
 S 2015-12-18 3391630
   bitrig-x86_64 6476e1562df02389b55553b4c88b1f4fd121cd40
   freebsd-i386 7e624c50494402e1feb14c743d659fbd71b448f5
diff --git a/src/test/auxiliary/augmented_assignments.rs b/src/test/auxiliary/augmented_assignments.rs
index 9577e1ff0c7..6601e7240a7 100644
--- a/src/test/auxiliary/augmented_assignments.rs
+++ b/src/test/auxiliary/augmented_assignments.rs
@@ -8,15 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(augmented_assignments)]
-#![feature(op_assign_traits)]
-
 use std::ops::AddAssign;
 
-pub struct Int(i32);
+pub struct Int(pub i32);
 
 impl AddAssign<i32> for Int {
     fn add_assign(&mut self, _: i32) {
-        unimplemented!();
     }
 }
diff --git a/src/test/auxiliary/custom_derive_plugin_attr.rs b/src/test/auxiliary/custom_derive_plugin_attr.rs
index ba216289fd4..2878674f0ea 100644
--- a/src/test/auxiliary/custom_derive_plugin_attr.rs
+++ b/src/test/auxiliary/custom_derive_plugin_attr.rs
@@ -73,7 +73,7 @@ fn expand(cx: &mut ExtCtxt,
 fn totalsum_substructure(cx: &mut ExtCtxt, trait_span: Span,
                          substr: &Substructure) -> P<ast::Expr> {
     let fields = match *substr.fields {
-        Struct(ref fs) | EnumMatching(_, _, ref fs) => fs,
+        Struct(_, ref fs) | EnumMatching(_, _, ref fs) => fs,
         _ => cx.span_bug(trait_span, "impossible substructure")
     };
 
diff --git a/src/test/auxiliary/dummy_mir_pass.rs b/src/test/auxiliary/dummy_mir_pass.rs
index df9ea4ab012..16ef965e0db 100644
--- a/src/test/auxiliary/dummy_mir_pass.rs
+++ b/src/test/auxiliary/dummy_mir_pass.rs
@@ -21,17 +21,14 @@ extern crate syntax;
 use rustc::mir::transform::MirPass;
 use rustc::mir::repr::{Mir, Literal};
 use rustc::mir::visit::MutVisitor;
-use rustc::middle::ty;
+use rustc::middle::infer::InferCtxt;
 use rustc::middle::const_eval::ConstVal;
-use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
 use rustc_plugin::Registry;
-use rustc_front::hir;
-use syntax::attr;
 
 struct Pass;
 
 impl MirPass for Pass {
-    fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) {
+    fn run_on_mir<'a, 'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &InferCtxt<'a, 'tcx>) {
         Visitor.visit_mir(mir)
     }
 }
diff --git a/src/test/auxiliary/empty-struct.rs b/src/test/auxiliary/empty-struct.rs
index 3b92bc31217..22f65c2b0d8 100644
--- a/src/test/auxiliary/empty-struct.rs
+++ b/src/test/auxiliary/empty-struct.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(braced_empty_structs)]
-
 pub struct XEmpty1 {}
 pub struct XEmpty2;
 
diff --git a/src/test/auxiliary/issue-21221-3.rs b/src/test/auxiliary/issue-21221-3.rs
new file mode 100644
index 00000000000..fae0fe16a26
--- /dev/null
+++ b/src/test/auxiliary/issue-21221-3.rs
@@ -0,0 +1,29 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+#![crate_type="lib"]
+
+pub mod outer {
+    // should suggest this
+    pub trait OuterTrait {}
+
+    // should not suggest this since the module is private
+    mod private_module {
+        pub trait OuterTrait {}
+    }
+
+    // should not suggest since the trait is private
+    pub mod public_module {
+        trait OuterTrait {}
+    }
+}
diff --git a/src/test/auxiliary/issue-21221-4.rs b/src/test/auxiliary/issue-21221-4.rs
new file mode 100644
index 00000000000..fffe060ee24
--- /dev/null
+++ b/src/test/auxiliary/issue-21221-4.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+#![crate_type="lib"]
+
+mod foo {
+    // should not be suggested => foo is private
+    pub trait T {}
+}
+
+// should be suggested
+pub use foo::T;
diff --git a/src/test/auxiliary/issue-29584.rs b/src/test/auxiliary/issue-29584.rs
new file mode 100644
index 00000000000..4a9e6126fc6
--- /dev/null
+++ b/src/test/auxiliary/issue-29584.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.
+
+pub struct Foo;
+
+#[doc(hidden)]
+mod bar {
+    trait Bar {}
+
+    impl Bar for ::Foo {}
+}
diff --git a/src/test/auxiliary/issue-31702-1.rs b/src/test/auxiliary/issue-31702-1.rs
new file mode 100644
index 00000000000..50a31630df3
--- /dev/null
+++ b/src/test/auxiliary/issue-31702-1.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Copy)]
+pub struct U256(pub [u64; 4]);
+
+impl Clone for U256 {
+    fn clone(&self) -> U256 {
+        *self
+    }
+}
+
+impl U256 {
+    pub fn new(value: u64) -> U256 {
+        let mut ret = [0; 4];
+        ret[0] = value;
+        U256(ret)
+    }
+}
diff --git a/src/test/auxiliary/issue-31702-2.rs b/src/test/auxiliary/issue-31702-2.rs
new file mode 100644
index 00000000000..c5b1bc6dfb0
--- /dev/null
+++ b/src/test/auxiliary/issue-31702-2.rs
@@ -0,0 +1,30 @@
+// 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: -g
+
+extern crate issue_31702_1;
+
+use std::collections::HashMap;
+use issue_31702_1::U256;
+
+pub struct Ethash {
+    engine_params: for<'a> fn() -> Option<&'a Vec<u8>>,
+    u256_params: HashMap<String, U256>,
+}
+
+impl Ethash {
+    pub fn u256_param(&mut self, name: &str) -> U256 {
+        let engine = self.engine_params;
+        *self.u256_params.entry(name.to_owned()).or_insert_with(|| {
+            engine().map_or(U256::new(0u64), |_a| loop {})
+        })
+    }
+}
diff --git a/src/test/auxiliary/privacy_reexport.rs b/src/test/auxiliary/privacy_reexport.rs
index e60dbb290b0..fd97f210a55 100644
--- a/src/test/auxiliary/privacy_reexport.rs
+++ b/src/test/auxiliary/privacy_reexport.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+pub extern crate core;
 pub use foo as bar;
 
 pub mod foo {
diff --git a/src/test/auxiliary/reachable-unnameable-items.rs b/src/test/auxiliary/reachable-unnameable-items.rs
new file mode 100644
index 00000000000..7ec2bb9394c
--- /dev/null
+++ b/src/test/auxiliary/reachable-unnameable-items.rs
@@ -0,0 +1,116 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use inner_private_module::*;
+
+mod inner_private_module {
+    pub struct Unnameable1;
+    pub struct Unnameable2;
+    #[derive(Clone, Copy)]
+    pub struct Unnameable3;
+    pub struct Unnameable4;
+    pub struct Unnameable5;
+    pub struct Unnameable6;
+    pub struct Unnameable7;
+    #[derive(Default)]
+    pub struct Unnameable8;
+    pub enum UnnameableEnum {
+        NameableVariant
+    }
+    pub trait UnnameableTrait {
+        type Alias: Default;
+    }
+
+    impl Unnameable1 {
+        pub fn method_of_unnameable_type1(&self) -> &'static str {
+            "Hello1"
+        }
+    }
+    impl Unnameable2 {
+        pub fn method_of_unnameable_type2(&self) -> &'static str {
+            "Hello2"
+        }
+    }
+    impl Unnameable3 {
+        pub fn method_of_unnameable_type3(&self) -> &'static str {
+            "Hello3"
+        }
+    }
+    impl Unnameable4 {
+        pub fn method_of_unnameable_type4(&self) -> &'static str {
+            "Hello4"
+        }
+    }
+    impl Unnameable5 {
+        pub fn method_of_unnameable_type5(&self) -> &'static str {
+            "Hello5"
+        }
+    }
+    impl Unnameable6 {
+        pub fn method_of_unnameable_type6(&self) -> &'static str {
+            "Hello6"
+        }
+    }
+    impl Unnameable7 {
+        pub fn method_of_unnameable_type7(&self) -> &'static str {
+            "Hello7"
+        }
+    }
+    impl Unnameable8 {
+        pub fn method_of_unnameable_type8(&self) -> &'static str {
+            "Hello8"
+        }
+    }
+    impl UnnameableEnum {
+        pub fn method_of_unnameable_enum(&self) -> &'static str {
+            "HelloEnum"
+        }
+    }
+}
+
+pub fn function_returning_unnameable_type() -> Unnameable1 {
+    Unnameable1
+}
+
+pub const CONSTANT_OF_UNNAMEABLE_TYPE: Unnameable2 =
+                                            Unnameable2;
+
+pub fn function_accepting_unnameable_type(_: Option<Unnameable3>) {}
+
+pub type AliasOfUnnameableType = Unnameable4;
+
+impl Unnameable1 {
+    pub fn inherent_method_returning_unnameable_type(&self) -> Unnameable5 {
+        Unnameable5
+    }
+}
+
+pub trait Tr {
+    fn trait_method_returning_unnameable_type(&self) -> Unnameable6 {
+        Unnameable6
+    }
+}
+impl Tr for Unnameable1 {}
+
+pub use inner_private_module::UnnameableEnum::NameableVariant;
+
+pub struct Struct {
+    pub field_of_unnameable_type: Unnameable7
+}
+
+pub static STATIC: Struct = Struct { field_of_unnameable_type: Unnameable7 } ;
+
+impl UnnameableTrait for AliasOfUnnameableType {
+    type Alias = Unnameable8;
+}
+
+pub fn generic_function<T: UnnameableTrait>() -> T::Alias {
+    Default::default()
+}
diff --git a/src/test/auxiliary/thread-local-extern-static.rs b/src/test/auxiliary/thread-local-extern-static.rs
new file mode 100644
index 00000000000..d1971a5e1ae
--- /dev/null
+++ b/src/test/auxiliary/thread-local-extern-static.rs
@@ -0,0 +1,17 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(thread_local)]
+#![feature(cfg_target_thread_local)]
+#![crate_type = "lib"]
+
+#[no_mangle]
+#[cfg_attr(target_thread_local, thread_local)]
+pub static FOO: u32 = 3;
diff --git a/src/test/compile-fail/associated-types-eq-1.rs b/src/test/compile-fail/associated-types-eq-1.rs
index 58dbb986325..59d87146097 100644
--- a/src/test/compile-fail/associated-types-eq-1.rs
+++ b/src/test/compile-fail/associated-types-eq-1.rs
@@ -17,7 +17,7 @@ pub trait Foo {
 }
 
 fn foo2<I: Foo>(x: I) {
-    let _: A = x.boo(); //~ERROR use of undeclared
+    let _: A = x.boo(); //~ERROR undefined or not in scope
 }
 
 pub fn main() {}
diff --git a/src/test/compile-fail/augmented-assignments.rs b/src/test/compile-fail/augmented-assignments.rs
index ee64171fd8c..221015d5120 100644
--- a/src/test/compile-fail/augmented-assignments.rs
+++ b/src/test/compile-fail/augmented-assignments.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(augmented_assignments)]
-
 use std::ops::AddAssign;
 
 struct Int(i32);
diff --git a/src/test/compile-fail/bad-type-env-capture.rs b/src/test/compile-fail/bad-type-env-capture.rs
index 4e5dc652fb5..a3139905244 100644
--- a/src/test/compile-fail/bad-type-env-capture.rs
+++ b/src/test/compile-fail/bad-type-env-capture.rs
@@ -10,6 +10,6 @@
 
 fn foo<T>() {
     fn bar(b: T) { } //~ ERROR can't use type parameters from outer
-    //~^ ERROR use of undeclared type name
+    //~^ ERROR type name `T` is undefined or not in scope
 }
 fn main() { }
diff --git a/src/test/compile-fail/borrowck-and-init.rs b/src/test/compile-fail/borrowck/borrowck-and-init.rs
index 92f16d8ffce..92f16d8ffce 100644
--- a/src/test/compile-fail/borrowck-and-init.rs
+++ b/src/test/compile-fail/borrowck/borrowck-and-init.rs
diff --git a/src/test/compile-fail/borrowck-anon-fields-struct.rs b/src/test/compile-fail/borrowck/borrowck-anon-fields-struct.rs
index 5ee2b89dd98..5ee2b89dd98 100644
--- a/src/test/compile-fail/borrowck-anon-fields-struct.rs
+++ b/src/test/compile-fail/borrowck/borrowck-anon-fields-struct.rs
diff --git a/src/test/compile-fail/borrowck-anon-fields-tuple.rs b/src/test/compile-fail/borrowck/borrowck-anon-fields-tuple.rs
index ebaed01756f..ebaed01756f 100644
--- a/src/test/compile-fail/borrowck-anon-fields-tuple.rs
+++ b/src/test/compile-fail/borrowck/borrowck-anon-fields-tuple.rs
diff --git a/src/test/compile-fail/borrowck-anon-fields-variant.rs b/src/test/compile-fail/borrowck/borrowck-anon-fields-variant.rs
index 4e1b85283a6..4e1b85283a6 100644
--- a/src/test/compile-fail/borrowck-anon-fields-variant.rs
+++ b/src/test/compile-fail/borrowck/borrowck-anon-fields-variant.rs
diff --git a/src/test/compile-fail/borrowck-argument.rs b/src/test/compile-fail/borrowck/borrowck-argument.rs
index 3230689e53c..3230689e53c 100644
--- a/src/test/compile-fail/borrowck-argument.rs
+++ b/src/test/compile-fail/borrowck/borrowck-argument.rs
diff --git a/src/test/compile-fail/borrowck-assign-comp-idx.rs b/src/test/compile-fail/borrowck/borrowck-assign-comp-idx.rs
index b18df7f3db6..b18df7f3db6 100644
--- a/src/test/compile-fail/borrowck-assign-comp-idx.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-comp-idx.rs
diff --git a/src/test/compile-fail/borrowck-assign-comp.rs b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
index 802b83119b7..802b83119b7 100644
--- a/src/test/compile-fail/borrowck-assign-comp.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
diff --git a/src/test/compile-fail/borrowck-assign-to-andmut-in-aliasable-loc.rs b/src/test/compile-fail/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs
index d66cdb99a74..d66cdb99a74 100644
--- a/src/test/compile-fail/borrowck-assign-to-andmut-in-aliasable-loc.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.rs
diff --git a/src/test/compile-fail/borrowck-assign-to-andmut-in-borrowed-loc.rs b/src/test/compile-fail/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs
index 77aa57ef1b5..77aa57ef1b5 100644
--- a/src/test/compile-fail/borrowck-assign-to-andmut-in-borrowed-loc.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-to-andmut-in-borrowed-loc.rs
diff --git a/src/test/compile-fail/borrowck-assign-to-constants.rs b/src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs
index 1b5b1899e0d..1b5b1899e0d 100644
--- a/src/test/compile-fail/borrowck-assign-to-constants.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-to-constants.rs
diff --git a/src/test/compile-fail/borrowck-auto-mut-ref-to-immut-var.rs b/src/test/compile-fail/borrowck/borrowck-auto-mut-ref-to-immut-var.rs
index ea020dc0685..ea020dc0685 100644
--- a/src/test/compile-fail/borrowck-auto-mut-ref-to-immut-var.rs
+++ b/src/test/compile-fail/borrowck/borrowck-auto-mut-ref-to-immut-var.rs
diff --git a/src/test/compile-fail/borrowck-autoref-3261.rs b/src/test/compile-fail/borrowck/borrowck-autoref-3261.rs
index d5f09305808..d5f09305808 100644
--- a/src/test/compile-fail/borrowck-autoref-3261.rs
+++ b/src/test/compile-fail/borrowck/borrowck-autoref-3261.rs
diff --git a/src/test/compile-fail/borrowck-bad-nested-calls-free.rs b/src/test/compile-fail/borrowck/borrowck-bad-nested-calls-free.rs
index 7913f9ac903..7913f9ac903 100644
--- a/src/test/compile-fail/borrowck-bad-nested-calls-free.rs
+++ b/src/test/compile-fail/borrowck/borrowck-bad-nested-calls-free.rs
diff --git a/src/test/compile-fail/borrowck-bad-nested-calls-move.rs b/src/test/compile-fail/borrowck/borrowck-bad-nested-calls-move.rs
index e24d4e87add..e24d4e87add 100644
--- a/src/test/compile-fail/borrowck-bad-nested-calls-move.rs
+++ b/src/test/compile-fail/borrowck/borrowck-bad-nested-calls-move.rs
diff --git a/src/test/compile-fail/borrowck-block-unint.rs b/src/test/compile-fail/borrowck/borrowck-block-unint.rs
index a09ee439245..a09ee439245 100644
--- a/src/test/compile-fail/borrowck-block-unint.rs
+++ b/src/test/compile-fail/borrowck/borrowck-block-unint.rs
diff --git a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs b/src/test/compile-fail/borrowck/borrowck-borrow-from-owned-ptr.rs
index e5091a92581..e5091a92581 100644
--- a/src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-from-owned-ptr.rs
diff --git a/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs b/src/test/compile-fail/borrowck/borrowck-borrow-from-stack-variable.rs
index 440be93dfdc..440be93dfdc 100644
--- a/src/test/compile-fail/borrowck-borrow-from-stack-variable.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-from-stack-variable.rs
diff --git a/src/test/compile-fail/borrowck-borrow-from-temporary.rs b/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs
index fbb3824cd40..fbb3824cd40 100644
--- a/src/test/compile-fail/borrowck-borrow-from-temporary.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs
diff --git a/src/test/compile-fail/borrowck-borrow-immut-deref-of-box-as-mut.rs b/src/test/compile-fail/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs
index 3662e23a412..3662e23a412 100644
--- a/src/test/compile-fail/borrowck-borrow-immut-deref-of-box-as-mut.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.rs
diff --git a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/compile-fail/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs
index d60751eddc7..d60751eddc7 100644
--- a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs
diff --git a/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs b/src/test/compile-fail/borrowck/borrowck-borrow-mut-object-twice.rs
index 7175194355b..7175194355b 100644
--- a/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-mut-object-twice.rs
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref-mut.rs
index 497b0e63edf..497b0e63edf 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref-mut.rs
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref.rs
index 693ed29bd05..693ed29bd05 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-auto-deref.rs
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-deref-mut.rs
index 34b926aab1f..34b926aab1f 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-deref-mut.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-deref-mut.rs
diff --git a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-deref.rs
index 5b916243b9e..5b916243b9e 100644
--- a/src/test/compile-fail/borrowck-borrow-overloaded-deref.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrow-overloaded-deref.rs
diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs b/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue-2.rs
index 309e286f48e..309e286f48e 100644
--- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue-2.rs
diff --git a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs b/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue.rs
index 8bbecfd48c6..8bbecfd48c6 100644
--- a/src/test/compile-fail/borrowck-borrowed-uniq-rvalue.rs
+++ b/src/test/compile-fail/borrowck/borrowck-borrowed-uniq-rvalue.rs
diff --git a/src/test/compile-fail/borrowck-box-insensitivity.rs b/src/test/compile-fail/borrowck/borrowck-box-insensitivity.rs
index c980e77df6f..c980e77df6f 100644
--- a/src/test/compile-fail/borrowck-box-insensitivity.rs
+++ b/src/test/compile-fail/borrowck/borrowck-box-insensitivity.rs
diff --git a/src/test/compile-fail/borrowck-break-uninit-2.rs b/src/test/compile-fail/borrowck/borrowck-break-uninit-2.rs
index 82a6c92abaf..82a6c92abaf 100644
--- a/src/test/compile-fail/borrowck-break-uninit-2.rs
+++ b/src/test/compile-fail/borrowck/borrowck-break-uninit-2.rs
diff --git a/src/test/compile-fail/borrowck-break-uninit.rs b/src/test/compile-fail/borrowck/borrowck-break-uninit.rs
index 8a6a036945b..8a6a036945b 100644
--- a/src/test/compile-fail/borrowck-break-uninit.rs
+++ b/src/test/compile-fail/borrowck/borrowck-break-uninit.rs
diff --git a/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs b/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
index 7626f354eb4..7626f354eb4 100644
--- a/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs
+++ b/src/test/compile-fail/borrowck/borrowck-call-is-borrow-issue-12224.rs
diff --git a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs b/src/test/compile-fail/borrowck/borrowck-call-method-from-mut-aliasable.rs
index bc0b667e895..bc0b667e895 100644
--- a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs
+++ b/src/test/compile-fail/borrowck/borrowck-call-method-from-mut-aliasable.rs
diff --git a/src/test/compile-fail/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs
index aaa07661215..aaa07661215 100644
--- a/src/test/compile-fail/borrowck-closures-mut-and-imm.rs
+++ b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs
diff --git a/src/test/compile-fail/borrowck-closures-mut-of-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-mut-of-imm.rs
index 40f9be2dd82..40f9be2dd82 100644
--- a/src/test/compile-fail/borrowck-closures-mut-of-imm.rs
+++ b/src/test/compile-fail/borrowck/borrowck-closures-mut-of-imm.rs
diff --git a/src/test/compile-fail/borrowck-closures-two-mut.rs b/src/test/compile-fail/borrowck/borrowck-closures-two-mut.rs
index 29546abe0bb..29546abe0bb 100644
--- a/src/test/compile-fail/borrowck-closures-two-mut.rs
+++ b/src/test/compile-fail/borrowck/borrowck-closures-two-mut.rs
diff --git a/src/test/compile-fail/borrowck-closures-unique-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-unique-imm.rs
index 247a4fe89a5..247a4fe89a5 100644
--- a/src/test/compile-fail/borrowck-closures-unique-imm.rs
+++ b/src/test/compile-fail/borrowck/borrowck-closures-unique-imm.rs
diff --git a/src/test/compile-fail/borrowck-closures-unique.rs b/src/test/compile-fail/borrowck/borrowck-closures-unique.rs
index 3646a68f06f..3646a68f06f 100644
--- a/src/test/compile-fail/borrowck-closures-unique.rs
+++ b/src/test/compile-fail/borrowck/borrowck-closures-unique.rs
diff --git a/src/test/compile-fail/borrowck-closures-use-after-free.rs b/src/test/compile-fail/borrowck/borrowck-closures-use-after-free.rs
index bb474342a7c..bb474342a7c 100644
--- a/src/test/compile-fail/borrowck-closures-use-after-free.rs
+++ b/src/test/compile-fail/borrowck/borrowck-closures-use-after-free.rs
diff --git a/src/test/compile-fail/borrowck-consume-unsize-vec.rs b/src/test/compile-fail/borrowck/borrowck-consume-unsize-vec.rs
index 32490e0dc7d..32490e0dc7d 100644
--- a/src/test/compile-fail/borrowck-consume-unsize-vec.rs
+++ b/src/test/compile-fail/borrowck/borrowck-consume-unsize-vec.rs
diff --git a/src/test/compile-fail/borrowck-consume-upcast-box.rs b/src/test/compile-fail/borrowck/borrowck-consume-upcast-box.rs
index 5bcafa675c7..5bcafa675c7 100644
--- a/src/test/compile-fail/borrowck-consume-upcast-box.rs
+++ b/src/test/compile-fail/borrowck/borrowck-consume-upcast-box.rs
diff --git a/src/test/compile-fail/borrowck-escaping-closure-error-1.rs b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-1.rs
index 87e40df7663..87e40df7663 100644
--- a/src/test/compile-fail/borrowck-escaping-closure-error-1.rs
+++ b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-1.rs
diff --git a/src/test/compile-fail/borrowck-escaping-closure-error-2.rs b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-2.rs
index 67700be890b..67700be890b 100644
--- a/src/test/compile-fail/borrowck-escaping-closure-error-2.rs
+++ b/src/test/compile-fail/borrowck/borrowck-escaping-closure-error-2.rs
diff --git a/src/test/compile-fail/borrowck-field-sensitivity.rs b/src/test/compile-fail/borrowck/borrowck-field-sensitivity.rs
index 13fd5fce955..13fd5fce955 100644
--- a/src/test/compile-fail/borrowck-field-sensitivity.rs
+++ b/src/test/compile-fail/borrowck/borrowck-field-sensitivity.rs
diff --git a/src/test/compile-fail/borrowck-fn-in-const-a.rs b/src/test/compile-fail/borrowck/borrowck-fn-in-const-a.rs
index 3098807f272..3098807f272 100644
--- a/src/test/compile-fail/borrowck-fn-in-const-a.rs
+++ b/src/test/compile-fail/borrowck/borrowck-fn-in-const-a.rs
diff --git a/src/test/compile-fail/borrowck-fn-in-const-b.rs b/src/test/compile-fail/borrowck/borrowck-fn-in-const-b.rs
index 7e29b2ee0fd..7e29b2ee0fd 100644
--- a/src/test/compile-fail/borrowck-fn-in-const-b.rs
+++ b/src/test/compile-fail/borrowck/borrowck-fn-in-const-b.rs
diff --git a/src/test/compile-fail/borrowck-fn-in-const-c.rs b/src/test/compile-fail/borrowck/borrowck-fn-in-const-c.rs
index e607397e920..e607397e920 100644
--- a/src/test/compile-fail/borrowck-fn-in-const-c.rs
+++ b/src/test/compile-fail/borrowck/borrowck-fn-in-const-c.rs
diff --git a/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs b/src/test/compile-fail/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs
index 31ec5aea7f3..31ec5aea7f3 100644
--- a/src/test/compile-fail/borrowck-for-loop-correct-cmt-for-pattern.rs
+++ b/src/test/compile-fail/borrowck/borrowck-for-loop-correct-cmt-for-pattern.rs
diff --git a/src/test/compile-fail/borrowck-for-loop-head-linkage.rs b/src/test/compile-fail/borrowck/borrowck-for-loop-head-linkage.rs
index b79fc5b2bf6..b79fc5b2bf6 100644
--- a/src/test/compile-fail/borrowck-for-loop-head-linkage.rs
+++ b/src/test/compile-fail/borrowck/borrowck-for-loop-head-linkage.rs
diff --git a/src/test/compile-fail/borrowck-if-no-else.rs b/src/test/compile-fail/borrowck/borrowck-if-no-else.rs
index 74b542800b9..74b542800b9 100644
--- a/src/test/compile-fail/borrowck-if-no-else.rs
+++ b/src/test/compile-fail/borrowck/borrowck-if-no-else.rs
diff --git a/src/test/compile-fail/borrowck-if-with-else.rs b/src/test/compile-fail/borrowck/borrowck-if-with-else.rs
index f3b02d12854..f3b02d12854 100644
--- a/src/test/compile-fail/borrowck-if-with-else.rs
+++ b/src/test/compile-fail/borrowck/borrowck-if-with-else.rs
diff --git a/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
index 8af10231921..8af10231921 100644
--- a/src/test/compile-fail/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
+++ b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs
diff --git a/src/test/compile-fail/borrowck-in-static.rs b/src/test/compile-fail/borrowck/borrowck-in-static.rs
index 16b0e8638de..16b0e8638de 100644
--- a/src/test/compile-fail/borrowck-in-static.rs
+++ b/src/test/compile-fail/borrowck/borrowck-in-static.rs
diff --git a/src/test/compile-fail/borrowck-init-in-called-fn-expr.rs b/src/test/compile-fail/borrowck/borrowck-init-in-called-fn-expr.rs
index 5b32fd2d198..5b32fd2d198 100644
--- a/src/test/compile-fail/borrowck-init-in-called-fn-expr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-init-in-called-fn-expr.rs
diff --git a/src/test/compile-fail/borrowck-init-in-fn-expr.rs b/src/test/compile-fail/borrowck/borrowck-init-in-fn-expr.rs
index 65f1a1fa098..65f1a1fa098 100644
--- a/src/test/compile-fail/borrowck-init-in-fn-expr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-init-in-fn-expr.rs
diff --git a/src/test/compile-fail/borrowck-init-in-fru.rs b/src/test/compile-fail/borrowck/borrowck-init-in-fru.rs
index 569ddb80c2f..569ddb80c2f 100644
--- a/src/test/compile-fail/borrowck-init-in-fru.rs
+++ b/src/test/compile-fail/borrowck/borrowck-init-in-fru.rs
diff --git a/src/test/compile-fail/borrowck-init-op-equal.rs b/src/test/compile-fail/borrowck/borrowck-init-op-equal.rs
index e0d93fd1d47..e0d93fd1d47 100644
--- a/src/test/compile-fail/borrowck-init-op-equal.rs
+++ b/src/test/compile-fail/borrowck/borrowck-init-op-equal.rs
diff --git a/src/test/compile-fail/borrowck-init-plus-equal.rs b/src/test/compile-fail/borrowck/borrowck-init-plus-equal.rs
index a036286f363..a036286f363 100644
--- a/src/test/compile-fail/borrowck-init-plus-equal.rs
+++ b/src/test/compile-fail/borrowck/borrowck-init-plus-equal.rs
diff --git a/src/test/compile-fail/borrowck-insert-during-each.rs b/src/test/compile-fail/borrowck/borrowck-insert-during-each.rs
index 2c634865983..2c634865983 100644
--- a/src/test/compile-fail/borrowck-insert-during-each.rs
+++ b/src/test/compile-fail/borrowck/borrowck-insert-during-each.rs
diff --git a/src/test/compile-fail/borrowck-issue-14498.rs b/src/test/compile-fail/borrowck/borrowck-issue-14498.rs
index 64033623fe2..64033623fe2 100644
--- a/src/test/compile-fail/borrowck-issue-14498.rs
+++ b/src/test/compile-fail/borrowck/borrowck-issue-14498.rs
diff --git a/src/test/compile-fail/borrowck-issue-2657-1.rs b/src/test/compile-fail/borrowck/borrowck-issue-2657-1.rs
index 0e1712137d3..0e1712137d3 100644
--- a/src/test/compile-fail/borrowck-issue-2657-1.rs
+++ b/src/test/compile-fail/borrowck/borrowck-issue-2657-1.rs
diff --git a/src/test/compile-fail/borrowck-issue-2657-2.rs b/src/test/compile-fail/borrowck/borrowck-issue-2657-2.rs
index a389a4a5593..a389a4a5593 100644
--- a/src/test/compile-fail/borrowck-issue-2657-2.rs
+++ b/src/test/compile-fail/borrowck/borrowck-issue-2657-2.rs
diff --git a/src/test/compile-fail/borrowck-lend-flow-if.rs b/src/test/compile-fail/borrowck/borrowck-lend-flow-if.rs
index a6ce36a5507..a6ce36a5507 100644
--- a/src/test/compile-fail/borrowck-lend-flow-if.rs
+++ b/src/test/compile-fail/borrowck/borrowck-lend-flow-if.rs
diff --git a/src/test/compile-fail/borrowck-lend-flow-loop.rs b/src/test/compile-fail/borrowck/borrowck-lend-flow-loop.rs
index f09e7ffd7e4..f09e7ffd7e4 100644
--- a/src/test/compile-fail/borrowck-lend-flow-loop.rs
+++ b/src/test/compile-fail/borrowck/borrowck-lend-flow-loop.rs
diff --git a/src/test/compile-fail/borrowck-lend-flow-match.rs b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs
index f24e82d11c5..f24e82d11c5 100644
--- a/src/test/compile-fail/borrowck-lend-flow-match.rs
+++ b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs
diff --git a/src/test/compile-fail/borrowck-lend-flow.rs b/src/test/compile-fail/borrowck/borrowck-lend-flow.rs
index 1ed779cfaac..1ed779cfaac 100644
--- a/src/test/compile-fail/borrowck-lend-flow.rs
+++ b/src/test/compile-fail/borrowck/borrowck-lend-flow.rs
diff --git a/src/test/compile-fail/borrowck-let-suggestion-suffixes.rs b/src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs
index f551a2aa811..f551a2aa811 100644
--- a/src/test/compile-fail/borrowck-let-suggestion-suffixes.rs
+++ b/src/test/compile-fail/borrowck/borrowck-let-suggestion-suffixes.rs
diff --git a/src/test/compile-fail/borrowck-let-suggestion.rs b/src/test/compile-fail/borrowck/borrowck-let-suggestion.rs
index d760f3db0c2..d760f3db0c2 100644
--- a/src/test/compile-fail/borrowck-let-suggestion.rs
+++ b/src/test/compile-fail/borrowck/borrowck-let-suggestion.rs
diff --git a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs b/src/test/compile-fail/borrowck/borrowck-loan-blocks-move-cc.rs
index 57b584a8959..57b584a8959 100644
--- a/src/test/compile-fail/borrowck-loan-blocks-move-cc.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-blocks-move-cc.rs
diff --git a/src/test/compile-fail/borrowck-loan-blocks-move.rs b/src/test/compile-fail/borrowck/borrowck-loan-blocks-move.rs
index f3f18807314..f3f18807314 100644
--- a/src/test/compile-fail/borrowck-loan-blocks-move.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-blocks-move.rs
diff --git a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs b/src/test/compile-fail/borrowck/borrowck-loan-blocks-mut-uniq.rs
index 32d8088549d..32d8088549d 100644
--- a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-blocks-mut-uniq.rs
diff --git a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs b/src/test/compile-fail/borrowck/borrowck-loan-in-overloaded-op.rs
index a9079cfc27d..a9079cfc27d 100644
--- a/src/test/compile-fail/borrowck-loan-in-overloaded-op.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-in-overloaded-op.rs
diff --git a/src/test/compile-fail/borrowck-loan-of-static-data-issue-27616.rs b/src/test/compile-fail/borrowck/borrowck-loan-of-static-data-issue-27616.rs
index 228e71025fd..228e71025fd 100644
--- a/src/test/compile-fail/borrowck-loan-of-static-data-issue-27616.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-of-static-data-issue-27616.rs
diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck/borrowck-loan-rcvr-overloaded-op.rs
index cce55b6c941..cce55b6c941 100644
--- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-rcvr-overloaded-op.rs
diff --git a/src/test/compile-fail/borrowck-loan-rcvr.rs b/src/test/compile-fail/borrowck/borrowck-loan-rcvr.rs
index 014b27f9659..014b27f9659 100644
--- a/src/test/compile-fail/borrowck-loan-rcvr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-rcvr.rs
diff --git a/src/test/compile-fail/borrowck-loan-vec-content.rs b/src/test/compile-fail/borrowck/borrowck-loan-vec-content.rs
index 21d9dea77b2..21d9dea77b2 100644
--- a/src/test/compile-fail/borrowck-loan-vec-content.rs
+++ b/src/test/compile-fail/borrowck/borrowck-loan-vec-content.rs
diff --git a/src/test/compile-fail/borrowck-match-binding-is-assignment.rs b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs
index c219b7c5424..c219b7c5424 100644
--- a/src/test/compile-fail/borrowck-match-binding-is-assignment.rs
+++ b/src/test/compile-fail/borrowck/borrowck-match-binding-is-assignment.rs
diff --git a/src/test/compile-fail/borrowck-move-by-capture.rs b/src/test/compile-fail/borrowck/borrowck-move-by-capture.rs
index bad52121043..bad52121043 100644
--- a/src/test/compile-fail/borrowck-move-by-capture.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-by-capture.rs
diff --git a/src/test/compile-fail/borrowck-move-error-with-note.rs b/src/test/compile-fail/borrowck/borrowck-move-error-with-note.rs
index e4b9fb26711..e4b9fb26711 100644
--- a/src/test/compile-fail/borrowck-move-error-with-note.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-error-with-note.rs
diff --git a/src/test/compile-fail/borrowck-move-from-subpath-of-borrowed-path.rs b/src/test/compile-fail/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs
index c02c6a71514..c02c6a71514 100644
--- a/src/test/compile-fail/borrowck-move-from-subpath-of-borrowed-path.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-from-subpath-of-borrowed-path.rs
diff --git a/src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs b/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs
index 7284fa7a850..7284fa7a850 100644
--- a/src/test/compile-fail/borrowck-move-from-unsafe-ptr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-from-unsafe-ptr.rs
diff --git a/src/test/compile-fail/borrowck-move-in-irrefut-pat.rs b/src/test/compile-fail/borrowck/borrowck-move-in-irrefut-pat.rs
index ec505faf885..ec505faf885 100644
--- a/src/test/compile-fail/borrowck-move-in-irrefut-pat.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-in-irrefut-pat.rs
diff --git a/src/test/compile-fail/borrowck-move-moved-value-into-closure.rs b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs
index c46bcbb32b9..c46bcbb32b9 100644
--- a/src/test/compile-fail/borrowck-move-moved-value-into-closure.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs
diff --git a/src/test/compile-fail/borrowck-move-mut-base-ptr.rs b/src/test/compile-fail/borrowck/borrowck-move-mut-base-ptr.rs
index 2fb89e6364b..2fb89e6364b 100644
--- a/src/test/compile-fail/borrowck-move-mut-base-ptr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-mut-base-ptr.rs
diff --git a/src/test/compile-fail/borrowck-move-out-of-overloaded-auto-deref.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs
index 27cef1f3c60..27cef1f3c60 100644
--- a/src/test/compile-fail/borrowck-move-out-of-overloaded-auto-deref.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-auto-deref.rs
diff --git a/src/test/compile-fail/borrowck-move-out-of-overloaded-deref.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-deref.rs
index fffcf575ab0..fffcf575ab0 100644
--- a/src/test/compile-fail/borrowck-move-out-of-overloaded-deref.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-overloaded-deref.rs
diff --git a/src/test/compile-fail/borrowck-move-out-of-static-item.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-static-item.rs
index 8b83b945fd1..8b83b945fd1 100644
--- a/src/test/compile-fail/borrowck-move-out-of-static-item.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-static-item.rs
diff --git a/src/test/compile-fail/borrowck-move-out-of-struct-with-dtor.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-struct-with-dtor.rs
index 3d13cbe30c5..3d13cbe30c5 100644
--- a/src/test/compile-fail/borrowck-move-out-of-struct-with-dtor.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-struct-with-dtor.rs
diff --git a/src/test/compile-fail/borrowck-move-out-of-tuple-struct-with-dtor.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
index 625f7184905..625f7184905 100644
--- a/src/test/compile-fail/borrowck-move-out-of-tuple-struct-with-dtor.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs
diff --git a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs b/src/test/compile-fail/borrowck/borrowck-move-out-of-vec-tail.rs
index d9a2f89a9e2..d9a2f89a9e2 100644
--- a/src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-out-of-vec-tail.rs
diff --git a/src/test/compile-fail/borrowck-move-subcomponent.rs b/src/test/compile-fail/borrowck/borrowck-move-subcomponent.rs
index 88871dda659..88871dda659 100644
--- a/src/test/compile-fail/borrowck-move-subcomponent.rs
+++ b/src/test/compile-fail/borrowck/borrowck-move-subcomponent.rs
diff --git a/src/test/compile-fail/borrowck-multiple-captures.rs b/src/test/compile-fail/borrowck/borrowck-multiple-captures.rs
index 042b914ce41..042b914ce41 100644
--- a/src/test/compile-fail/borrowck-multiple-captures.rs
+++ b/src/test/compile-fail/borrowck/borrowck-multiple-captures.rs
diff --git a/src/test/compile-fail/borrowck-mut-addr-of-imm-var.rs b/src/test/compile-fail/borrowck/borrowck-mut-addr-of-imm-var.rs
index b6626a835e4..b6626a835e4 100644
--- a/src/test/compile-fail/borrowck-mut-addr-of-imm-var.rs
+++ b/src/test/compile-fail/borrowck/borrowck-mut-addr-of-imm-var.rs
diff --git a/src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
index 38e0e27a7b9..38e0e27a7b9 100644
--- a/src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs
+++ b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs
diff --git a/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs b/src/test/compile-fail/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs
index bdeb7ea69bd..bdeb7ea69bd 100644
--- a/src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-mut-borrow-of-mut-base-ptr.rs
diff --git a/src/test/compile-fail/borrowck-mut-slice-of-imm-vec.rs b/src/test/compile-fail/borrowck/borrowck-mut-slice-of-imm-vec.rs
index 9341758afd8..9341758afd8 100644
--- a/src/test/compile-fail/borrowck-mut-slice-of-imm-vec.rs
+++ b/src/test/compile-fail/borrowck/borrowck-mut-slice-of-imm-vec.rs
diff --git a/src/test/compile-fail/borrowck-mutate-in-guard.rs b/src/test/compile-fail/borrowck/borrowck-mutate-in-guard.rs
index e35edca639e..e35edca639e 100644
--- a/src/test/compile-fail/borrowck-mutate-in-guard.rs
+++ b/src/test/compile-fail/borrowck/borrowck-mutate-in-guard.rs
diff --git a/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs b/src/test/compile-fail/borrowck/borrowck-no-cycle-in-exchange-heap.rs
index 8cb7423f3cb..8cb7423f3cb 100644
--- a/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs
+++ b/src/test/compile-fail/borrowck/borrowck-no-cycle-in-exchange-heap.rs
diff --git a/src/test/compile-fail/borrowck-object-lifetime.rs b/src/test/compile-fail/borrowck/borrowck-object-lifetime.rs
index 021b3f38e00..021b3f38e00 100644
--- a/src/test/compile-fail/borrowck-object-lifetime.rs
+++ b/src/test/compile-fail/borrowck/borrowck-object-lifetime.rs
diff --git a/src/test/compile-fail/borrowck-object-mutability.rs b/src/test/compile-fail/borrowck/borrowck-object-mutability.rs
index 1bdc32b0975..1bdc32b0975 100644
--- a/src/test/compile-fail/borrowck-object-mutability.rs
+++ b/src/test/compile-fail/borrowck/borrowck-object-mutability.rs
diff --git a/src/test/compile-fail/borrowck-or-init.rs b/src/test/compile-fail/borrowck/borrowck-or-init.rs
index 27871a6ab16..27871a6ab16 100644
--- a/src/test/compile-fail/borrowck-or-init.rs
+++ b/src/test/compile-fail/borrowck/borrowck-or-init.rs
diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-call.rs
index 93c37524bf5..93c37524bf5 100644
--- a/src/test/compile-fail/borrowck-overloaded-call.rs
+++ b/src/test/compile-fail/borrowck/borrowck-overloaded-call.rs
diff --git a/src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs
index bee56c9bf39..bee56c9bf39 100644
--- a/src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs
+++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-and-overloaded-deref.rs
diff --git a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-autoderef.rs
index b726c46d5d5..b726c46d5d5 100644
--- a/src/test/compile-fail/borrowck-overloaded-index-autoderef.rs
+++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-autoderef.rs
diff --git a/src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-move-from-vec.rs
index 1b62d9c326d..1b62d9c326d 100644
--- a/src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs
+++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-move-from-vec.rs
diff --git a/src/test/compile-fail/borrowck-overloaded-index-move-index.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-move-index.rs
index d8615d19053..d8615d19053 100644
--- a/src/test/compile-fail/borrowck-overloaded-index-move-index.rs
+++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-move-index.rs
diff --git a/src/test/compile-fail/borrowck-overloaded-index-ref-index.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs
index 4c50caf4976..4c50caf4976 100644
--- a/src/test/compile-fail/borrowck-overloaded-index-ref-index.rs
+++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs
diff --git a/src/test/compile-fail/borrowck-partial-reinit-1.rs b/src/test/compile-fail/borrowck/borrowck-partial-reinit-1.rs
index 1ee040a0705..1ee040a0705 100644
--- a/src/test/compile-fail/borrowck-partial-reinit-1.rs
+++ b/src/test/compile-fail/borrowck/borrowck-partial-reinit-1.rs
diff --git a/src/test/compile-fail/borrowck-partial-reinit-2.rs b/src/test/compile-fail/borrowck/borrowck-partial-reinit-2.rs
index c9cdeff9c7a..c9cdeff9c7a 100644
--- a/src/test/compile-fail/borrowck-partial-reinit-2.rs
+++ b/src/test/compile-fail/borrowck/borrowck-partial-reinit-2.rs
diff --git a/src/test/compile-fail/borrowck-partial-reinit-3.rs b/src/test/compile-fail/borrowck/borrowck-partial-reinit-3.rs
index 0aa73892b82..0aa73892b82 100644
--- a/src/test/compile-fail/borrowck-partial-reinit-3.rs
+++ b/src/test/compile-fail/borrowck/borrowck-partial-reinit-3.rs
diff --git a/src/test/compile-fail/borrowck-partial-reinit-4.rs b/src/test/compile-fail/borrowck/borrowck-partial-reinit-4.rs
index 774e04ecb29..774e04ecb29 100644
--- a/src/test/compile-fail/borrowck-partial-reinit-4.rs
+++ b/src/test/compile-fail/borrowck/borrowck-partial-reinit-4.rs
diff --git a/src/test/compile-fail/borrowck-pat-reassign-binding.rs b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs
index d176245823e..d176245823e 100644
--- a/src/test/compile-fail/borrowck-pat-reassign-binding.rs
+++ b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs
diff --git a/src/test/compile-fail/borrowck-reborrow-from-mut.rs b/src/test/compile-fail/borrowck/borrowck-reborrow-from-mut.rs
index 6f5dfa67be5..6f5dfa67be5 100644
--- a/src/test/compile-fail/borrowck-reborrow-from-mut.rs
+++ b/src/test/compile-fail/borrowck/borrowck-reborrow-from-mut.rs
diff --git a/src/test/compile-fail/borrowck-reborrow-from-shorter-lived-andmut.rs b/src/test/compile-fail/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs
index eee407472bf..eee407472bf 100644
--- a/src/test/compile-fail/borrowck-reborrow-from-shorter-lived-andmut.rs
+++ b/src/test/compile-fail/borrowck/borrowck-reborrow-from-shorter-lived-andmut.rs
diff --git a/src/test/compile-fail/borrowck-ref-into-rvalue.rs b/src/test/compile-fail/borrowck/borrowck-ref-into-rvalue.rs
index 726d4bcdf1d..726d4bcdf1d 100644
--- a/src/test/compile-fail/borrowck-ref-into-rvalue.rs
+++ b/src/test/compile-fail/borrowck/borrowck-ref-into-rvalue.rs
diff --git a/src/test/compile-fail/borrowck-ref-mut-of-imm.rs b/src/test/compile-fail/borrowck/borrowck-ref-mut-of-imm.rs
index 1784b72a699..1784b72a699 100644
--- a/src/test/compile-fail/borrowck-ref-mut-of-imm.rs
+++ b/src/test/compile-fail/borrowck/borrowck-ref-mut-of-imm.rs
diff --git a/src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs b/src/test/compile-fail/borrowck/borrowck-report-with-custom-diagnostic.rs
index 61bf2c11a1f..61bf2c11a1f 100644
--- a/src/test/compile-fail/borrowck-report-with-custom-diagnostic.rs
+++ b/src/test/compile-fail/borrowck/borrowck-report-with-custom-diagnostic.rs
diff --git a/src/test/compile-fail/borrowck-return-variable-on-stack-via-clone.rs b/src/test/compile-fail/borrowck/borrowck-return-variable-on-stack-via-clone.rs
index 7529943f0bc..7529943f0bc 100644
--- a/src/test/compile-fail/borrowck-return-variable-on-stack-via-clone.rs
+++ b/src/test/compile-fail/borrowck/borrowck-return-variable-on-stack-via-clone.rs
diff --git a/src/test/compile-fail/borrowck-return.rs b/src/test/compile-fail/borrowck/borrowck-return.rs
index 74d435b35e7..74d435b35e7 100644
--- a/src/test/compile-fail/borrowck-return.rs
+++ b/src/test/compile-fail/borrowck/borrowck-return.rs
diff --git a/src/test/compile-fail/borrowck-struct-update-with-dtor.rs b/src/test/compile-fail/borrowck/borrowck-struct-update-with-dtor.rs
index bf1497420e2..bf1497420e2 100644
--- a/src/test/compile-fail/borrowck-struct-update-with-dtor.rs
+++ b/src/test/compile-fail/borrowck/borrowck-struct-update-with-dtor.rs
diff --git a/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs b/src/test/compile-fail/borrowck/borrowck-swap-mut-base-ptr.rs
index 552fcec8e28..552fcec8e28 100644
--- a/src/test/compile-fail/borrowck-swap-mut-base-ptr.rs
+++ b/src/test/compile-fail/borrowck/borrowck-swap-mut-base-ptr.rs
diff --git a/src/test/compile-fail/borrowck-unary-move.rs b/src/test/compile-fail/borrowck/borrowck-unary-move.rs
index 5b5c5f4da91..5b5c5f4da91 100644
--- a/src/test/compile-fail/borrowck-unary-move.rs
+++ b/src/test/compile-fail/borrowck/borrowck-unary-move.rs
diff --git a/src/test/compile-fail/borrowck-unboxed-closures.rs b/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
index 1c12ca9c1de..1c12ca9c1de 100644
--- a/src/test/compile-fail/borrowck-unboxed-closures.rs
+++ b/src/test/compile-fail/borrowck/borrowck-unboxed-closures.rs
diff --git a/src/test/compile-fail/borrowck-uninit-after-item.rs b/src/test/compile-fail/borrowck/borrowck-uninit-after-item.rs
index acd827d6c62..acd827d6c62 100644
--- a/src/test/compile-fail/borrowck-uninit-after-item.rs
+++ b/src/test/compile-fail/borrowck/borrowck-uninit-after-item.rs
diff --git a/src/test/compile-fail/borrowck-uninit-in-assignop.rs b/src/test/compile-fail/borrowck/borrowck-uninit-in-assignop.rs
index e253ecc74b9..e253ecc74b9 100644
--- a/src/test/compile-fail/borrowck-uninit-in-assignop.rs
+++ b/src/test/compile-fail/borrowck/borrowck-uninit-in-assignop.rs
diff --git a/src/test/compile-fail/borrowck-uninit.rs b/src/test/compile-fail/borrowck/borrowck-uninit.rs
index f4b73bc889f..f4b73bc889f 100644
--- a/src/test/compile-fail/borrowck-uninit.rs
+++ b/src/test/compile-fail/borrowck/borrowck-uninit.rs
diff --git a/src/test/compile-fail/borrowck-uniq-via-lend.rs b/src/test/compile-fail/borrowck/borrowck-uniq-via-lend.rs
index f36dc0ca43f..f36dc0ca43f 100644
--- a/src/test/compile-fail/borrowck-uniq-via-lend.rs
+++ b/src/test/compile-fail/borrowck/borrowck-uniq-via-lend.rs
diff --git a/src/test/compile-fail/borrowck-use-in-index-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-use-in-index-lvalue.rs
index 7291bcd2ce1..7291bcd2ce1 100644
--- a/src/test/compile-fail/borrowck-use-in-index-lvalue.rs
+++ b/src/test/compile-fail/borrowck/borrowck-use-in-index-lvalue.rs
diff --git a/src/test/compile-fail/borrowck-use-mut-borrow.rs b/src/test/compile-fail/borrowck/borrowck-use-mut-borrow.rs
index c11e58651aa..c11e58651aa 100644
--- a/src/test/compile-fail/borrowck-use-mut-borrow.rs
+++ b/src/test/compile-fail/borrowck/borrowck-use-mut-borrow.rs
diff --git a/src/test/compile-fail/borrowck-use-uninitialized-in-cast-trait.rs b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast-trait.rs
index 796b455f5c7..796b455f5c7 100644
--- a/src/test/compile-fail/borrowck-use-uninitialized-in-cast-trait.rs
+++ b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast-trait.rs
diff --git a/src/test/compile-fail/borrowck-use-uninitialized-in-cast.rs b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs
index a3d5af80b53..a3d5af80b53 100644
--- a/src/test/compile-fail/borrowck-use-uninitialized-in-cast.rs
+++ b/src/test/compile-fail/borrowck/borrowck-use-uninitialized-in-cast.rs
diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs
index 98052ad31a7..98052ad31a7 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
+++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-element-loan.rs
diff --git a/src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-loan-from-mut.rs
index db635893c81..db635893c81 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs
+++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-loan-from-mut.rs
diff --git a/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
index 97dcaeb0bf1..97dcaeb0bf1 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-move-tail.rs
+++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-move-tail.rs
diff --git a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-nesting.rs
index a69ce0cb365..a69ce0cb365 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
+++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-nesting.rs
diff --git a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs b/src/test/compile-fail/borrowck/borrowck-vec-pattern-tail-element-loan.rs
index 82b3490d7d7..82b3490d7d7 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
+++ b/src/test/compile-fail/borrowck/borrowck-vec-pattern-tail-element-loan.rs
diff --git a/src/test/compile-fail/borrowck-while-break.rs b/src/test/compile-fail/borrowck/borrowck-while-break.rs
index 8cdf1da5c93..8cdf1da5c93 100644
--- a/src/test/compile-fail/borrowck-while-break.rs
+++ b/src/test/compile-fail/borrowck/borrowck-while-break.rs
diff --git a/src/test/compile-fail/borrowck-while-cond.rs b/src/test/compile-fail/borrowck/borrowck-while-cond.rs
index 27d42d666ea..27d42d666ea 100644
--- a/src/test/compile-fail/borrowck-while-cond.rs
+++ b/src/test/compile-fail/borrowck/borrowck-while-cond.rs
diff --git a/src/test/compile-fail/borrowck-while.rs b/src/test/compile-fail/borrowck/borrowck-while.rs
index e3566e9bb92..e3566e9bb92 100644
--- a/src/test/compile-fail/borrowck-while.rs
+++ b/src/test/compile-fail/borrowck/borrowck-while.rs
diff --git a/src/test/compile-fail/cfg-arg-invalid.rs b/src/test/compile-fail/cfg-arg-invalid.rs
new file mode 100644
index 00000000000..404630399c6
--- /dev/null
+++ b/src/test/compile-fail/cfg-arg-invalid.rs
@@ -0,0 +1,13 @@
+// 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: --cfg a{b}
+// error-pattern: invalid --cfg argument: a{b}
+fn main() {}
diff --git a/src/test/compile-fail/dep-graph-struct-signature.rs b/src/test/compile-fail/dep-graph-struct-signature.rs
index 5cfb748b6f4..c16998cd33c 100644
--- a/src/test/compile-fail/dep-graph-struct-signature.rs
+++ b/src/test/compile-fail/dep-graph-struct-signature.rs
@@ -74,23 +74,17 @@ mod signatures {
     fn indirect(x: WillChanges) { }
 }
 
-// these are invalid dependencies, though sometimes we create edges
-// anyway.
 mod invalid_signatures {
     use WontChange;
 
-    // FIXME due to the variance pass having overly conservative edges,
-    // we incorrectly think changes are needed here
-    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
-    #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK
+    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path
+    #[rustc_then_this_would_need(CollectItem)] //~ ERROR no path
     trait A {
         fn do_something_else_twice(x: WontChange);
     }
 
-    // FIXME due to the variance pass having overly conservative edges,
-    // we incorrectly think changes are needed here
-    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR OK
-    #[rustc_then_this_would_need(CollectItem)] //~ ERROR OK
+    #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path
+    #[rustc_then_this_would_need(CollectItem)] //~ ERROR no path
     fn b(x: WontChange) { }
 
     #[rustc_then_this_would_need(ItemSignature)] //~ ERROR no path from `WillChange`
diff --git a/src/test/compile-fail/duplicate_entry_error.rs b/src/test/compile-fail/duplicate_entry_error.rs
new file mode 100644
index 00000000000..d39553a7267
--- /dev/null
+++ b/src/test/compile-fail/duplicate_entry_error.rs
@@ -0,0 +1,22 @@
+// 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.
+
+// Test for issue #31788
+
+// error-pattern: duplicate entry for `panic_fmt`, first definition found in `std`
+
+#![feature(lang_items)]
+
+#[lang = "panic_fmt"]
+fn panic_fmt() -> ! {
+    loop {}
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/compile-fail/empty-struct-braces-expr.rs b/src/test/compile-fail/empty-struct-braces-expr.rs
index 61e4a1ea397..1c86af30c79 100644
--- a/src/test/compile-fail/empty-struct-braces-expr.rs
+++ b/src/test/compile-fail/empty-struct-braces-expr.rs
@@ -12,8 +12,6 @@
 
 // aux-build:empty-struct.rs
 
-#![feature(braced_empty_structs)]
-
 extern crate empty_struct;
 use empty_struct::*;
 
diff --git a/src/test/compile-fail/empty-struct-braces-pat-1.rs b/src/test/compile-fail/empty-struct-braces-pat-1.rs
index 4dd256c68bf..a5c740d9f63 100644
--- a/src/test/compile-fail/empty-struct-braces-pat-1.rs
+++ b/src/test/compile-fail/empty-struct-braces-pat-1.rs
@@ -12,8 +12,6 @@
 
 // aux-build:empty-struct.rs
 
-#![feature(braced_empty_structs)]
-
 extern crate empty_struct;
 use empty_struct::*;
 
diff --git a/src/test/compile-fail/empty-struct-braces-pat-2.rs b/src/test/compile-fail/empty-struct-braces-pat-2.rs
index ac6fbc7e06d..0bd96d82095 100644
--- a/src/test/compile-fail/empty-struct-braces-pat-2.rs
+++ b/src/test/compile-fail/empty-struct-braces-pat-2.rs
@@ -12,8 +12,6 @@
 
 // aux-build:empty-struct.rs
 
-#![feature(braced_empty_structs)]
-
 extern crate empty_struct;
 use empty_struct::*;
 
diff --git a/src/test/compile-fail/empty-struct-braces-pat-3.rs b/src/test/compile-fail/empty-struct-braces-pat-3.rs
index c973049184f..88249fc422f 100644
--- a/src/test/compile-fail/empty-struct-braces-pat-3.rs
+++ b/src/test/compile-fail/empty-struct-braces-pat-3.rs
@@ -12,8 +12,6 @@
 
 // aux-build:empty-struct.rs
 
-#![feature(braced_empty_structs)]
-
 extern crate empty_struct;
 use empty_struct::*;
 
diff --git a/src/test/compile-fail/empty-struct-unit-expr.rs b/src/test/compile-fail/empty-struct-unit-expr.rs
index 822ee9e0dbc..350b96c764c 100644
--- a/src/test/compile-fail/empty-struct-unit-expr.rs
+++ b/src/test/compile-fail/empty-struct-unit-expr.rs
@@ -12,8 +12,6 @@
 
 // aux-build:empty-struct.rs
 
-#![feature(braced_empty_structs)]
-
 extern crate empty_struct;
 use empty_struct::*;
 
diff --git a/src/test/compile-fail/empty-struct-unit-pat.rs b/src/test/compile-fail/empty-struct-unit-pat.rs
index 0f54d1b7365..a75290c9405 100644
--- a/src/test/compile-fail/empty-struct-unit-pat.rs
+++ b/src/test/compile-fail/empty-struct-unit-pat.rs
@@ -12,10 +12,6 @@
 
 // aux-build:empty-struct.rs
 
-#![feature(rustc_attrs)]
-// remove prior feature after warning cycle and promoting warnings to errors
-#![feature(braced_empty_structs)]
-
 extern crate empty_struct;
 use empty_struct::*;
 
@@ -26,8 +22,7 @@ enum E {
 }
 
 // remove attribute after warning cycle and promoting warnings to errors
-#[rustc_error]
-fn main() { //~ ERROR: compilation successful
+fn main() {
     let e2 = Empty2;
     let e4 = E::Empty4;
     let xe2 = XEmpty2;
@@ -41,12 +36,12 @@ fn main() { //~ ERROR: compilation successful
     //     XEmpty2() => () // ERROR `XEmpty2` does not name a tuple variant or a tuple struct
     // }
     match e2 {
-        Empty2(..) => () //~ WARN `Empty2` does not name a tuple variant or a tuple struct
-            //~^ WARN hard error
+        Empty2(..) => () //~ ERROR `Empty2` does not name a tuple variant or a tuple struct
+            //~^ ERROR hard error
     }
     match xe2 {
-        XEmpty2(..) => () //~ WARN `XEmpty2` does not name a tuple variant or a tuple struct
-            //~^ WARN hard error
+        XEmpty2(..) => () //~ ERROR `XEmpty2` does not name a tuple variant or a tuple struct
+            //~^ ERROR hard error
     }
     // Rejected by parser as yet
     // match e4 {
@@ -57,12 +52,12 @@ fn main() { //~ ERROR: compilation successful
     //     _ => {},
     // }
     match e4 {
-        E::Empty4(..) => () //~ WARN `E::Empty4` does not name a tuple variant or a tuple struct
-            //~^ WARN hard error
+        E::Empty4(..) => () //~ ERROR `E::Empty4` does not name a tuple variant or a tuple struct
+            //~^ ERROR hard error
     }
     match xe4 {
-        XE::XEmpty4(..) => (), //~ WARN `XE::XEmpty4` does not name a tuple variant or a tuple
-            //~^ WARN hard error
+        XE::XEmpty4(..) => (), //~ ERROR `XE::XEmpty4` does not name a tuple variant or a tuple
+            //~^ ERROR hard error
         _ => {},
     }
 }
diff --git a/src/test/compile-fail/extern-crate-visibility.rs b/src/test/compile-fail/extern-crate-visibility.rs
new file mode 100644
index 00000000000..56a41a15ab3
--- /dev/null
+++ b/src/test/compile-fail/extern-crate-visibility.rs
@@ -0,0 +1,34 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+mod foo {
+    extern crate core;
+}
+
+// Check that private crates can be used from outside their modules, albeit with warnings
+use foo::core; //~ WARN extern crate `core` is private
+//~^ WARN this was previously accepted by the compiler but is being phased out
+use foo::core::cell; //~ WARN extern crate `core` is private
+//~^ WARN this was previously accepted by the compiler but is being phased out
+
+fn f() {
+    foo::core::cell::Cell::new(0); //~ WARN extern crate `core` is private
+    //~^ WARN this was previously accepted by the compiler but is being phased out
+
+    use foo::*;
+    mod core {} // Check that private crates are not glob imported
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/extern-with-type-bounds.rs b/src/test/compile-fail/extern-with-type-bounds.rs
index 2553bdcbb27..d8bdd5974c7 100644
--- a/src/test/compile-fail/extern-with-type-bounds.rs
+++ b/src/test/compile-fail/extern-with-type-bounds.rs
@@ -24,7 +24,7 @@ extern "rust-intrinsic" {
 
     // Unresolved bounds should still error.
     fn align_of<T: NoSuchTrait>() -> usize;
-    //~^ ERROR use of undeclared trait name `NoSuchTrait`
+    //~^ ERROR trait `NoSuchTrait` is not in scope
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/glob-resolve1.rs b/src/test/compile-fail/glob-resolve1.rs
index 181503db818..1e5662aa172 100644
--- a/src/test/compile-fail/glob-resolve1.rs
+++ b/src/test/compile-fail/glob-resolve1.rs
@@ -35,7 +35,7 @@ fn main() {
     C; //~ ERROR: unresolved
     import(); //~ ERROR: unresolved
 
-    foo::<A>(); //~ ERROR: undeclared
-    foo::<C>(); //~ ERROR: undeclared
-    foo::<D>(); //~ ERROR: undeclared
+    foo::<A>(); //~ ERROR: not in scope
+    foo::<C>(); //~ ERROR: not in scope
+    foo::<D>(); //~ ERROR: not in scope
 }
diff --git a/src/test/compile-fail/import-shadow-6.rs b/src/test/compile-fail/import-shadow-6.rs
index 0f3d54d5fe3..fa3b75c70f0 100644
--- a/src/test/compile-fail/import-shadow-6.rs
+++ b/src/test/compile-fail/import-shadow-6.rs
@@ -12,8 +12,8 @@
 
 #![no_implicit_prelude]
 
-use qux::*; //~ERROR a type named `Baz` has already been imported in this module
-use foo::*;
+use qux::*;
+use foo::*; //~ERROR a type named `Baz` has already been imported in this module
 
 mod foo {
     pub type Baz = isize;
diff --git a/src/test/compile-fail/import.rs b/src/test/compile-fail/import.rs
index 86c4ce8b038..ff93cd0f066 100644
--- a/src/test/compile-fail/import.rs
+++ b/src/test/compile-fail/import.rs
@@ -15,5 +15,10 @@ use zed::baz;
 
 mod zed {
     pub fn bar() { println!("bar"); }
+    use foo; //~ ERROR unresolved import
+}
+
+fn main() {
+    zed::foo(); //~ ERROR unresolved name
+    bar();
 }
-fn main() { bar(); }
diff --git a/src/test/compile-fail/inner-static-type-parameter.rs b/src/test/compile-fail/inner-static-type-parameter.rs
index 56b681378cc..6fcda66486b 100644
--- a/src/test/compile-fail/inner-static-type-parameter.rs
+++ b/src/test/compile-fail/inner-static-type-parameter.rs
@@ -15,7 +15,7 @@ enum Bar<T> { What } //~ ERROR parameter `T` is never used
 fn foo<T>() {
     static a: Bar<T> = Bar::What;
     //~^ ERROR cannot use an outer type parameter in this context
-    //~| ERROR use of undeclared type name `T`
+    //~| ERROR type name `T` is undefined or not in scope
 }
 
 fn main() {
diff --git a/src/test/compile-fail/issue-18058.rs b/src/test/compile-fail/issue-18058.rs
index bbb540200b4..0447cf781ff 100644
--- a/src/test/compile-fail/issue-18058.rs
+++ b/src/test/compile-fail/issue-18058.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 impl Undefined {}
-//~^ ERROR use of undeclared type name `Undefined`
+//~^ ERROR type name `Undefined` is undefined or not in scope
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-18119.rs b/src/test/compile-fail/issue-18119.rs
index 1270b094534..f06496463e4 100644
--- a/src/test/compile-fail/issue-18119.rs
+++ b/src/test/compile-fail/issue-18119.rs
@@ -13,10 +13,10 @@ static Y: u8 = 1;
 fn foo() {}
 
 impl X {}
-//~^ ERROR use of undeclared type name `X`
+//~^ ERROR type name `X` is undefined or not in scope
 impl Y {}
-//~^ ERROR use of undeclared type name `Y`
+//~^ ERROR type name `Y` is undefined or not in scope
 impl foo {}
-//~^ ERROR use of undeclared type name `foo`
+//~^ ERROR type name `foo` is undefined or not in scope
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-19883.rs b/src/test/compile-fail/issue-19883.rs
index 7ec3093a6e0..3a7a1692f38 100644
--- a/src/test/compile-fail/issue-19883.rs
+++ b/src/test/compile-fail/issue-19883.rs
@@ -17,7 +17,7 @@ trait From<Src> {
 trait To: Sized {
     fn to<Dst: From<Self>>(self) ->
         <Dst as From<Self>>::Dst
-        //~^ ERROR use of undeclared associated type `From::Dst`
+        //~^ ERROR associated type `From::Dst` is undefined or not in scope
     {
         From::from(self)
     }
diff --git a/src/test/compile-fail/issue-21221-1.rs b/src/test/compile-fail/issue-21221-1.rs
new file mode 100644
index 00000000000..03dd7b6754a
--- /dev/null
+++ b/src/test/compile-fail/issue-21221-1.rs
@@ -0,0 +1,94 @@
+// 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.
+
+mod mul1 {
+    pub trait Mul {}
+}
+
+mod mul2 {
+    pub trait Mul {}
+}
+
+mod mul3 {
+    enum Mul {
+      Yes,
+      No
+    }
+}
+
+mod mul4 {
+    type Mul = String;
+}
+
+mod mul5 {
+    struct Mul{
+        left_term: u32,
+        right_term: u32
+    }
+}
+
+#[derive(Debug)]
+struct Foo;
+
+// When we comment the next line:
+//use mul1::Mul;
+
+// BEFORE, we got the following error for the `impl` below:
+//   error: use of undeclared trait name `Mul` [E0405]
+// AFTER, we get this message:
+//   error: trait `Mul` is not in scope.
+//   help: ...
+//   help: you can import several candidates into scope (`use ...;`):
+//   help:   `mul1::Mul`
+//   help:   `mul2::Mul`
+//   help:   `std::ops::Mul`
+
+impl Mul for Foo {
+//~^ ERROR trait `Mul` is not in scope
+//~| HELP `mul1::Mul`
+//~| HELP `mul2::Mul`
+//~| HELP `std::ops::Mul`
+}
+
+// BEFORE, we got:
+//   error: use of undeclared type name `Mul` [E0412]
+// AFTER, we get:
+//   error: type name `Mul` is not in scope. Maybe you meant:
+//   help: ...
+//   help: you can import several candidates into scope (`use ...;`):
+//   help:   `mul1::Mul`
+//   help:   `mul2::Mul`
+//   help:   `mul3::Mul`
+//   help:   `mul4::Mul`
+//   help:   and 2 other candidates
+fn getMul() -> Mul {
+//~^ ERROR type name `Mul` is undefined or not in scope
+//~| HELP `mul1::Mul`
+//~| HELP `mul2::Mul`
+//~| HELP `mul3::Mul`
+//~| HELP `mul4::Mul`
+//~| HELP and 2 other candidates
+}
+
+// Let's also test what happens if the trait doesn't exist:
+impl ThisTraitReallyDoesntExistInAnyModuleReally for Foo {
+//~^ ERROR trait `ThisTraitReallyDoesntExistInAnyModuleReally` is not in scope
+}
+
+// Let's also test what happens if there's just one alternative:
+impl Div for Foo {
+//~^ ERROR trait `Div` is not in scope
+//~| HELP `use std::ops::Div;`
+}
+
+fn main() {
+    let foo = Foo();
+    println!("Hello, {:?}!", foo);
+}
diff --git a/src/test/compile-fail/issue-21221-2.rs b/src/test/compile-fail/issue-21221-2.rs
new file mode 100644
index 00000000000..4145d20dea5
--- /dev/null
+++ b/src/test/compile-fail/issue-21221-2.rs
@@ -0,0 +1,30 @@
+// 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 mod foo {
+    pub mod bar {
+        // note: trait T is not public, but being in the current
+        // crate, it's fine to show it, since the programmer can
+        // decide to make it public based on the suggestion ...
+        trait T {}
+    }
+    // imports should be ignored:
+    use self::bar::T;
+}
+
+pub mod baz {
+    pub use foo;
+    pub use std::ops::{Mul as T};
+}
+
+struct Foo;
+impl T for Foo { }
+//~^ ERROR trait `T` is not in scope
+//~| HELP you can to import it into scope: `use foo::bar::T;`.
diff --git a/src/test/compile-fail/issue-21221-3.rs b/src/test/compile-fail/issue-21221-3.rs
new file mode 100644
index 00000000000..ba66496b930
--- /dev/null
+++ b/src/test/compile-fail/issue-21221-3.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+// aux-build:issue-21221-3.rs
+
+extern crate issue_21221_3;
+
+struct Foo;
+
+// NOTE: This shows only traits accessible from the current
+// crate, thus the two private entities:
+//   `issue_21221_3::outer::private_module::OuterTrait` and
+//   `issue_21221_3::outer::public_module::OuterTrait`
+// are hidden from the view.
+impl OuterTrait for Foo {}
+//~^ ERROR trait `OuterTrait` is not in scope
+//~| HELP you can to import it into scope: `use issue_21221_3::outer::OuterTrait;`.
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/compile-fail/issue-21221-4.rs b/src/test/compile-fail/issue-21221-4.rs
new file mode 100644
index 00000000000..8d09510ae09
--- /dev/null
+++ b/src/test/compile-fail/issue-21221-4.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// testing whether the lookup mechanism picks up types
+// defined in the outside crate
+
+// aux-build:issue-21221-4.rs
+
+extern crate issue_21221_4;
+
+struct Foo;
+
+impl T for Foo {}
+//~^ ERROR trait `T` is not in scope
+//~| HELP you can to import it into scope: `use issue_21221_4::T;`.
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/compile-fail/issue-22037.rs b/src/test/compile-fail/issue-22037.rs
index 3c8e7a2be0c..74f1be95420 100644
--- a/src/test/compile-fail/issue-22037.rs
+++ b/src/test/compile-fail/issue-22037.rs
@@ -11,7 +11,7 @@
 trait A {
     type Output;
     fn a(&self) -> <Self as A>::X;
-//~^ ERROR: use of undeclared associated type `A::X`
+//~^ ERROR: associated type `A::X` is undefined or not in scope
 }
 
 impl A for u32 {
diff --git a/src/test/compile-fail/issue-22384.rs b/src/test/compile-fail/issue-22384.rs
index 368e2483533..46a43bdfcb8 100644
--- a/src/test/compile-fail/issue-22384.rs
+++ b/src/test/compile-fail/issue-22384.rs
@@ -14,5 +14,5 @@ trait Trait {
 
 fn main() {
     <<i32 as Copy>::foobar as Trait>::foo();
-    //~^ ERROR use of undeclared associated type `Copy::foobar`
+    //~^ ERROR associated type `Copy::foobar` is undefined or not in scope
 }
diff --git a/src/test/compile-fail/issue-27831.rs b/src/test/compile-fail/issue-27831.rs
index ff2846dc705..d014c45ad2d 100644
--- a/src/test/compile-fail/issue-27831.rs
+++ b/src/test/compile-fail/issue-27831.rs
@@ -22,11 +22,11 @@ fn main() {
     let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
 
     let x = Bar;
-    Bar { ..x }; //~ ERROR empty structs and enum variants with braces are unstable
-    let Bar { .. } = x; //~ ERROR empty structs and enum variants with braces are unstable
+    Bar { ..x };
+    let Bar { .. } = x;
 
     match Enum::Bar {
-        Enum::Bar { .. } //~ ERROR empty structs and enum variants with braces are unstable
+        Enum::Bar { .. }
            => {}
         Enum::Foo { .. } //~ ERROR `Enum::Foo` does not name a struct
            => {}
diff --git a/src/test/compile-fail/issue-3021-c.rs b/src/test/compile-fail/issue-3021-c.rs
index 5b3e343deea..03473bd44cc 100644
--- a/src/test/compile-fail/issue-3021-c.rs
+++ b/src/test/compile-fail/issue-3021-c.rs
@@ -13,8 +13,8 @@ fn siphash<T>() {
     trait t {
         fn g(&self, x: T) -> T;  //~ ERROR can't use type parameters from outer function; try using
         //~^ ERROR can't use type parameters from outer function; try using
-        //~^^ ERROR use of undeclared type name `T`
-        //~^^^ ERROR use of undeclared type name `T`
+        //~^^ ERROR type name `T` is undefined or not in scope
+        //~^^^ ERROR type name `T` is undefined or not in scope
     }
 }
 
diff --git a/src/test/compile-fail/issue-31769.rs b/src/test/compile-fail/issue-31769.rs
new file mode 100644
index 00000000000..4b5df7ea53c
--- /dev/null
+++ b/src/test/compile-fail/issue-31769.rs
@@ -0,0 +1,14 @@
+// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    #[inline] struct Foo;  //~ ERROR attribute should be applied to function
+    #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct or enum
+}
diff --git a/src/test/compile-fail/issue-31845.rs b/src/test/compile-fail/issue-31845.rs
new file mode 100644
index 00000000000..344a1117254
--- /dev/null
+++ b/src/test/compile-fail/issue-31845.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks lexical scopes cannot see through normal module boundries
+
+fn f() {
+    fn g() {}
+    mod foo {
+        fn h() {
+           g(); //~ ERROR unresolved name
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-3214.rs b/src/test/compile-fail/issue-3214.rs
index 27b7fb75275..4f955df8205 100644
--- a/src/test/compile-fail/issue-3214.rs
+++ b/src/test/compile-fail/issue-3214.rs
@@ -11,7 +11,7 @@
 fn foo<T>() {
     struct foo {
         x: T, //~ ERROR can't use type parameters from outer function;
-        //~^ ERROR use of undeclared type name
+        //~^ ERROR type name `T` is undefined or not in scope
     }
 
     impl<T> Drop for foo<T> {
diff --git a/src/test/compile-fail/issue-4366-2.rs b/src/test/compile-fail/issue-4366-2.rs
index e8dfac45447..a6fe719509c 100644
--- a/src/test/compile-fail/issue-4366-2.rs
+++ b/src/test/compile-fail/issue-4366-2.rs
@@ -23,7 +23,7 @@ mod a {
     pub mod sub {
         use a::b::*;
         fn sub() -> bar { 1 }
-        //~^ ERROR: undeclared type name
+        //~^ ERROR: type name `bar` is undefined or not in scope
     }
 }
 
diff --git a/src/test/compile-fail/issue-5997-enum.rs b/src/test/compile-fail/issue-5997-enum.rs
index ad485f2d330..20d239c6ae0 100644
--- a/src/test/compile-fail/issue-5997-enum.rs
+++ b/src/test/compile-fail/issue-5997-enum.rs
@@ -11,7 +11,7 @@
 fn f<Z>() -> bool {
     enum E { V(Z) }
     //~^ ERROR can't use type parameters from outer function
-    //~^^ ERROR use of undeclared type name `Z`
+    //~^^ ERROR type name `Z` is undefined or not in scope
     true
 }
 
diff --git a/src/test/compile-fail/issue-5997-struct.rs b/src/test/compile-fail/issue-5997-struct.rs
index 587c7c63f4c..40be2f04cb4 100644
--- a/src/test/compile-fail/issue-5997-struct.rs
+++ b/src/test/compile-fail/issue-5997-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn f<T>() -> bool {
-    struct S(T); //~ ERROR use of undeclared type name `T`
+    struct S(T); //~ ERROR type name `T` is undefined or not in scope
     //~^ ERROR can't use type parameters from outer function; try using
 
     true
diff --git a/src/test/compile-fail/issue-7607-1.rs b/src/test/compile-fail/issue-7607-1.rs
index 40c3d96bc9a..96ac2de1762 100644
--- a/src/test/compile-fail/issue-7607-1.rs
+++ b/src/test/compile-fail/issue-7607-1.rs
@@ -12,7 +12,7 @@ struct Foo {
     x: isize
 }
 
-impl Fo { //~ ERROR use of undeclared type name `Fo`
+impl Fo { //~ ERROR type name `Fo` is undefined or not in scope
     fn foo() {}
 }
 
diff --git a/src/test/compile-fail/issue-8767.rs b/src/test/compile-fail/issue-8767.rs
index 96c8ec45058..1c97c0c886d 100644
--- a/src/test/compile-fail/issue-8767.rs
+++ b/src/test/compile-fail/issue-8767.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-impl B { //~ ERROR use of undeclared type name `B`
+impl B { //~ ERROR type name `B` is undefined or not in scope
 }
 
 fn main() {
diff --git a/src/test/compile-fail/lint-unused-imports.rs b/src/test/compile-fail/lint-unused-imports.rs
index 080c5e400ac..3c1f4b04306 100644
--- a/src/test/compile-fail/lint-unused-imports.rs
+++ b/src/test/compile-fail/lint-unused-imports.rs
@@ -69,6 +69,13 @@ mod bar {
     }
 }
 
+fn g() {
+    use self::g; //~ ERROR unused import
+    fn f() {
+        self::g();
+    }
+}
+
 fn main() {
     cal(foo::Point{x:3, y:9});
     let mut a = 3;
diff --git a/src/test/compile-fail/macro_undefined.rs b/src/test/compile-fail/macro_undefined.rs
new file mode 100644
index 00000000000..d9f86e3e62a
--- /dev/null
+++ b/src/test/compile-fail/macro_undefined.rs
@@ -0,0 +1,25 @@
+// 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.
+
+// Test macro_undefined issue
+
+mod m {
+    #[macro_export]
+    macro_rules! kl {
+        () => ()
+    }
+}
+
+fn main() {
+    k!(); //~ ERROR macro undefined: 'k!'
+          //~^ HELP did you mean `kl!`?
+    kl!(); //~ ERROR macro undefined: 'kl!'
+           //~^ HELP have you added the `#[macro_use]` on the module/import?
+}
diff --git a/src/test/compile-fail/warn-pub-extern-crate.rs b/src/test/compile-fail/mir-unpretty.rs
index de3cc27c49b..8950bef6a46 100644
--- a/src/test/compile-fail/warn-pub-extern-crate.rs
+++ b/src/test/compile-fail/mir-unpretty.rs
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs)]
+// compile-flags: -Z unstable-options --unpretty=mir
 
-pub extern crate core; //~WARN `pub extern crate` does not work
-
-#[rustc_error]
-fn main() {} //~ ERROR: compilation successful
+fn main() {
+    let x: () = 0; //~ ERROR: mismatched types
+}
diff --git a/src/test/compile-fail/no-implicit-prelude-nested.rs b/src/test/compile-fail/no-implicit-prelude-nested.rs
index 526750257d2..af1046bcd5d 100644
--- a/src/test/compile-fail/no-implicit-prelude-nested.rs
+++ b/src/test/compile-fail/no-implicit-prelude-nested.rs
@@ -18,11 +18,11 @@
 mod foo {
     mod baz {
         struct Test;
-        impl Add for Test {} //~ ERROR: use of undeclared trait
-        impl Clone for Test {} //~ ERROR: use of undeclared trait
-        impl Iterator for Test {} //~ ERROR: use of undeclared trait
-        impl ToString for Test {} //~ ERROR: use of undeclared trait
-        impl Writer for Test {} //~ ERROR: use of undeclared trait
+        impl Add for Test {} //~ ERROR: not in scope
+        impl Clone for Test {} //~ ERROR: not in scope
+        impl Iterator for Test {} //~ ERROR: not in scope
+        impl ToString for Test {} //~ ERROR: not in scope
+        impl Writer for Test {} //~ ERROR: not in scope
 
         fn foo() {
             drop(2) //~ ERROR: unresolved name
@@ -30,11 +30,11 @@ mod foo {
     }
 
     struct Test;
-    impl Add for Test {} //~ ERROR: use of undeclared trait
-    impl Clone for Test {} //~ ERROR: use of undeclared trait
-    impl Iterator for Test {} //~ ERROR: use of undeclared trait
-    impl ToString for Test {} //~ ERROR: use of undeclared trait
-    impl Writer for Test {} //~ ERROR: use of undeclared trait
+    impl Add for Test {} //~ ERROR: not in scope
+    impl Clone for Test {} //~ ERROR: not in scope
+    impl Iterator for Test {} //~ ERROR: not in scope
+    impl ToString for Test {} //~ ERROR: not in scope
+    impl Writer for Test {} //~ ERROR: not in scope
 
     fn foo() {
         drop(2) //~ ERROR: unresolved name
@@ -45,11 +45,11 @@ fn qux() {
     #[no_implicit_prelude]
     mod qux_inner {
         struct Test;
-        impl Add for Test {} //~ ERROR: use of undeclared trait
-        impl Clone for Test {} //~ ERROR: use of undeclared trait
-        impl Iterator for Test {} //~ ERROR: use of undeclared trait
-        impl ToString for Test {} //~ ERROR: use of undeclared trait
-        impl Writer for Test {} //~ ERROR: use of undeclared trait
+        impl Add for Test {} //~ ERROR: not in scope
+        impl Clone for Test {} //~ ERROR: not in scope
+        impl Iterator for Test {} //~ ERROR: not in scope
+        impl ToString for Test {} //~ ERROR: not in scope
+        impl Writer for Test {} //~ ERROR: not in scope
 
         fn foo() {
             drop(2) //~ ERROR: unresolved name
diff --git a/src/test/compile-fail/no-implicit-prelude.rs b/src/test/compile-fail/no-implicit-prelude.rs
index c4bcd33b93b..4693fd14e7d 100644
--- a/src/test/compile-fail/no-implicit-prelude.rs
+++ b/src/test/compile-fail/no-implicit-prelude.rs
@@ -17,11 +17,11 @@
 // fail with the same error message).
 
 struct Test;
-impl Add for Test {} //~ ERROR: use of undeclared trait
-impl Clone for Test {} //~ ERROR: use of undeclared trait
-impl Iterator for Test {} //~ ERROR: use of undeclared trait
-impl ToString for Test {} //~ ERROR: use of undeclared trait
-impl Writer for Test {} //~ ERROR: use of undeclared trait
+impl Add for Test {} //~ ERROR: not in scope
+impl Clone for Test {} //~ ERROR: not in scope
+impl Iterator for Test {} //~ ERROR: not in scope
+impl ToString for Test {} //~ ERROR: not in scope
+impl Writer for Test {} //~ ERROR: not in scope
 
 fn main() {
     drop(2) //~ ERROR: unresolved name
diff --git a/src/test/compile-fail/no-method-suggested-traits.rs b/src/test/compile-fail/no-method-suggested-traits.rs
index 08c848a09ab..1683db811cf 100644
--- a/src/test/compile-fail/no-method-suggested-traits.rs
+++ b/src/test/compile-fail/no-method-suggested-traits.rs
@@ -34,31 +34,31 @@ fn main() {
     1u32.method();
     //~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
     //~^^ ERROR no method named
-    //~^^^ HELP `foo::Bar`
-    //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
+    //~^^^ HELP `use foo::Bar`
+    //~^^^^ HELP `use no_method_suggested_traits::foo::PubPub`
     std::rc::Rc::new(&mut Box::new(&1u32)).method();
     //~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
     //~^^ ERROR no method named
-    //~^^^ HELP `foo::Bar`
-    //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
+    //~^^^ HELP `use foo::Bar`
+    //~^^^^ HELP `use no_method_suggested_traits::foo::PubPub`
 
     'a'.method();
     //~^ ERROR no method named
     //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
-    //~^^^ HELP `foo::Bar`
+    //~^^^ HELP `use foo::Bar`
     std::rc::Rc::new(&mut Box::new(&'a')).method();
     //~^ ERROR no method named
     //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
-    //~^^^ HELP `foo::Bar`
+    //~^^^ HELP `use foo::Bar`
 
     1i32.method();
     //~^ ERROR no method named
     //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
-    //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
+    //~^^^ HELP `use no_method_suggested_traits::foo::PubPub`
     std::rc::Rc::new(&mut Box::new(&1i32)).method();
     //~^ ERROR no method named
     //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
-    //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
+    //~^^^ HELP `use no_method_suggested_traits::foo::PubPub`
 
     Foo.method();
     //~^ ERROR no method named
diff --git a/src/test/compile-fail/no-extern-crate-in-glob-import.rs b/src/test/compile-fail/non-inline-mod-restriction.rs
index 75882c5e981..c4ede12e820 100644
--- a/src/test/compile-fail/no-extern-crate-in-glob-import.rs
+++ b/src/test/compile-fail/non-inline-mod-restriction.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,15 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that extern crate declarations are excluded from glob imports.
-
-#![feature(core)]
-extern crate core;
-
-mod T {
-    pub use super::*;
-}
+// Test that non-inline modules are not allowed inside blocks.
 
 fn main() {
-    use T::core; //~ ERROR unresolved import `T::core`
+    mod foo; //~ ERROR Cannot declare a non-inline module inside a block
 }
diff --git a/src/test/compile-fail/privacy-ns1.rs b/src/test/compile-fail/privacy-ns1.rs
index 5952f05b7bc..dcab3a46b0a 100644
--- a/src/test/compile-fail/privacy-ns1.rs
+++ b/src/test/compile-fail/privacy-ns1.rs
@@ -42,7 +42,7 @@ pub mod foo2 {
 fn test_glob2() {
     use foo2::*;
 
-    let _x: Box<Bar>;  //~ ERROR use of undeclared type name `Bar`
+    let _x: Box<Bar>;  //~ ERROR type name `Bar` is undefined or not in scope
 }
 
 // neither public
@@ -58,7 +58,7 @@ fn test_glob3() {
     use foo3::*;
 
     Bar();  //~ ERROR unresolved name `Bar`
-    let _x: Box<Bar>;  //~ ERROR  use of undeclared type name `Bar`
+    let _x: Box<Bar>;  //~ ERROR  type name `Bar` is undefined or not in scope
 }
 
 fn main() {
diff --git a/src/test/compile-fail/privacy5.rs b/src/test/compile-fail/privacy5.rs
index 83e13ff52f6..588c9be3065 100644
--- a/src/test/compile-fail/privacy5.rs
+++ b/src/test/compile-fail/privacy5.rs
@@ -63,25 +63,25 @@ fn this_crate() {
     let c = a::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
     let d = a::D(4);
 
-    let a::A(()) = a; //~ ERROR: field #1 of struct `a::A` is private
+    let a::A(()) = a; //~ ERROR: field #0 of struct `a::A` is private
     let a::A(_) = a;
-    match a { a::A(()) => {} } //~ ERROR: field #1 of struct `a::A` is private
+    match a { a::A(()) => {} } //~ ERROR: field #0 of struct `a::A` is private
     match a { a::A(_) => {} }
 
     let a::B(_) = b;
-    let a::B(_b) = b; //~ ERROR: field #1 of struct `a::B` is private
+    let a::B(_b) = b; //~ ERROR: field #0 of struct `a::B` is private
     match b { a::B(_) => {} }
-    match b { a::B(_b) => {} } //~ ERROR: field #1 of struct `a::B` is private
-    match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field #1 of struct `a::B` is private
+    match b { a::B(_b) => {} } //~ ERROR: field #0 of struct `a::B` is private
+    match b { a::B(1) => {} a::B(_) => {} } //~ ERROR: field #0 of struct `a::B` is private
 
     let a::C(_, _) = c;
     let a::C(_a, _) = c;
-    let a::C(_, _b) = c; //~ ERROR: field #2 of struct `a::C` is private
-    let a::C(_a, _b) = c; //~ ERROR: field #2 of struct `a::C` is private
+    let a::C(_, _b) = c; //~ ERROR: field #1 of struct `a::C` is private
+    let a::C(_a, _b) = c; //~ ERROR: field #1 of struct `a::C` is private
     match c { a::C(_, _) => {} }
     match c { a::C(_a, _) => {} }
-    match c { a::C(_, _b) => {} } //~ ERROR: field #2 of struct `a::C` is private
-    match c { a::C(_a, _b) => {} } //~ ERROR: field #2 of struct `a::C` is private
+    match c { a::C(_, _b) => {} } //~ ERROR: field #1 of struct `a::C` is private
+    match c { a::C(_a, _b) => {} } //~ ERROR: field #1 of struct `a::C` is private
 
     let a::D(_) = d;
     let a::D(_d) = d;
@@ -101,30 +101,30 @@ fn xcrate() {
     let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
     let d = other::D(4);
 
-    let other::A(()) = a; //~ ERROR: field #1 of struct `other::A` is private
+    let other::A(()) = a; //~ ERROR: field #0 of struct `other::A` is private
     let other::A(_) = a;
     match a { other::A(()) => {} }
-    //~^ ERROR: field #1 of struct `other::A` is private
+    //~^ ERROR: field #0 of struct `other::A` is private
     match a { other::A(_) => {} }
 
     let other::B(_) = b;
-    let other::B(_b) = b; //~ ERROR: field #1 of struct `other::B` is private
+    let other::B(_b) = b; //~ ERROR: field #0 of struct `other::B` is private
     match b { other::B(_) => {} }
     match b { other::B(_b) => {} }
-    //~^ ERROR: field #1 of struct `other::B` is private
+    //~^ ERROR: field #0 of struct `other::B` is private
     match b { other::B(1) => {} other::B(_) => {} }
-    //~^ ERROR: field #1 of struct `other::B` is private
+    //~^ ERROR: field #0 of struct `other::B` is private
 
     let other::C(_, _) = c;
     let other::C(_a, _) = c;
-    let other::C(_, _b) = c; //~ ERROR: field #2 of struct `other::C` is private
-    let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `other::C` is private
+    let other::C(_, _b) = c; //~ ERROR: field #1 of struct `other::C` is private
+    let other::C(_a, _b) = c; //~ ERROR: field #1 of struct `other::C` is private
     match c { other::C(_, _) => {} }
     match c { other::C(_a, _) => {} }
     match c { other::C(_, _b) => {} }
-    //~^ ERROR: field #2 of struct `other::C` is private
+    //~^ ERROR: field #1 of struct `other::C` is private
     match c { other::C(_a, _b) => {} }
-    //~^ ERROR: field #2 of struct `other::C` is private
+    //~^ ERROR: field #1 of struct `other::C` is private
 
     let other::D(_) = d;
     let other::D(_d) = d;
diff --git a/src/test/compile-fail/private-variant-reexport.rs b/src/test/compile-fail/private-variant-and-crate-reexport.rs
index 06f08dc13c6..5811d82681e 100644
--- a/src/test/compile-fail/private-variant-reexport.rs
+++ b/src/test/compile-fail/private-variant-and-crate-reexport.rs
@@ -11,6 +11,10 @@
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
 
+extern crate core;
+pub use core as reexported_core; //~ WARN extern crate `core` is private, and cannot be reexported
+//~^ WARNING hard error
+
 mod m1 {
     pub use ::E::V; //~ WARN variant `V` is private, and cannot be reexported
     //~^ WARNING hard error
diff --git a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
index 88f09233d10..92134ecde91 100644
--- a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
+++ b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs
@@ -18,7 +18,7 @@ trait TraitA<A> {
             //~^ ERROR parameter `B` is never used
             Variance(A)
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR use of undeclared type name `A`
+                //~^^ ERROR type name `A` is undefined or not in scope
         }
     }
 }
@@ -27,7 +27,7 @@ trait TraitB<A> {
     fn outer(self) {
         struct Foo<B>(A);
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR use of undeclared type name `A`
+                //~^^ ERROR type name `A` is undefined or not in scope
                 //~^^^ ERROR parameter `B` is never used
     }
 }
@@ -36,7 +36,7 @@ trait TraitC<A> {
     fn outer(self) {
         struct Foo<B> { a: A }
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR use of undeclared type name `A`
+                //~^^ ERROR type name `A` is undefined or not in scope
                 //~^^^ ERROR parameter `B` is never used
     }
 }
@@ -45,7 +45,7 @@ trait TraitD<A> {
     fn outer(self) {
         fn foo<B>(a: A) { }
                 //~^ ERROR can't use type parameters from outer function
-                //~^^ ERROR use of undeclared type name `A`
+                //~^^ ERROR type name `A` is undefined or not in scope
     }
 }
 
diff --git a/src/test/compile-fail/resolve-unknown-trait.rs b/src/test/compile-fail/resolve-unknown-trait.rs
index fd4dce51fc8..dae3a79832b 100644
--- a/src/test/compile-fail/resolve-unknown-trait.rs
+++ b/src/test/compile-fail/resolve-unknown-trait.rs
@@ -10,10 +10,10 @@
 
 
 trait NewTrait : SomeNonExistentTrait {}
-//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
+//~^ ERROR trait `SomeNonExistentTrait` is not in scope
 
 impl SomeNonExistentTrait for isize {}
-//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
+//~^ ERROR trait `SomeNonExistentTrait` is not in scope
 
 fn f<T:SomeNonExistentTrait>() {}
-//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
+//~^ ERROR trait `SomeNonExistentTrait` is not in scope
diff --git a/src/test/compile-fail/trait-impl-for-module.rs b/src/test/compile-fail/trait-impl-for-module.rs
index 969b6398fdb..c04e197b6bd 100644
--- a/src/test/compile-fail/trait-impl-for-module.rs
+++ b/src/test/compile-fail/trait-impl-for-module.rs
@@ -14,7 +14,7 @@ mod a {
 trait A {
 }
 
-impl A for a { //~ ERROR use of undeclared type name `a`
+impl A for a { //~ ERROR type name `a` is undefined or not in scope
 }
 
 fn main() {
diff --git a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
index b195a932aca..21450856ae6 100644
--- a/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
+++ b/src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
@@ -10,7 +10,7 @@
 
 #![feature(unboxed_closures)]
 
-fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR undeclared trait name `Nonexist`
+fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR trait `Nonexist` is not in scope
 
 type Typedef = isize;
 
diff --git a/src/test/run-fail/mir_drop_panics.rs b/src/test/run-fail/mir_drop_panics.rs
index df20700e016..1a4330523ba 100644
--- a/src/test/run-fail/mir_drop_panics.rs
+++ b/src/test/run-fail/mir_drop_panics.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 #![feature(rustc_attrs)]
 
-// ignore-msvc: FIXME(#30941)
 // error-pattern:panic 1
 // error-pattern:drop 2
 use std::io::{self, Write};
diff --git a/src/test/run-fail/mir_trans_calls_converging_drops.rs b/src/test/run-fail/mir_trans_calls_converging_drops.rs
index eb399e07d85..5927d802b45 100644
--- a/src/test/run-fail/mir_trans_calls_converging_drops.rs
+++ b/src/test/run-fail/mir_trans_calls_converging_drops.rs
@@ -10,7 +10,6 @@
 
 #![feature(rustc_attrs)]
 
-// ignore-msvc: FIXME(#30941)
 // error-pattern:converging_fn called
 // error-pattern:0 dropped
 // error-pattern:exit
diff --git a/src/test/run-fail/mir_trans_calls_converging_drops_2.rs b/src/test/run-fail/mir_trans_calls_converging_drops_2.rs
index df4ead387b9..96a46f47eb5 100644
--- a/src/test/run-fail/mir_trans_calls_converging_drops_2.rs
+++ b/src/test/run-fail/mir_trans_calls_converging_drops_2.rs
@@ -10,7 +10,6 @@
 
 #![feature(rustc_attrs)]
 
-// ignore-msvc: FIXME(#30941)
 // error-pattern:complex called
 // error-pattern:dropped
 // error-pattern:exit
diff --git a/src/test/run-fail/mir_trans_calls_diverging_drops.rs b/src/test/run-fail/mir_trans_calls_diverging_drops.rs
index cbe8793cceb..89b53b18f06 100644
--- a/src/test/run-fail/mir_trans_calls_diverging_drops.rs
+++ b/src/test/run-fail/mir_trans_calls_diverging_drops.rs
@@ -10,7 +10,6 @@
 
 #![feature(rustc_attrs)]
 
-// ignore-msvc: FIXME(#30941)
 // error-pattern:diverging_fn called
 // error-pattern:0 dropped
 
diff --git a/src/test/run-make/llvm-module-pass/Makefile b/src/test/run-make/llvm-module-pass/Makefile
deleted file mode 100644
index 93c7c4f5001..00000000000
--- a/src/test/run-make/llvm-module-pass/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
--include ../tools.mk
-
-# Windows doesn't correctly handle include statements with escaping paths,
-# so this test will not get run on Windows.
-ifdef IS_WINDOWS
-all:
-else
-all: $(call NATIVE_STATICLIB,llvm-pass)
-	$(RUSTC) plugin.rs -C prefer-dynamic
-	$(RUSTC) main.rs
-
-$(TMPDIR)/libllvm-pass.o:
-	$(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-pass.so.cc -o $(TMPDIR)/libllvm-pass.o
-endif
diff --git a/src/test/run-make/llvm-pass/Makefile b/src/test/run-make/llvm-pass/Makefile
new file mode 100644
index 00000000000..aab6e895f22
--- /dev/null
+++ b/src/test/run-make/llvm-pass/Makefile
@@ -0,0 +1,17 @@
+-include ../tools.mk
+
+# Windows doesn't correctly handle include statements with escaping paths,
+# so this test will not get run on Windows.
+ifdef IS_WINDOWS
+all:
+else
+all: $(call NATIVE_STATICLIB,llvm-function-pass) $(call NATIVE_STATICLIB,llvm-module-pass)
+	$(RUSTC) plugin.rs -C prefer-dynamic
+	$(RUSTC) main.rs
+
+$(TMPDIR)/libllvm-function-pass.o:
+	$(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-function-pass.so.cc -o $(TMPDIR)/libllvm-function-pass.o
+
+$(TMPDIR)/libllvm-module-pass.o:
+	$(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-module-pass.so.cc -o $(TMPDIR)/libllvm-module-pass.o
+endif
diff --git a/src/test/run-make/llvm-pass/llvm-function-pass.so.cc b/src/test/run-make/llvm-pass/llvm-function-pass.so.cc
new file mode 100644
index 00000000000..4470c400760
--- /dev/null
+++ b/src/test/run-make/llvm-pass/llvm-function-pass.so.cc
@@ -0,0 +1,56 @@
+// 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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "llvm/Pass.h"
+#include "llvm/IR/Function.h"
+
+using namespace llvm;
+
+namespace {
+
+  class TestLLVMPass : public FunctionPass {
+
+  public:
+
+    static char ID;
+    TestLLVMPass() : FunctionPass(ID) { }
+
+    bool runOnFunction(Function &F) override;
+
+    const char *getPassName() const override {
+      return "Some LLVM pass";
+    }
+
+  };
+
+}
+
+bool TestLLVMPass::runOnFunction(Function &F) {
+  // A couple examples of operations that previously caused segmentation faults
+  // https://github.com/rust-lang/rust/issues/31067
+
+  for (auto N = F.begin(); N != F.end(); ++N) {
+    /* code */
+  }
+
+  LLVMContext &C = F.getContext();
+  IntegerType *Int8Ty  = IntegerType::getInt8Ty(C);
+  PointerType::get(Int8Ty, 0);
+  return true;
+}
+
+char TestLLVMPass::ID = 0;
+
+static RegisterPass<TestLLVMPass> RegisterAFLPass(
+  "some-llvm-function-pass", "Some LLVM pass");
diff --git a/src/test/run-make/llvm-module-pass/llvm-pass.so.cc b/src/test/run-make/llvm-pass/llvm-module-pass.so.cc
index 06b0d6c300c..510375a5e66 100644
--- a/src/test/run-make/llvm-module-pass/llvm-pass.so.cc
+++ b/src/test/run-make/llvm-pass/llvm-module-pass.so.cc
@@ -52,4 +52,4 @@ bool TestLLVMPass::runOnModule(Module &M) {
 char TestLLVMPass::ID = 0;
 
 static RegisterPass<TestLLVMPass> RegisterAFLPass(
-  "some-llvm-pass", "Some LLVM pass");
+  "some-llvm-module-pass", "Some LLVM pass");
diff --git a/src/test/run-make/llvm-module-pass/main.rs b/src/test/run-make/llvm-pass/main.rs
index 5b5ab94bcef..5b5ab94bcef 100644
--- a/src/test/run-make/llvm-module-pass/main.rs
+++ b/src/test/run-make/llvm-pass/main.rs
diff --git a/src/test/run-make/llvm-module-pass/plugin.rs b/src/test/run-make/llvm-pass/plugin.rs
index 039de3c7179..f77b2fca857 100644
--- a/src/test/run-make/llvm-module-pass/plugin.rs
+++ b/src/test/run-make/llvm-pass/plugin.rs
@@ -15,12 +15,14 @@
 extern crate rustc;
 extern crate rustc_plugin;
 
-#[link(name = "llvm-pass", kind = "static")]
+#[link(name = "llvm-function-pass", kind = "static")]
+#[link(name = "llvm-module-pass", kind = "static")]
 extern {}
 
 use rustc_plugin::registry::Registry;
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_llvm_pass("some-llvm-pass");
+    reg.register_llvm_pass("some-llvm-function-pass");
+    reg.register_llvm_pass("some-llvm-module-pass");
 }
diff --git a/src/test/run-make/volatile-intrinsics/main.rs b/src/test/run-make/volatile-intrinsics/main.rs
index 6c6afdc1303..4d0d7672101 100644
--- a/src/test/run-make/volatile-intrinsics/main.rs
+++ b/src/test/run-make/volatile-intrinsics/main.rs
@@ -8,9 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(core_intrinsics)]
+#![feature(core_intrinsics, volatile)]
 
 use std::intrinsics::{volatile_load, volatile_store};
+use std::ptr::{read_volatile, write_volatile};
 
 pub fn main() {
     unsafe {
@@ -18,4 +19,9 @@ pub fn main() {
         volatile_store(&mut i, 2);
         assert_eq!(volatile_load(&i), 2);
     }
+    unsafe {
+        let mut i : isize = 1;
+        write_volatile(&mut i, 2);
+        assert_eq!(read_volatile(&i), 2);
+    }
 }
diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
index b13e34256d2..247e82c2f09 100644
--- a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
+++ b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
+
 #![allow(dead_code)]
 #![feature(const_fn)]
 
diff --git a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs
index 0bbb9ed1285..220968529de 100644
--- a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs
+++ b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
 
 // This would previously leak the Box<Trait> because we wouldn't
 // schedule cleanups when auto borrowing trait objects.
diff --git a/src/test/run-pass-valgrind/cleanup-stdin.rs b/src/test/run-pass-valgrind/cleanup-stdin.rs
index dcdce50c1e9..b7c94ed6944 100644
--- a/src/test/run-pass-valgrind/cleanup-stdin.rs
+++ b/src/test/run-pass-valgrind/cleanup-stdin.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
+
 fn main() {
     let _ = std::io::stdin();
     let _ = std::io::stdout();
diff --git a/src/test/run-pass-valgrind/down-with-thread-dtors.rs b/src/test/run-pass-valgrind/down-with-thread-dtors.rs
index 5c449d511d5..0bf10c67d9f 100644
--- a/src/test/run-pass-valgrind/down-with-thread-dtors.rs
+++ b/src/test/run-pass-valgrind/down-with-thread-dtors.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
+
 thread_local!(static FOO: Foo = Foo);
 thread_local!(static BAR: Bar = Bar(1));
 thread_local!(static BAZ: Baz = Baz);
diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs
index d051b7b491b..995da8c73fa 100644
--- a/src/test/run-pass-valgrind/dst-dtor-1.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-1.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
+
 static mut DROP_RAN: bool = false;
 
 struct Foo;
diff --git a/src/test/run-pass-valgrind/dst-dtor-2.rs b/src/test/run-pass-valgrind/dst-dtor-2.rs
index a89873b1277..471169340d7 100644
--- a/src/test/run-pass-valgrind/dst-dtor-2.rs
+++ b/src/test/run-pass-valgrind/dst-dtor-2.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
+
 static mut DROP_RAN: isize = 0;
 
 struct Foo;
diff --git a/src/test/run-pass-valgrind/exit-flushes.rs b/src/test/run-pass-valgrind/exit-flushes.rs
index 632693dd728..1897b921401 100644
--- a/src/test/run-pass-valgrind/exit-flushes.rs
+++ b/src/test/run-pass-valgrind/exit-flushes.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
 // ignore-macos this needs valgrind 3.11 or higher; see
 // https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679
 
diff --git a/src/test/run-pass-valgrind/osx-frameworks.rs b/src/test/run-pass-valgrind/osx-frameworks.rs
index 41b34dc79bd..468a20db6f7 100644
--- a/src/test/run-pass-valgrind/osx-frameworks.rs
+++ b/src/test/run-pass-valgrind/osx-frameworks.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// no-prefer-dynamic
 // pretty-expanded FIXME #23616
 
 #![feature(libc)]
diff --git a/src/test/run-pass/atomic-compare_exchange.rs b/src/test/run-pass/atomic-compare_exchange.rs
new file mode 100644
index 00000000000..7946704709c
--- /dev/null
+++ b/src/test/run-pass/atomic-compare_exchange.rs
@@ -0,0 +1,37 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(extended_compare_and_swap)]
+use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT};
+use std::sync::atomic::Ordering::*;
+
+static ATOMIC: AtomicIsize = ATOMIC_ISIZE_INIT;
+
+fn main() {
+    // Make sure trans can emit all the intrinsics correctly
+    ATOMIC.compare_exchange(0, 1, Relaxed, Relaxed);
+    ATOMIC.compare_exchange(0, 1, Acquire, Relaxed);
+    ATOMIC.compare_exchange(0, 1, Release, Relaxed);
+    ATOMIC.compare_exchange(0, 1, AcqRel, Relaxed);
+    ATOMIC.compare_exchange(0, 1, SeqCst, Relaxed);
+    ATOMIC.compare_exchange(0, 1, Acquire, Acquire);
+    ATOMIC.compare_exchange(0, 1, AcqRel, Acquire);
+    ATOMIC.compare_exchange(0, 1, SeqCst, Acquire);
+    ATOMIC.compare_exchange(0, 1, SeqCst, SeqCst);
+    ATOMIC.compare_exchange_weak(0, 1, Relaxed, Relaxed);
+    ATOMIC.compare_exchange_weak(0, 1, Acquire, Relaxed);
+    ATOMIC.compare_exchange_weak(0, 1, Release, Relaxed);
+    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Relaxed);
+    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Relaxed);
+    ATOMIC.compare_exchange_weak(0, 1, Acquire, Acquire);
+    ATOMIC.compare_exchange_weak(0, 1, AcqRel, Acquire);
+    ATOMIC.compare_exchange_weak(0, 1, SeqCst, Acquire);
+    ATOMIC.compare_exchange_weak(0, 1, SeqCst, SeqCst);
+}
diff --git a/src/test/compile-fail/augmented-assignments-feature-gate-cross.rs b/src/test/run-pass/augmented-assignments-feature-gate-cross.rs
index d4a9830f220..b68e011af15 100644
--- a/src/test/compile-fail/augmented-assignments-feature-gate-cross.rs
+++ b/src/test/run-pass/augmented-assignments-feature-gate-cross.rs
@@ -10,9 +10,6 @@
 
 // aux-build:augmented_assignments.rs
 
-// Test that the feature gate is needed when using augmented assignments that were overloaded in
-// another crate
-
 extern crate augmented_assignments;
 
 use augmented_assignments::Int;
@@ -20,6 +17,4 @@ use augmented_assignments::Int;
 fn main() {
     let mut x = Int(0);
     x += 1;
-    //~^ error: overloaded augmented assignments are not stable
-    //~| help: add #![feature(augmented_assignments)] to the crate root to enable
 }
diff --git a/src/test/compile-fail/augmented-assignments-feature-gate.rs b/src/test/run-pass/augmented-assignments-feature-gate.rs
index 6f9e9cf945a..f7e20ee9445 100644
--- a/src/test/compile-fail/augmented-assignments-feature-gate.rs
+++ b/src/test/run-pass/augmented-assignments-feature-gate.rs
@@ -14,13 +14,10 @@ struct Int(i32);
 
 impl AddAssign<i32> for Int {
     fn add_assign(&mut self, _: i32) {
-        unimplemented!()
     }
 }
 
 fn main() {
     let mut x = Int(0);
     x += 1;
-    //~^ error: overloaded augmented assignments are not stable
-    //~| help: add #![feature(augmented_assignments)] to the crate root to enable
 }
diff --git a/src/test/compile-fail/augmented-assignments-trait.rs b/src/test/run-pass/augmented-assignments-trait.rs
index 83e8d1f3b38..f1cb2c56dbc 100644
--- a/src/test/compile-fail/augmented-assignments-trait.rs
+++ b/src/test/run-pass/augmented-assignments-trait.rs
@@ -9,14 +9,11 @@
 // except according to those terms.
 
 use std::ops::AddAssign;
-//~^ error: use of unstable library feature 'op_assign_traits'
 
 struct Int(i32);
 
 impl AddAssign for Int {
-    //~^ error: use of unstable library feature 'op_assign_traits'
     fn add_assign(&mut self, _: Int) {
-        //~^ error: use of unstable library feature 'op_assign_traits'
         unimplemented!()
     }
 }
diff --git a/src/test/run-pass/augmented-assignments.rs b/src/test/run-pass/augmented-assignments.rs
index eb4c1dbb0b7..8c9ebcd274a 100644
--- a/src/test/run-pass/augmented-assignments.rs
+++ b/src/test/run-pass/augmented-assignments.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(augmented_assignments)]
-#![feature(op_assign_traits)]
-
 use std::mem;
 use std::ops::{
     AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, Index, MulAssign, RemAssign,
diff --git a/src/test/run-pass/borrowck-assign-to-subfield.rs b/src/test/run-pass/borrowck/borrowck-assign-to-subfield.rs
index ee74a054408..ee74a054408 100644
--- a/src/test/run-pass/borrowck-assign-to-subfield.rs
+++ b/src/test/run-pass/borrowck/borrowck-assign-to-subfield.rs
diff --git a/src/test/run-pass/borrowck-binding-mutbl.rs b/src/test/run-pass/borrowck/borrowck-binding-mutbl.rs
index 10e9a1b51e2..10e9a1b51e2 100644
--- a/src/test/run-pass/borrowck-binding-mutbl.rs
+++ b/src/test/run-pass/borrowck/borrowck-binding-mutbl.rs
diff --git a/src/test/run-pass/borrowck-borrow-from-expr-block.rs b/src/test/run-pass/borrowck/borrowck-borrow-from-expr-block.rs
index 7fdc65a96e2..7fdc65a96e2 100644
--- a/src/test/run-pass/borrowck-borrow-from-expr-block.rs
+++ b/src/test/run-pass/borrowck/borrowck-borrow-from-expr-block.rs
diff --git a/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs b/src/test/run-pass/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs
index b716a1a27a1..b716a1a27a1 100644
--- a/src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs
+++ b/src/test/run-pass/borrowck/borrowck-borrow-of-mut-base-ptr-safe.rs
diff --git a/src/test/run-pass/borrowck-closures-two-imm.rs b/src/test/run-pass/borrowck/borrowck-closures-two-imm.rs
index 5b15c8f0797..5b15c8f0797 100644
--- a/src/test/run-pass/borrowck-closures-two-imm.rs
+++ b/src/test/run-pass/borrowck/borrowck-closures-two-imm.rs
diff --git a/src/test/run-pass/borrowck-field-sensitivity.rs b/src/test/run-pass/borrowck/borrowck-field-sensitivity.rs
index d97564a2914..d97564a2914 100644
--- a/src/test/run-pass/borrowck-field-sensitivity.rs
+++ b/src/test/run-pass/borrowck/borrowck-field-sensitivity.rs
diff --git a/src/test/run-pass/borrowck-fixed-length-vecs.rs b/src/test/run-pass/borrowck/borrowck-fixed-length-vecs.rs
index 0e33351894d..0e33351894d 100644
--- a/src/test/run-pass/borrowck-fixed-length-vecs.rs
+++ b/src/test/run-pass/borrowck/borrowck-fixed-length-vecs.rs
diff --git a/src/test/run-pass/borrowck-freeze-frozen-mut.rs b/src/test/run-pass/borrowck/borrowck-freeze-frozen-mut.rs
index 380bd398a7c..380bd398a7c 100644
--- a/src/test/run-pass/borrowck-freeze-frozen-mut.rs
+++ b/src/test/run-pass/borrowck/borrowck-freeze-frozen-mut.rs
diff --git a/src/test/run-pass/borrowck-lend-args.rs b/src/test/run-pass/borrowck/borrowck-lend-args.rs
index f1f0274c5cc..f1f0274c5cc 100644
--- a/src/test/run-pass/borrowck-lend-args.rs
+++ b/src/test/run-pass/borrowck/borrowck-lend-args.rs
diff --git a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs b/src/test/run-pass/borrowck/borrowck-macro-interaction-issue-6304.rs
index fb30c85e709..fb30c85e709 100644
--- a/src/test/run-pass/borrowck-macro-interaction-issue-6304.rs
+++ b/src/test/run-pass/borrowck/borrowck-macro-interaction-issue-6304.rs
diff --git a/src/test/run-pass/borrowck-move-by-capture-ok.rs b/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
index bbc668f5cab..bbc668f5cab 100644
--- a/src/test/run-pass/borrowck-move-by-capture-ok.rs
+++ b/src/test/run-pass/borrowck/borrowck-move-by-capture-ok.rs
diff --git a/src/test/run-pass/borrowck-mut-uniq.rs b/src/test/run-pass/borrowck/borrowck-mut-uniq.rs
index f535c5fcfc9..f535c5fcfc9 100644
--- a/src/test/run-pass/borrowck-mut-uniq.rs
+++ b/src/test/run-pass/borrowck/borrowck-mut-uniq.rs
diff --git a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs b/src/test/run-pass/borrowck/borrowck-mut-vec-as-imm-slice.rs
index d55517c65d6..d55517c65d6 100644
--- a/src/test/run-pass/borrowck-mut-vec-as-imm-slice.rs
+++ b/src/test/run-pass/borrowck/borrowck-mut-vec-as-imm-slice.rs
diff --git a/src/test/run-pass/borrowck-pat-enum.rs b/src/test/run-pass/borrowck/borrowck-pat-enum.rs
index b29cb63f6fa..b29cb63f6fa 100644
--- a/src/test/run-pass/borrowck-pat-enum.rs
+++ b/src/test/run-pass/borrowck/borrowck-pat-enum.rs
diff --git a/src/test/run-pass/borrowck-pat-reassign-no-binding.rs b/src/test/run-pass/borrowck/borrowck-pat-reassign-no-binding.rs
index e0a5db678d2..e0a5db678d2 100644
--- a/src/test/run-pass/borrowck-pat-reassign-no-binding.rs
+++ b/src/test/run-pass/borrowck/borrowck-pat-reassign-no-binding.rs
diff --git a/src/test/run-pass/borrowck-rvalues-mutable.rs b/src/test/run-pass/borrowck/borrowck-rvalues-mutable.rs
index 93cb0cb0af2..93cb0cb0af2 100644
--- a/src/test/run-pass/borrowck-rvalues-mutable.rs
+++ b/src/test/run-pass/borrowck/borrowck-rvalues-mutable.rs
diff --git a/src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs b/src/test/run-pass/borrowck/borrowck-scope-of-deref-issue-4666.rs
index 59a5fea769a..59a5fea769a 100644
--- a/src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs
+++ b/src/test/run-pass/borrowck/borrowck-scope-of-deref-issue-4666.rs
diff --git a/src/test/run-pass/borrowck-static-item-in-fn.rs b/src/test/run-pass/borrowck/borrowck-static-item-in-fn.rs
index d51d0b1d2e1..d51d0b1d2e1 100644
--- a/src/test/run-pass/borrowck-static-item-in-fn.rs
+++ b/src/test/run-pass/borrowck/borrowck-static-item-in-fn.rs
diff --git a/src/test/run-pass/borrowck-trait-lifetime.rs b/src/test/run-pass/borrowck/borrowck-trait-lifetime.rs
index 0bfa8f48650..0bfa8f48650 100644
--- a/src/test/run-pass/borrowck-trait-lifetime.rs
+++ b/src/test/run-pass/borrowck/borrowck-trait-lifetime.rs
diff --git a/src/test/run-pass/borrowck-uniq-via-ref.rs b/src/test/run-pass/borrowck/borrowck-uniq-via-ref.rs
index 0ec87599c63..0ec87599c63 100644
--- a/src/test/run-pass/borrowck-uniq-via-ref.rs
+++ b/src/test/run-pass/borrowck/borrowck-uniq-via-ref.rs
diff --git a/src/test/run-pass/borrowck-univariant-enum.rs b/src/test/run-pass/borrowck/borrowck-univariant-enum.rs
index 2e8ddb08064..2e8ddb08064 100644
--- a/src/test/run-pass/borrowck-univariant-enum.rs
+++ b/src/test/run-pass/borrowck/borrowck-univariant-enum.rs
diff --git a/src/test/run-pass/borrowck-use-mut-borrow.rs b/src/test/run-pass/borrowck/borrowck-use-mut-borrow.rs
index 7ad81b6be6e..7ad81b6be6e 100644
--- a/src/test/run-pass/borrowck-use-mut-borrow.rs
+++ b/src/test/run-pass/borrowck/borrowck-use-mut-borrow.rs
diff --git a/src/test/run-pass/empty-struct-braces-derive.rs b/src/test/run-pass/empty-struct-braces-derive.rs
new file mode 100644
index 00000000000..8d19209208d
--- /dev/null
+++ b/src/test/run-pass/empty-struct-braces-derive.rs
@@ -0,0 +1,44 @@
+// 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.
+
+// `#[derive(Trait)]` works for empty structs/variants with braces
+
+#![feature(rustc_private)]
+
+extern crate serialize as rustc_serialize;
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
+         Default, Debug, RustcEncodable, RustcDecodable)]
+struct S {}
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
+         Debug, RustcEncodable, RustcDecodable)]
+enum E {
+    V {},
+    U,
+}
+
+fn main() {
+    let s = S {};
+    let s1 = s;
+    let s2 = s.clone();
+    assert_eq!(s, s1);
+    assert_eq!(s, s2);
+    assert!(!(s < s1));
+    assert_eq!(format!("{:?}", s), "S");
+
+    let e = E::V {};
+    let e1 = e;
+    let e2 = e.clone();
+    assert_eq!(e, e1);
+    assert_eq!(e, e2);
+    assert!(!(e < e1));
+    assert_eq!(format!("{:?}", e), "V");
+}
diff --git a/src/test/compile-fail/empty-struct-braces-gate-1.rs b/src/test/run-pass/empty-struct-braces-gate-1.rs
index a131b46e1c1..8287e151326 100644
--- a/src/test/compile-fail/empty-struct-braces-gate-1.rs
+++ b/src/test/run-pass/empty-struct-braces-gate-1.rs
@@ -11,11 +11,11 @@
 // Feature gate test for empty struct with braces
 // Can't define an empty braced struct
 
-struct Empty1 {} //~ ERROR empty structs and enum variants with braces are unstable
+struct Empty1 {}
 struct Empty2;
 
 enum E {
-    Empty4 {}, //~ ERROR empty structs and enum variants with braces are unstable
+    Empty4 {},
     Empty5,
 }
 
diff --git a/src/test/compile-fail/empty-struct-braces-gate-2.rs b/src/test/run-pass/empty-struct-braces-gate-2.rs
index b2d44301eed..0ec3c89859e 100644
--- a/src/test/compile-fail/empty-struct-braces-gate-2.rs
+++ b/src/test/run-pass/empty-struct-braces-gate-2.rs
@@ -18,29 +18,29 @@ enum E {
 }
 
 fn main() {
-    let e2: Empty2 = Empty2 {}; //~ ERROR empty structs and enum variants with braces are unstable
+    let e2: Empty2 = Empty2 {};
     let e2: Empty2 = Empty2;
-    let e5: E = E::Empty5 {}; //~ ERROR empty structs and enum variants with braces are unstable
+    let e5: E = E::Empty5 {};
     let e5: E = E::Empty5;
 
     match e2 {
-        Empty2 {} => {} //~ ERROR empty structs and enum variants with braces are unstable
+        Empty2 {} => {}
     }
     match e2 {
         Empty2 => {}
     }
     match e2 {
-        Empty2 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
+        Empty2 { .. } => {}
     }
     match e5 {
-        E::Empty5 {} => {} //~ ERROR empty structs and enum variants with braces are unstable
+        E::Empty5 {} => {}
     }
     match e5 {
         E::Empty5 => {}
     }
     match e5 {
-        E::Empty5 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
+        E::Empty5 { .. } => {}
     }
 
-    let e22 = Empty2 { ..e2 }; //~ ERROR empty structs and enum variants with braces are unstable
+    let e22 = Empty2 { ..e2 };
 }
diff --git a/src/test/run-pass/empty-struct-braces.rs b/src/test/run-pass/empty-struct-braces.rs
index 8d6f4d4c30a..85ae77f20f1 100644
--- a/src/test/run-pass/empty-struct-braces.rs
+++ b/src/test/run-pass/empty-struct-braces.rs
@@ -13,8 +13,6 @@
 
 // aux-build:empty-struct.rs
 
-#![feature(braced_empty_structs)]
-
 extern crate empty_struct;
 use empty_struct::*;
 
diff --git a/src/test/run-pass/foreign-mod-src/compiletest-ignore-dir b/src/test/run-pass/foreign-mod-src/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-pass/foreign-mod-src/compiletest-ignore-dir
diff --git a/src/test/run-pass/foreign-src/compiletest-ignore-dir b/src/test/run-pass/foreign-src/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-pass/foreign-src/compiletest-ignore-dir
diff --git a/src/test/run-pass/intrinsic-atomics.rs b/src/test/run-pass/intrinsic-atomics.rs
index 4ccab55e943..3cc125e9513 100644
--- a/src/test/run-pass/intrinsic-atomics.rs
+++ b/src/test/run-pass/intrinsic-atomics.rs
@@ -19,6 +19,10 @@ mod rusti {
         pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> T;
         pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> T;
 
+        pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+        pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
+
         pub fn atomic_load<T>(src: *const T) -> T;
         pub fn atomic_load_acq<T>(src: *const T) -> T;
 
@@ -79,5 +83,32 @@ pub fn main() {
         assert_eq!(rusti::atomic_xsub_acq(&mut *x, 1), 2);
         assert_eq!(rusti::atomic_xsub_rel(&mut *x, 1), 1);
         assert_eq!(*x, 0);
+
+        loop {
+            let res = rusti::atomic_cxchgweak(&mut *x, 0, 1);
+            assert_eq!(res.0, 0);
+            if res.1 {
+                break;
+            }
+        }
+        assert_eq!(*x, 1);
+
+        loop {
+            let res = rusti::atomic_cxchgweak_acq(&mut *x, 1, 2);
+            assert_eq!(res.0, 1);
+            if res.1 {
+                break;
+            }
+        }
+        assert_eq!(*x, 2);
+
+        loop {
+            let res = rusti::atomic_cxchgweak_rel(&mut *x, 2, 3);
+            assert_eq!(res.0, 2);
+            if res.1 {
+                break;
+            }
+        }
+        assert_eq!(*x, 3);
     }
 }
diff --git a/src/test/run-pass/issue-16819.rs b/src/test/run-pass/issue-16819.rs
index a9abb99696f..fb35ce33157 100644
--- a/src/test/run-pass/issue-16819.rs
+++ b/src/test/run-pass/issue-16819.rs
@@ -10,8 +10,6 @@
 
 //`#[cfg]` on struct field permits empty unusable struct
 
-#![feature(braced_empty_structs)]
-
 struct S {
     #[cfg(untrue)]
     a: int,
diff --git a/src/test/run-pass/issue-25916.rs b/src/test/run-pass/issue-25916.rs
new file mode 100644
index 00000000000..eb52e2e21c4
--- /dev/null
+++ b/src/test/run-pass/issue-25916.rs
@@ -0,0 +1,35 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    macro_rules! f {
+        () => { 0 + 0 }
+    }
+    // 16 per line
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+    f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();f!();
+}
diff --git a/src/test/run-pass/issue-29914-2.rs b/src/test/run-pass/issue-29914-2.rs
new file mode 100644
index 00000000000..fe0a6cf2880
--- /dev/null
+++ b/src/test/run-pass/issue-29914-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.
+
+const ARR: [usize; 5] = [5, 4, 3, 2, 1];
+
+fn main() {
+    assert_eq!(3, ARR[ARR[3]]);
+}
diff --git a/src/test/run-pass/issue-29914-3.rs b/src/test/run-pass/issue-29914-3.rs
new file mode 100644
index 00000000000..3a02764164c
--- /dev/null
+++ b/src/test/run-pass/issue-29914-3.rs
@@ -0,0 +1,16 @@
+// 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.
+
+const ARR: [usize; 5] = [5, 4, 3, 2, 1];
+const BLA: usize = ARR[ARR[3]];
+
+fn main() {
+    assert_eq!(3, BLA);
+}
diff --git a/src/test/run-pass/issue-29914.rs b/src/test/run-pass/issue-29914.rs
new file mode 100644
index 00000000000..bb933f0e422
--- /dev/null
+++ b/src/test/run-pass/issue-29914.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(const_indexing)]
+
+const ARR: [usize; 5] = [5, 4, 3, 2, 1];
+
+fn main() {
+    assert_eq!(3, ARR[ARR[3]]);
+}
diff --git a/src/test/run-pass/issue-31702.rs b/src/test/run-pass/issue-31702.rs
new file mode 100644
index 00000000000..334c1b2a28b
--- /dev/null
+++ b/src/test/run-pass/issue-31702.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.
+
+// aux-build:issue-31702-1.rs
+// aux-build:issue-31702-2.rs
+// ignore-test: FIXME(#31702) when this test was added it was thought that the
+//                            accompanying llvm update would fix it, but
+//                            unfortunately it appears that was not the case. In
+//                            the interest of not deleting the test, though,
+//                            this is just tagged with ignore-test
+
+// this test is actually entirely in the linked library crates
+
+extern crate issue_31702_1;
+extern crate issue_31702_2;
+
+fn main() {}
diff --git a/src/test/run-pass/issue-pr29383.rs b/src/test/run-pass/issue-pr29383.rs
index 487dbdd33c9..defb2c164da 100644
--- a/src/test/run-pass/issue-pr29383.rs
+++ b/src/test/run-pass/issue-pr29383.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(match_of_unit_variant_via_paren_dotdot)]
+
 enum E {
     A,
     B,
diff --git a/src/test/run-pass/issue_26873_multifile/compiletest-ignore-dir b/src/test/run-pass/issue_26873_multifile/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-pass/issue_26873_multifile/compiletest-ignore-dir
diff --git a/src/test/run-pass/mir_augmented_assignments.rs b/src/test/run-pass/mir_augmented_assignments.rs
new file mode 100644
index 00000000000..dcfa569a933
--- /dev/null
+++ b/src/test/run-pass/mir_augmented_assignments.rs
@@ -0,0 +1,185 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+use std::mem;
+use std::ops::{
+    AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, MulAssign, RemAssign,
+    ShlAssign, ShrAssign, SubAssign,
+};
+
+#[derive(Debug, PartialEq)]
+struct Int(i32);
+
+struct Slice([i32]);
+
+impl Slice {
+    fn new(slice: &mut [i32]) -> &mut Slice {
+        unsafe {
+            mem::transmute(slice)
+        }
+    }
+}
+
+fn main() {
+    main_mir();
+}
+
+#[rustc_mir]
+fn main_mir() {
+    let mut x = Int(1);
+
+    x += Int(2);
+    assert_eq!(x, Int(0b11));
+
+    x &= Int(0b01);
+    assert_eq!(x, Int(0b01));
+
+    x |= Int(0b10);
+    assert_eq!(x, Int(0b11));
+
+    x ^= Int(0b01);
+    assert_eq!(x, Int(0b10));
+
+    x /= Int(2);
+    assert_eq!(x, Int(1));
+
+    x *= Int(3);
+    assert_eq!(x, Int(3));
+
+    x %= Int(2);
+    assert_eq!(x, Int(1));
+
+    // overloaded RHS
+    x <<= 1u8;
+    assert_eq!(x, Int(2));
+
+    x <<= 1u16;
+    assert_eq!(x, Int(4));
+
+    x >>= 1u8;
+    assert_eq!(x, Int(2));
+
+    x >>= 1u16;
+    assert_eq!(x, Int(1));
+
+    x -= Int(1);
+    assert_eq!(x, Int(0));
+
+    // indexed LHS
+    // FIXME(mir-drop): use the vec![..] macro
+    let mut v = Vec::new();
+    v.push(Int(1));
+    v.push(Int(2));
+    v[0] += Int(2);
+    assert_eq!(v[0], Int(3));
+
+    // unsized RHS
+    let mut array = [0, 1, 2];
+    *Slice::new(&mut array) += 1;
+    assert_eq!(array[0], 1);
+    assert_eq!(array[1], 2);
+    assert_eq!(array[2], 3);
+
+}
+
+impl AddAssign for Int {
+    #[rustc_mir]
+    fn add_assign(&mut self, rhs: Int) {
+        self.0 += rhs.0;
+    }
+}
+
+impl BitAndAssign for Int {
+    #[rustc_mir]
+    fn bitand_assign(&mut self, rhs: Int) {
+        self.0 &= rhs.0;
+    }
+}
+
+impl BitOrAssign for Int {
+    #[rustc_mir]
+    fn bitor_assign(&mut self, rhs: Int) {
+        self.0 |= rhs.0;
+    }
+}
+
+impl BitXorAssign for Int {
+    #[rustc_mir]
+    fn bitxor_assign(&mut self, rhs: Int) {
+        self.0 ^= rhs.0;
+    }
+}
+
+impl DivAssign for Int {
+    #[rustc_mir]
+    fn div_assign(&mut self, rhs: Int) {
+        self.0 /= rhs.0;
+    }
+}
+
+impl MulAssign for Int {
+    #[rustc_mir]
+    fn mul_assign(&mut self, rhs: Int) {
+        self.0 *= rhs.0;
+    }
+}
+
+impl RemAssign for Int {
+    #[rustc_mir]
+    fn rem_assign(&mut self, rhs: Int) {
+        self.0 %= rhs.0;
+    }
+}
+
+impl ShlAssign<u8> for Int {
+    #[rustc_mir]
+    fn shl_assign(&mut self, rhs: u8) {
+        self.0 <<= rhs;
+    }
+}
+
+impl ShlAssign<u16> for Int {
+    #[rustc_mir]
+    fn shl_assign(&mut self, rhs: u16) {
+        self.0 <<= rhs;
+    }
+}
+
+impl ShrAssign<u8> for Int {
+    #[rustc_mir]
+    fn shr_assign(&mut self, rhs: u8) {
+        self.0 >>= rhs;
+    }
+}
+
+impl ShrAssign<u16> for Int {
+    #[rustc_mir]
+    fn shr_assign(&mut self, rhs: u16) {
+        self.0 >>= rhs;
+    }
+}
+
+impl SubAssign for Int {
+    #[rustc_mir]
+    fn sub_assign(&mut self, rhs: Int) {
+        self.0 -= rhs.0;
+    }
+}
+
+impl AddAssign<i32> for Slice {
+    #[rustc_mir]
+    fn add_assign(&mut self, rhs: i32) {
+        for lhs in &mut self.0 {
+            *lhs += rhs;
+        }
+    }
+}
diff --git a/src/test/run-pass/mir_autoderef.rs b/src/test/run-pass/mir_autoderef.rs
new file mode 100644
index 00000000000..81712e4569f
--- /dev/null
+++ b/src/test/run-pass/mir_autoderef.rs
@@ -0,0 +1,41 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+use std::ops::{Deref, DerefMut};
+
+pub struct MyRef(u32);
+
+impl Deref for MyRef {
+    type Target = u32;
+    fn deref(&self) -> &u32 { &self.0 }
+}
+
+impl DerefMut for MyRef {
+    fn deref_mut(&mut self) -> &mut u32 { &mut self.0 }
+}
+
+
+#[rustc_mir]
+fn deref(x: &MyRef) -> &u32 {
+    x
+}
+
+#[rustc_mir]
+fn deref_mut(x: &mut MyRef) -> &mut u32 {
+    x
+}
+
+fn main() {
+    let mut r = MyRef(2);
+    assert_eq!(deref(&r) as *const _, &r.0 as *const _);
+    assert_eq!(deref_mut(&mut r) as *mut _, &mut r.0 as *mut _);
+}
diff --git a/src/test/run-pass/mir_struct_with_assoc_ty.rs b/src/test/run-pass/mir_struct_with_assoc_ty.rs
new file mode 100644
index 00000000000..1f75369b94a
--- /dev/null
+++ b/src/test/run-pass/mir_struct_with_assoc_ty.rs
@@ -0,0 +1,41 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+use std::marker::PhantomData;
+
+pub trait DataBind {
+    type Data;
+}
+
+impl<T> DataBind for Global<T> {
+    type Data = T;
+}
+
+pub struct Global<T>(PhantomData<T>);
+
+pub struct Data {
+    pub offsets: <Global<[u32; 2]> as DataBind>::Data,
+}
+
+#[rustc_mir]
+fn create_data() -> Data {
+    let mut d = Data { offsets: [1, 2] };
+    d.offsets[0] = 3;
+    d
+}
+
+
+fn main() {
+    let d = create_data();
+    assert_eq!(d.offsets[0], 3);
+    assert_eq!(d.offsets[1], 2);
+}
diff --git a/src/test/run-pass/mir_trans_calls.rs b/src/test/run-pass/mir_trans_calls.rs
index fc45fbf7278..b8b7ecbf03c 100644
--- a/src/test/run-pass/mir_trans_calls.rs
+++ b/src/test/run-pass/mir_trans_calls.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_attrs)]
+#![feature(rustc_attrs, unboxed_closures, fn_traits)]
 
 #[rustc_mir]
 fn test1(a: isize, b: (i32, i32), c: &[i32]) -> (isize, (i32, i32), &[i32]) {
@@ -117,6 +117,27 @@ fn test_fn_impl(f: &&Fn(i32, i32) -> i32, x: i32, y: i32) -> i32 {
     f(x, y)
 }
 
+#[rustc_mir]
+fn test_fn_direct_call<F>(f: &F, x: i32, y: i32) -> i32
+    where F: Fn(i32, i32) -> i32
+{
+    f.call((x, y))
+}
+
+#[rustc_mir]
+fn test_fn_const_call<F>(f: &F) -> i32
+    where F: Fn(i32, i32) -> i32
+{
+    f.call((100, -1))
+}
+
+#[rustc_mir]
+fn test_fn_nil_call<F>(f: &F) -> i32
+    where F: Fn() -> i32
+{
+    f()
+}
+
 fn main() {
     assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..]));
     assert_eq!(test2(98), 98);
@@ -128,9 +149,14 @@ fn main() {
     assert_eq!(test8(), 2);
     assert_eq!(test9(), 41 + 42 * 43);
 
-    let closure = |x: i32, y: i32| { x + y };
-    assert_eq!(test_closure(&closure, 100, 1), 101);
+    let r = 3;
+    let closure = |x: i32, y: i32| { r*(x + (y*2)) };
+    assert_eq!(test_fn_const_call(&closure), 294);
+    assert_eq!(test_closure(&closure, 100, 1), 306);
     let function_object = &closure as &Fn(i32, i32) -> i32;
-    assert_eq!(test_fn_object(function_object, 100, 2), 102);
-    assert_eq!(test_fn_impl(&function_object, 100, 3), 103);
+    assert_eq!(test_fn_object(function_object, 100, 2), 312);
+    assert_eq!(test_fn_impl(&function_object, 100, 3), 318);
+    assert_eq!(test_fn_direct_call(&closure, 100, 4), 324);
+
+    assert_eq!(test_fn_nil_call(&(|| 42)), 42);
 }
diff --git a/src/test/run-pass/mod_dir_implicit_aux/compiletest-ignore-dir b/src/test/run-pass/mod_dir_implicit_aux/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-pass/mod_dir_implicit_aux/compiletest-ignore-dir
diff --git a/src/test/run-pass/mod_dir_simple/compiletest-ignore-dir b/src/test/run-pass/mod_dir_simple/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-pass/mod_dir_simple/compiletest-ignore-dir
diff --git a/src/test/run-pass/module-polymorphism3-files/compiletest-ignore-dir b/src/test/run-pass/module-polymorphism3-files/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-pass/module-polymorphism3-files/compiletest-ignore-dir
diff --git a/src/test/run-pass/num-wrapping.rs b/src/test/run-pass/num-wrapping.rs
index 33f7b97ef96..faa02c6698e 100644
--- a/src/test/run-pass/num-wrapping.rs
+++ b/src/test/run-pass/num-wrapping.rs
@@ -12,7 +12,7 @@
 //
 // Test std::num::Wrapping<T> for {uN, iN, usize, isize}
 
-#![feature(op_assign_traits, num_bits_bytes, test)]
+#![feature(num_bits_bytes, test)]
 
 extern crate test;
 
diff --git a/src/test/run-pass/privacy-reexport.rs b/src/test/run-pass/privacy-reexport.rs
index d9d107d900b..15c977afe2a 100644
--- a/src/test/run-pass/privacy-reexport.rs
+++ b/src/test/run-pass/privacy-reexport.rs
@@ -15,5 +15,8 @@
 extern crate privacy_reexport;
 
 pub fn main() {
+    // Check that public extern crates are visible to outside crates
+    privacy_reexport::core::cell::Cell::new(0);
+
     privacy_reexport::bar::frob();
 }
diff --git a/src/test/run-pass/reachable-unnameable-items.rs b/src/test/run-pass/reachable-unnameable-items.rs
new file mode 100644
index 00000000000..8a23403359f
--- /dev/null
+++ b/src/test/run-pass/reachable-unnameable-items.rs
@@ -0,0 +1,41 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:reachable-unnameable-items.rs
+
+#![feature(recover)]
+
+extern crate reachable_unnameable_items;
+use reachable_unnameable_items::*;
+
+fn main() {
+    let res1 = function_returning_unnameable_type().method_of_unnameable_type1();
+    let res2 = CONSTANT_OF_UNNAMEABLE_TYPE.method_of_unnameable_type2();
+    let res4 = AliasOfUnnameableType{}.method_of_unnameable_type4();
+    let res5 = function_returning_unnameable_type().inherent_method_returning_unnameable_type().
+                                                    method_of_unnameable_type5();
+    let res6 = function_returning_unnameable_type().trait_method_returning_unnameable_type().
+                                                    method_of_unnameable_type6();
+    let res7 = STATIC.field_of_unnameable_type.method_of_unnameable_type7();
+    let res8 = generic_function::<AliasOfUnnameableType>().method_of_unnameable_type8();
+    let res_enum = NameableVariant.method_of_unnameable_enum();
+    assert_eq!(res1, "Hello1");
+    assert_eq!(res2, "Hello2");
+    assert_eq!(res4, "Hello4");
+    assert_eq!(res5, "Hello5");
+    assert_eq!(res6, "Hello6");
+    assert_eq!(res7, "Hello7");
+    assert_eq!(res8, "Hello8");
+    assert_eq!(res_enum, "HelloEnum");
+
+    let none = None;
+    function_accepting_unnameable_type(none);
+    let _guard = std::panic::recover(|| none.unwrap().method_of_unnameable_type3());
+}
diff --git a/src/test/run-pass/reachable-unnameable-type-alias.rs b/src/test/run-pass/reachable-unnameable-type-alias.rs
new file mode 100644
index 00000000000..5d0c6df3d58
--- /dev/null
+++ b/src/test/run-pass/reachable-unnameable-type-alias.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.
+
+#![feature(staged_api)]
+#![stable(feature = "a", since = "b")]
+
+mod inner_private_module {
+    // UnnameableTypeAlias isn't marked as reachable, so no stability annotation is required here
+    pub type UnnameableTypeAlias = u8;
+}
+
+#[stable(feature = "a", since = "b")]
+pub fn f() -> inner_private_module::UnnameableTypeAlias {
+    0
+}
+
+fn main() {}
diff --git a/src/test/run-pass/signal-alternate-stack-cleanup.rs b/src/test/run-pass/signal-alternate-stack-cleanup.rs
new file mode 100644
index 00000000000..26fa36f0c13
--- /dev/null
+++ b/src/test/run-pass/signal-alternate-stack-cleanup.rs
@@ -0,0 +1,44 @@
+// 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.
+
+// Previously memory for alternate signal stack have been unmapped during
+// main thread exit while still being in use by signal handlers. This test
+// triggers this situation by sending signal from atexit handler.
+//
+// ignore-windows
+
+#![feature(libc)]
+extern crate libc;
+
+use libc::*;
+
+unsafe extern fn signal_handler(signum: c_int, _: *mut siginfo_t, _: *mut c_void) {
+    assert_eq!(signum, SIGWINCH);
+}
+
+extern fn send_signal() {
+    unsafe {
+        raise(SIGWINCH);
+    }
+}
+
+fn main() {
+    unsafe {
+        // Install signal hander that runs on alternate signal stack.
+        let mut action: sigaction = std::mem::zeroed();
+        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
+        action.sa_sigaction = signal_handler as sighandler_t;
+        sigaction(SIGWINCH, &action, std::ptr::null_mut());
+
+        // Send SIGWINCH on exit.
+        atexit(send_signal);
+    }
+}
+
diff --git a/src/test/run-pass/thread-local-extern-static.rs b/src/test/run-pass/thread-local-extern-static.rs
new file mode 100644
index 00000000000..92a95cad0d3
--- /dev/null
+++ b/src/test/run-pass/thread-local-extern-static.rs
@@ -0,0 +1,26 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-windows
+// aux-build:thread-local-extern-static.rs
+
+#![feature(thread_local)]
+#![feature(cfg_target_thread_local)]
+
+extern crate thread_local_extern_static;
+
+extern {
+    #[cfg_attr(target_thread_local, thread_local)]
+    static FOO: u32;
+}
+
+fn main() {
+    assert_eq!(FOO, 3);
+}
diff --git a/src/test/run-pass/write-fmt-errors.rs b/src/test/run-pass/write-fmt-errors.rs
new file mode 100644
index 00000000000..e4439087946
--- /dev/null
+++ b/src/test/run-pass/write-fmt-errors.rs
@@ -0,0 +1,54 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use std::io::{self, Error, Write, sink};
+
+struct ErrorDisplay;
+
+impl fmt::Display for ErrorDisplay {
+    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+        Err(fmt::Error)
+    }
+}
+
+struct ErrorWriter;
+
+const FORMAT_ERROR: io::ErrorKind = io::ErrorKind::Other;
+const WRITER_ERROR: io::ErrorKind = io::ErrorKind::NotConnected;
+
+impl Write for ErrorWriter {
+    fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
+        Err(Error::new(WRITER_ERROR, "not connected"))
+    }
+
+    fn flush(&mut self) -> io::Result<()> { Ok(()) }
+}
+
+fn main() {
+    // Test that the error from the formatter is propagated.
+    let res = write!(sink(), "{} {} {}", 1, ErrorDisplay, "bar");
+    assert!(res.is_err(), "formatter error did not propagate");
+    assert_eq!(res.unwrap_err().kind(), FORMAT_ERROR);
+
+    // Test that an underlying error is propagated
+    let res = write!(ErrorWriter, "abc");
+    assert!(res.is_err(), "writer error did not propagate");
+
+    // Writer error
+    let res = write!(ErrorWriter, "abc {}", ErrorDisplay);
+    assert!(res.is_err(), "writer error did not propagate");
+    assert_eq!(res.unwrap_err().kind(), WRITER_ERROR);
+
+    // Formatter error
+    let res = write!(ErrorWriter, "{} abc", ErrorDisplay);
+    assert!(res.is_err(), "formatter error did not propagate");
+    assert_eq!(res.unwrap_err().kind(), FORMAT_ERROR);
+}
diff --git a/src/test/rustdoc/issue-26995.rs b/src/test/rustdoc/issue-26995.rs
new file mode 100644
index 00000000000..bfb440a1839
--- /dev/null
+++ b/src/test/rustdoc/issue-26995.rs
@@ -0,0 +1,17 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-windows
+// compile-flags: --no-defaults
+
+// @has src/issue_26995/dev/null.html
+// @has issue_26995/null/index.html '//a/@href' '../../src/issue_26995/dev/null.html'
+#[path="/dev/null"]
+pub mod null;
diff --git a/src/test/rustdoc/issue-29584.rs b/src/test/rustdoc/issue-29584.rs
new file mode 100644
index 00000000000..0b5ef7fca8e
--- /dev/null
+++ b/src/test/rustdoc/issue-29584.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.
+
+// aux-build:issue-29584.rs
+// ignore-cross-compile
+
+extern crate issue_29584;
+
+// @has issue_29584/struct.Foo.html
+// @!has - 'impl Bar for'
+pub use issue_29584::Foo;
diff --git a/src/test/rustdoc/issue-31808.rs b/src/test/rustdoc/issue-31808.rs
new file mode 100644
index 00000000000..46be8229d7c
--- /dev/null
+++ b/src/test/rustdoc/issue-31808.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.
+
+#![feature(associated_consts, associated_types)]
+
+// Test that associated item impls on primitive types don't crash rustdoc
+
+pub trait Foo {
+    const BAR: usize;
+    type BAZ;
+}
+
+impl Foo for () {
+    const BAR: usize = 0;
+    type BAZ = usize;
+}
diff --git a/src/test/rustdoc/issue-31899.rs b/src/test/rustdoc/issue-31899.rs
new file mode 100644
index 00000000000..0722dc4e052
--- /dev/null
+++ b/src/test/rustdoc/issue-31899.rs
@@ -0,0 +1,70 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// @has issue_31899/index.html
+// @has - 'Make this line a bit longer.'
+// @!has - 'rust rust-example-rendered'
+// @!has - 'use ndarray::arr2'
+// @!has - 'prohibited'
+
+/// A tuple or fixed size array that can be used to index an array.
+/// Make this line a bit longer.
+///
+/// ```
+/// use ndarray::arr2;
+///
+/// let mut a = arr2(&[[0, 1], [0, 0]]);
+/// a[[1, 1]] = 1;
+/// assert_eq!(a[[0, 1]], 1);
+/// assert_eq!(a[[1, 1]], 1);
+/// ```
+///
+/// **Note** the blanket implementation that's not visible in rustdoc:
+/// `impl<D> NdIndex for D where D: Dimension { ... }`
+pub fn bar() {}
+
+/// Some line
+///
+/// # prohibited
+pub fn foo() {}
+
+/// Some line
+///
+/// 1. prohibited
+/// 2. bar
+pub fn baz() {}
+
+/// Some line
+///
+/// - prohibited
+/// - bar
+pub fn qux() {}
+
+/// Some line
+///
+/// * prohibited
+/// * bar
+pub fn quz() {}
+
+/// Some line
+///
+/// > prohibited
+/// > bar
+pub fn qur() {}
+
+/// Some line
+///
+/// prohibited
+/// =====
+///
+/// Second
+/// ------
+pub fn qut() {}
diff --git a/src/test/rustdoc/src-links/compiletest-ignore-dir b/src/test/rustdoc/src-links/compiletest-ignore-dir
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/rustdoc/src-links/compiletest-ignore-dir