about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiletest/compiletest.rs1
-rw-r--r--src/compiletest/runtest.rs12
-rw-r--r--src/doc/complement-lang-faq.md2
-rw-r--r--src/doc/complement-project-faq.md2
-rw-r--r--src/doc/intro.md101
-rw-r--r--src/doc/not_found.md5
-rw-r--r--src/doc/reference.md117
-rw-r--r--src/doc/rust.css4
-rw-r--r--src/doc/rustdoc.md31
-rw-r--r--src/doc/trpl/README.md6
-rw-r--r--src/doc/trpl/SUMMARY.md2
-rw-r--r--src/doc/trpl/arrays-vectors-and-slices.md14
-rw-r--r--src/doc/trpl/closures.md28
-rw-r--r--src/doc/trpl/comments.md3
-rw-r--r--src/doc/trpl/compound-data-types.md19
-rw-r--r--src/doc/trpl/crates-and-modules.md6
-rw-r--r--src/doc/trpl/error-handling.md20
-rw-r--r--src/doc/trpl/ffi.md115
-rw-r--r--src/doc/trpl/functions.md22
-rw-r--r--src/doc/trpl/generics.md26
-rw-r--r--src/doc/trpl/guessing-game.md126
-rw-r--r--src/doc/trpl/hello-world.md4
-rw-r--r--src/doc/trpl/if.md2
-rw-r--r--src/doc/trpl/iterators.md76
-rw-r--r--src/doc/trpl/looping.md12
-rw-r--r--src/doc/trpl/macros.md53
-rw-r--r--src/doc/trpl/match.md12
-rw-r--r--src/doc/trpl/ownership.md126
-rw-r--r--src/doc/trpl/patterns.md52
-rw-r--r--src/doc/trpl/plugins.md10
-rw-r--r--src/doc/trpl/pointers.md125
-rw-r--r--src/doc/trpl/standard-input.md12
-rw-r--r--src/doc/trpl/testing.md18
-rw-r--r--src/doc/trpl/threads.md (renamed from src/doc/trpl/tasks.md)100
-rw-r--r--src/doc/trpl/traits.md85
-rw-r--r--src/doc/trpl/unsafe.md44
-rw-r--r--src/doc/trpl/variable-bindings.md22
-rw-r--r--src/doc/tutorial.md2
-rw-r--r--src/driver/driver.rs2
-rw-r--r--src/etc/emacs/rust-mode.el5
-rw-r--r--src/etc/vim/syntax/rust.vim12
-rw-r--r--src/grammar/RustLexer.g45
-rw-r--r--src/grammar/verify.rs19
-rw-r--r--src/liballoc/arc.rs18
-rw-r--r--src/liballoc/boxed.rs8
-rw-r--r--src/liballoc/heap.rs3
-rw-r--r--src/liballoc/lib.rs2
-rw-r--r--src/liballoc/rc.rs167
-rw-r--r--src/libarena/lib.rs1
-rw-r--r--src/libcollections/bit.rs8
-rw-r--r--src/libcollections/btree/map.rs13
-rw-r--r--src/libcollections/btree/set.rs2
-rw-r--r--src/libcollections/dlist.rs374
-rw-r--r--src/libcollections/lib.rs5
-rw-r--r--src/libcollections/slice.rs12
-rw-r--r--src/libcollections/str.rs6
-rw-r--r--src/libcollections/string.rs26
-rw-r--r--src/libcollections/vec.rs63
-rw-r--r--src/libcore/atomic.rs385
-rw-r--r--src/libcore/cell.rs6
-rw-r--r--src/libcore/finally.rs8
-rw-r--r--src/libcore/fmt/float.rs2
-rw-r--r--src/libcore/fmt/mod.rs27
-rw-r--r--src/libcore/fmt/rt.rs9
-rw-r--r--src/libcore/hash/mod.rs410
-rw-r--r--src/libcore/intrinsics.rs15
-rw-r--r--src/libcore/iter.rs6
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/macros.rs17
-rw-r--r--src/libcore/marker.rs103
-rw-r--r--src/libcore/num/int.rs7
-rw-r--r--src/libcore/num/isize.rs6
-rw-r--r--src/libcore/num/mod.rs8
-rw-r--r--src/libcore/ops.rs72
-rw-r--r--src/libcore/option.rs1
-rw-r--r--src/libcore/prelude.rs4
-rw-r--r--src/libcore/ptr.rs1
-rw-r--r--src/libcore/result.rs14
-rw-r--r--src/libcore/slice.rs12
-rw-r--r--src/libcore/str/mod.rs6
-rw-r--r--src/libcore/tuple.rs3
-rw-r--r--src/libcoretest/atomic.rs16
-rw-r--r--src/libcoretest/char.rs4
-rw-r--r--src/libcoretest/iter.rs20
-rw-r--r--src/libcoretest/lib.rs1
-rw-r--r--src/libcoretest/mem.rs16
-rw-r--r--src/libflate/lib.rs1
-rw-r--r--src/libfmt_macros/lib.rs5
-rw-r--r--src/libgetopts/lib.rs1
-rw-r--r--src/libgraphviz/lib.rs1
-rw-r--r--src/liblibc/lib.rs47
-rw-r--r--src/liblog/lib.rs1
-rw-r--r--src/librand/lib.rs4
-rw-r--r--src/librbml/io.rs2
-rw-r--r--src/librbml/lib.rs1
-rw-r--r--src/libregex/lib.rs1
-rw-r--r--src/librustc/README.txt2
-rw-r--r--src/librustc/lib.rs4
-rw-r--r--src/librustc/lint/builtin.rs8
-rw-r--r--src/librustc/metadata/creader.rs64
-rw-r--r--src/librustc/metadata/csearch.rs19
-rw-r--r--src/librustc/metadata/cstore.rs11
-rw-r--r--src/librustc/metadata/decoder.rs33
-rw-r--r--src/librustc/metadata/filesearch.rs26
-rw-r--r--src/librustc/metadata/loader.rs47
-rw-r--r--src/librustc/middle/cfg/construct.rs3
-rw-r--r--src/librustc/middle/cfg/graphviz.rs5
-rw-r--r--src/librustc/middle/check_const.rs2
-rw-r--r--src/librustc/middle/check_match.rs2
-rw-r--r--src/librustc/middle/check_static.rs2
-rw-r--r--src/librustc/middle/check_static_recursion.rs2
-rw-r--r--src/librustc/middle/const_eval.rs11
-rw-r--r--src/librustc/middle/effect.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs2
-rw-r--r--src/librustc/middle/infer/mod.rs33
-rw-r--r--src/librustc/middle/liveness.rs14
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/privacy.rs1562
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/middle/recursion_limit.rs4
-rw-r--r--src/librustc/middle/region.rs2
-rw-r--r--src/librustc/middle/subst.rs6
-rw-r--r--src/librustc/middle/traits/error_reporting.rs202
-rw-r--r--src/librustc/middle/traits/mod.rs15
-rw-r--r--src/librustc/middle/traits/select.rs143
-rw-r--r--src/librustc/middle/traits/util.rs5
-rw-r--r--src/librustc/middle/ty.rs111
-rw-r--r--src/librustc/middle/ty_fold.rs14
-rw-r--r--src/librustc/plugin/registry.rs4
-rw-r--r--src/librustc/session/mod.rs58
-rw-r--r--src/librustc/session/search_paths.rs13
-rw-r--r--src/librustc/util/ppaux.rs4
-rw-r--r--src/librustc_back/lib.rs1
-rw-r--r--src/librustc_back/sha2.rs4
-rw-r--r--src/librustc_back/svh.rs2
-rw-r--r--src/librustc_back/target/apple_ios_base.rs9
-rw-r--r--src/librustc_back/target/mod.rs4
-rw-r--r--src/librustc_back/target/powerpc_unknown_linux_gnu.rs26
-rw-r--r--src/librustc_back/target/x86_64_apple_darwin.rs1
-rw-r--r--src/librustc_back/target/x86_64_pc_windows_gnu.rs1
-rw-r--r--src/librustc_back/target/x86_64_unknown_dragonfly.rs1
-rw-r--r--src/librustc_back/target/x86_64_unknown_freebsd.rs1
-rw-r--r--src/librustc_back/target/x86_64_unknown_linux_gnu.rs1
-rw-r--r--src/librustc_bitflags/lib.rs (renamed from src/libstd/bitflags.rs)14
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_driver/driver.rs285
-rw-r--r--src/librustc_driver/lib.rs47
-rw-r--r--src/librustc_driver/pretty.rs56
-rw-r--r--src/librustc_llvm/lib.rs15
-rw-r--r--src/librustc_privacy/lib.rs1599
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs6
-rw-r--r--src/librustc_resolve/lib.rs57
-rw-r--r--src/librustc_trans/back/link.rs8
-rw-r--r--src/librustc_trans/back/lto.rs5
-rw-r--r--src/librustc_trans/back/write.rs6
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/save/mod.rs61
-rw-r--r--src/librustc_trans/save/recorder.rs20
-rw-r--r--src/librustc_trans/trans/_match.rs20
-rw-r--r--src/librustc_trans/trans/asm.rs5
-rw-r--r--src/librustc_trans/trans/base.rs85
-rw-r--r--src/librustc_trans/trans/builder.rs2
-rw-r--r--src/librustc_trans/trans/cabi.rs2
-rw-r--r--src/librustc_trans/trans/cabi_aarch64.rs29
-rw-r--r--src/librustc_trans/trans/cabi_arm.rs40
-rw-r--r--src/librustc_trans/trans/cabi_mips.rs30
-rw-r--r--src/librustc_trans/trans/cabi_powerpc.rs183
-rw-r--r--src/librustc_trans/trans/cabi_x86_64.rs126
-rw-r--r--src/librustc_trans/trans/callee.rs7
-rw-r--r--src/librustc_trans/trans/common.rs16
-rw-r--r--src/librustc_trans/trans/consts.rs2
-rw-r--r--src/librustc_trans/trans/controlflow.rs6
-rw-r--r--src/librustc_trans/trans/debuginfo.rs25
-rw-r--r--src/librustc_trans/trans/expr.rs27
-rw-r--r--src/librustc_trans/trans/foreign.rs45
-rw-r--r--src/librustc_trans/trans/glue.rs17
-rw-r--r--src/librustc_trans/trans/intrinsic.rs13
-rw-r--r--src/librustc_trans/trans/machine.rs11
-rw-r--r--src/librustc_trans/trans/meth.rs19
-rw-r--r--src/librustc_trans/trans/mod.rs1
-rw-r--r--src/librustc_trans/trans/monomorphize.rs1
-rw-r--r--src/librustc_trans/trans/tvec.rs24
-rw-r--r--src/librustc_trans/trans/type_.rs26
-rw-r--r--src/librustc_trans/trans/type_of.rs15
-rw-r--r--src/librustc_typeck/astconv.rs79
-rw-r--r--src/librustc_typeck/check/_match.rs6
-rw-r--r--src/librustc_typeck/check/callee.rs32
-rw-r--r--src/librustc_typeck/check/closure.rs2
-rw-r--r--src/librustc_typeck/check/compare_method.rs413
-rw-r--r--src/librustc_typeck/check/method/mod.rs112
-rw-r--r--src/librustc_typeck/check/method/probe.rs69
-rw-r--r--src/librustc_typeck/check/method/suggest.rs308
-rw-r--r--src/librustc_typeck/check/mod.rs825
-rw-r--r--src/librustc_typeck/check/wf.rs31
-rw-r--r--src/librustc_typeck/coherence/impls.rs48
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustc_typeck/coherence/overlap.rs39
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs23
-rw-r--r--src/librustc_typeck/lib.rs10
-rw-r--r--src/librustdoc/clean/inline.rs9
-rw-r--r--src/librustdoc/clean/mod.rs243
-rw-r--r--src/librustdoc/core.rs7
-rw-r--r--src/librustdoc/html/format.rs63
-rw-r--r--src/librustdoc/html/markdown.rs25
-rw-r--r--src/librustdoc/html/static/playpen.js3
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/librustdoc/markdown.rs1
-rw-r--r--src/librustdoc/test.rs11
-rw-r--r--src/libserialize/json.rs4
-rw-r--r--src/libserialize/lib.rs2
-rw-r--r--src/libstd/collections/hash/map.rs74
-rw-r--r--src/libstd/collections/hash/set.rs30
-rw-r--r--src/libstd/collections/hash/table.rs24
-rw-r--r--src/libstd/fmt.rs11
-rw-r--r--src/libstd/io/buffered.rs60
-rw-r--r--src/libstd/io/comm_adapters.rs2
-rw-r--r--src/libstd/io/fs.rs2
-rw-r--r--src/libstd/io/mem.rs10
-rw-r--r--src/libstd/io/mod.rs33
-rw-r--r--src/libstd/io/net/ip.rs2
-rw-r--r--src/libstd/io/net/pipe.rs2
-rw-r--r--src/libstd/io/net/tcp.rs6
-rw-r--r--src/libstd/io/process.rs2
-rw-r--r--src/libstd/io/test.rs6
-rw-r--r--src/libstd/io/timer.rs4
-rw-r--r--src/libstd/io/util.rs29
-rw-r--r--src/libstd/lib.rs12
-rw-r--r--src/libstd/macros.rs18
-rw-r--r--src/libstd/num/mod.rs42
-rw-r--r--src/libstd/os.rs9
-rw-r--r--src/libstd/path/mod.rs6
-rw-r--r--src/libstd/path/posix.rs6
-rw-r--r--src/libstd/path/windows.rs34
-rw-r--r--src/libstd/rand/mod.rs31
-rw-r--r--src/libstd/rand/os.rs14
-rw-r--r--src/libstd/rt/backtrace.rs2
-rw-r--r--src/libstd/rt/libunwind.rs3
-rw-r--r--src/libstd/rt/unwind.rs22
-rw-r--r--src/libstd/rt/util.rs56
-rw-r--r--src/libstd/sync/condvar.rs133
-rw-r--r--src/libstd/sync/future.rs16
-rw-r--r--src/libstd/sync/mpsc/blocking.rs29
-rw-r--r--src/libstd/sync/mpsc/mod.rs18
-rw-r--r--src/libstd/sync/mpsc/oneshot.rs6
-rw-r--r--src/libstd/sync/mpsc/select.rs28
-rw-r--r--src/libstd/sync/mpsc/shared.rs18
-rw-r--r--src/libstd/sync/mpsc/spsc_queue.rs10
-rw-r--r--src/libstd/sync/mpsc/stream.rs10
-rw-r--r--src/libstd/sync/mpsc/sync.rs6
-rw-r--r--src/libstd/sync/mutex.rs33
-rw-r--r--src/libstd/sync/once.rs10
-rw-r--r--src/libstd/sync/poison.rs17
-rw-r--r--src/libstd/sync/rwlock.rs54
-rw-r--r--src/libstd/sys/common/backtrace.rs4
-rw-r--r--src/libstd/sys/common/stack.rs12
-rw-r--r--src/libstd/sys/common/thread_local.rs6
-rw-r--r--src/libstd/sys/unix/c.rs16
-rw-r--r--src/libstd/sys/unix/condvar.rs56
-rw-r--r--src/libstd/sys/unix/mod.rs1
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs7
-rw-r--r--src/libstd/sys/unix/sync.rs9
-rw-r--r--src/libstd/sys/unix/thread.rs14
-rw-r--r--src/libstd/sys/unix/time.rs124
-rw-r--r--src/libstd/sys/unix/timer.rs2
-rw-r--r--src/libstd/sys/windows/condvar.rs14
-rw-r--r--src/libstd/sys/windows/mod.rs1
-rw-r--r--src/libstd/sys/windows/mutex.rs72
-rw-r--r--src/libstd/sys/windows/os.rs2
-rw-r--r--src/libstd/sys/windows/sync.rs46
-rw-r--r--src/libstd/sys/windows/time.rs50
-rw-r--r--src/libstd/time/mod.rs68
-rw-r--r--src/libsyntax/ast.rs21
-rw-r--r--src/libsyntax/ast_map/mod.rs24
-rw-r--r--src/libsyntax/codemap.rs2
-rw-r--r--src/libsyntax/diagnostic.rs5
-rw-r--r--src/libsyntax/ext/asm.rs6
-rw-r--r--src/libsyntax/ext/base.rs106
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs7
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs53
-rw-r--r--src/libsyntax/ext/deriving/hash.rs22
-rw-r--r--src/libsyntax/ext/expand.rs284
-rw-r--r--src/libsyntax/feature_gate.rs9
-rw-r--r--src/libsyntax/fold.rs93
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/obsolete.rs40
-rw-r--r--src/libsyntax/parse/parser.rs178
-rw-r--r--src/libsyntax/print/pp.rs189
-rw-r--r--src/libsyntax/print/pprust.rs263
-rw-r--r--src/libsyntax/ptr.rs8
-rw-r--r--src/libsyntax/visit.rs18
-rw-r--r--src/libterm/lib.rs1
-rw-r--r--src/libtest/lib.rs9
-rw-r--r--src/libunicode/lib.rs1
-rw-r--r--src/rt/arch/aarch64/morestack.S4
-rw-r--r--src/rt/arch/powerpc/morestack.S18
-rw-r--r--src/rt/arch/powerpc/record_sp.S4
-rw-r--r--src/rustbook/build.rs12
-rw-r--r--src/rustbook/css.rs56
-rw-r--r--src/rustbook/javascript.rs43
-rw-r--r--src/rustbook/main.rs2
-rw-r--r--src/rustllvm/llvm-auto-clean-trigger2
-rw-r--r--src/snapshots.txt9
-rw-r--r--src/test/auxiliary/issue-17718.rs4
-rw-r--r--src/test/auxiliary/issue-21202.rs (renamed from src/test/compile-fail/obsolete-tuple-struct-deref.rs)11
-rw-r--r--src/test/auxiliary/macro_crate_test.rs31
-rw-r--r--src/test/auxiliary/no_method_suggested_traits.rs43
-rw-r--r--src/test/bench/shootout-binarytrees.rs38
-rw-r--r--src/test/bench/shootout-fasta-redux.rs4
-rw-r--r--src/test/bench/shootout-threadring.rs14
-rw-r--r--src/test/compile-fail/array-not-vector.rs14
-rw-r--r--src/test/compile-fail/associated-types-eq-3.rs17
-rw-r--r--src/test/compile-fail/associated-types-path-2.rs10
-rw-r--r--src/test/compile-fail/bad-const-type.rs7
-rw-r--r--src/test/compile-fail/block-must-not-have-result-do.rs8
-rw-r--r--src/test/compile-fail/block-must-not-have-result-res.rs8
-rw-r--r--src/test/compile-fail/block-must-not-have-result-while.rs8
-rw-r--r--src/test/compile-fail/coercion-slice.rs7
-rw-r--r--src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs29
-rw-r--r--src/test/compile-fail/coherence-impls-builtin.rs37
-rw-r--r--src/test/compile-fail/coherence-negative-impls-safe.rs20
-rw-r--r--src/test/compile-fail/coherence-orphan.rs6
-rw-r--r--src/test/compile-fail/const-cast-different-types.rs12
-rw-r--r--src/test/compile-fail/cross-borrow-trait.rs6
-rw-r--r--src/test/compile-fail/destructure-trait-ref.rs21
-rw-r--r--src/test/compile-fail/dst-bad-assign.rs9
-rw-r--r--src/test/compile-fail/dst-bad-coerce1.rs6
-rw-r--r--src/test/compile-fail/dst-bad-coerce4.rs6
-rw-r--r--src/test/compile-fail/explicit-self-lifetime-mismatch.rs10
-rw-r--r--src/test/compile-fail/fail-no-dead-code-core.rs1
-rw-r--r--src/test/compile-fail/feature-gate-simd-ffi.rs26
-rw-r--r--src/test/compile-fail/fn-item-type.rs12
-rw-r--r--src/test/compile-fail/fn-trait-formatting.rs21
-rw-r--r--src/test/compile-fail/fully-qualified-type-name1.rs6
-rw-r--r--src/test/compile-fail/fully-qualified-type-name2.rs6
-rw-r--r--src/test/compile-fail/fully-qualified-type-name4.rs6
-rw-r--r--src/test/compile-fail/generic-type-params-name-repr.rs36
-rw-r--r--src/test/compile-fail/huge-enum.rs4
-rw-r--r--src/test/compile-fail/if-branch-types.rs6
-rw-r--r--src/test/compile-fail/if-without-else-result.rs6
-rw-r--r--src/test/compile-fail/integer-literal-suffix-inference.rs252
-rw-r--r--src/test/compile-fail/integral-variable-unification-error.rs6
-rw-r--r--src/test/compile-fail/issue-10176.rs6
-rw-r--r--src/test/compile-fail/issue-11319.rs6
-rw-r--r--src/test/compile-fail/issue-11771.rs12
-rw-r--r--src/test/compile-fail/issue-12997-2.rs6
-rw-r--r--src/test/compile-fail/issue-13058.rs6
-rw-r--r--src/test/compile-fail/issue-13359.rs12
-rw-r--r--src/test/compile-fail/issue-13466.rs15
-rw-r--r--src/test/compile-fail/issue-13482-2.rs7
-rw-r--r--src/test/compile-fail/issue-13482.rs6
-rw-r--r--src/test/compile-fail/issue-13624.rs13
-rw-r--r--src/test/compile-fail/issue-14091.rs6
-rw-r--r--src/test/compile-fail/issue-14541.rs7
-rw-r--r--src/test/compile-fail/issue-14845.rs12
-rw-r--r--src/test/compile-fail/issue-14853.rs3
-rw-r--r--src/test/compile-fail/issue-15783.rs9
-rw-r--r--src/test/compile-fail/issue-15896.rs7
-rw-r--r--src/test/compile-fail/issue-16338.rs7
-rw-r--r--src/test/compile-fail/issue-16401.rs7
-rw-r--r--src/test/compile-fail/issue-17033.rs6
-rw-r--r--src/test/compile-fail/issue-17283.rs18
-rw-r--r--src/test/compile-fail/issue-17718-static-sync.rs9
-rw-r--r--src/test/compile-fail/issue-17740.rs10
-rw-r--r--src/test/compile-fail/issue-17905.rs5
-rw-r--r--src/test/compile-fail/issue-17913.rs4
-rw-r--r--src/test/compile-fail/issue-17999.rs1
-rw-r--r--src/test/compile-fail/issue-19991.rs6
-rw-r--r--src/test/compile-fail/issue-20831-debruijn.rs49
-rw-r--r--src/test/compile-fail/issue-21045.rs16
-rw-r--r--src/test/compile-fail/issue-21160.rs21
-rw-r--r--src/test/compile-fail/issue-21202.rs25
-rw-r--r--src/test/compile-fail/issue-2611-4.rs3
-rw-r--r--src/test/compile-fail/issue-2951.rs7
-rw-r--r--src/test/compile-fail/issue-3477.rs7
-rw-r--r--src/test/compile-fail/issue-3563.rs9
-rw-r--r--src/test/compile-fail/issue-3680.rs7
-rw-r--r--src/test/compile-fail/issue-4201.rs6
-rw-r--r--src/test/compile-fail/issue-4517.rs7
-rw-r--r--src/test/compile-fail/issue-4968.rs7
-rw-r--r--src/test/compile-fail/issue-5100.rs36
-rw-r--r--src/test/compile-fail/issue-5358-1.rs7
-rw-r--r--src/test/compile-fail/issue-5500.rs6
-rw-r--r--src/test/compile-fail/issue-7013.rs1
-rw-r--r--src/test/compile-fail/issue-7061.rs6
-rw-r--r--src/test/compile-fail/issue-7092.rs6
-rw-r--r--src/test/compile-fail/issue-7867.rs23
-rw-r--r--src/test/compile-fail/issue-8761.rs12
-rw-r--r--src/test/compile-fail/kindck-nonsendable-1.rs1
-rw-r--r--src/test/compile-fail/lint-ctypes.rs1
-rw-r--r--src/test/compile-fail/lint-dead-code-1.rs1
-rw-r--r--src/test/compile-fail/lint-dead-code-3.rs1
-rw-r--r--src/test/compile-fail/lint-dead-code-4.rs1
-rw-r--r--src/test/compile-fail/lint-exceeding-bitshifts.rs1
-rw-r--r--src/test/compile-fail/lint-unused-extern-crate.rs1
-rw-r--r--src/test/compile-fail/lint-uppercase-variables.rs1
-rw-r--r--src/test/compile-fail/liveness-unused.rs1
-rw-r--r--src/test/compile-fail/match-struct.rs7
-rw-r--r--src/test/compile-fail/match-vec-mismatch-2.rs6
-rw-r--r--src/test/compile-fail/method-self-arg-1.rs18
-rw-r--r--src/test/compile-fail/mut-pattern-mismatched.rs10
-rw-r--r--src/test/compile-fail/mutable-enum-indirect.rs11
-rw-r--r--src/test/compile-fail/no-method-suggested-traits.rs62
-rw-r--r--src/test/compile-fail/no-send-res-ports.rs1
-rw-r--r--src/test/compile-fail/no-type-for-node-ice.rs15
-rw-r--r--src/test/compile-fail/no_send-enum.rs11
-rw-r--r--src/test/compile-fail/no_send-rc.rs1
-rw-r--r--src/test/compile-fail/no_send-struct.rs9
-rw-r--r--src/test/compile-fail/no_share-enum.rs11
-rw-r--r--src/test/compile-fail/no_share-rc.rs1
-rw-r--r--src/test/compile-fail/no_share-struct.rs9
-rw-r--r--src/test/compile-fail/noexporttypeexe.rs6
-rw-r--r--src/test/compile-fail/obsolete-tilde.rs21
-rw-r--r--src/test/compile-fail/occurs-check-2.rs6
-rw-r--r--src/test/compile-fail/occurs-check.rs6
-rw-r--r--src/test/compile-fail/on-unimplemented-bad-anno.rs37
-rw-r--r--src/test/compile-fail/on-unimplemented.rs38
-rw-r--r--src/test/compile-fail/pattern-error-continue.rs13
-rw-r--r--src/test/compile-fail/pptypedef.rs12
-rw-r--r--src/test/compile-fail/ptr-coercion.rs15
-rw-r--r--src/test/compile-fail/regions-bound-missing-bound-in-impl.rs12
-rw-r--r--src/test/compile-fail/regions-bounds.rs10
-rw-r--r--src/test/compile-fail/regions-early-bound-error-method.rs8
-rw-r--r--src/test/compile-fail/regions-early-bound-error.rs7
-rw-r--r--src/test/compile-fail/regions-fn-subtyping-return-static.rs7
-rw-r--r--src/test/compile-fail/regions-infer-paramd-indirect.rs5
-rw-r--r--src/test/compile-fail/repeat_count.rs35
-rw-r--r--src/test/compile-fail/shift-various-bad-types.rs6
-rw-r--r--src/test/compile-fail/slightly-nice-generic-literal-messages.rs6
-rw-r--r--src/test/compile-fail/std-uncopyable-atomics.rs4
-rw-r--r--src/test/compile-fail/struct-base-wrong-type.rs24
-rw-r--r--src/test/compile-fail/structure-constructor-type-mismatch.rs16
-rw-r--r--src/test/compile-fail/suppressed-error.rs6
-rw-r--r--src/test/compile-fail/tag-that-dare-not-speak-its-name.rs6
-rw-r--r--src/test/compile-fail/task-rng-isnt-sendable.rs1
-rw-r--r--src/test/compile-fail/terr-in-field.rs6
-rw-r--r--src/test/compile-fail/terr-sorts.rs6
-rw-r--r--src/test/compile-fail/trait-bounds-cant-coerce.rs6
-rw-r--r--src/test/compile-fail/trait-bounds-impl-comparison-1.rs15
-rw-r--r--src/test/compile-fail/trait-bounds-impl-comparison-2.rs2
-rw-r--r--src/test/compile-fail/traits-negative-impls.rs58
-rw-r--r--src/test/compile-fail/tuple-arity-mismatch.rs12
-rw-r--r--src/test/compile-fail/tutorial-suffix-inference-test.rs18
-rw-r--r--src/test/compile-fail/type-mismatch-multiple.rs12
-rw-r--r--src/test/compile-fail/type-parameter-names.rs6
-rw-r--r--src/test/compile-fail/type-params-in-different-spaces-1.rs6
-rw-r--r--src/test/compile-fail/typeck-negative-impls-builtin.rs20
-rw-r--r--src/test/compile-fail/typeck-unsafe-always-share.rs18
-rw-r--r--src/test/compile-fail/typeck_type_placeholder_mismatch.rs12
-rw-r--r--src/test/compile-fail/ufcs-explicit-self-bad.rs11
-rw-r--r--src/test/compile-fail/ufcs-qpath-missing-params.rs (renamed from src/test/compile-fail/vec-matching-obsolete-syntax.rs)13
-rw-r--r--src/test/compile-fail/ufcs-qpath-self-mismatch.rs21
-rw-r--r--src/test/compile-fail/unique-unique-kind.rs1
-rw-r--r--src/test/compile-fail/unsendable-class.rs1
-rw-r--r--src/test/compile-fail/unsupported-cast.rs2
-rw-r--r--src/test/compile-fail/unused-attr.rs1
-rw-r--r--src/test/compile-fail/variadic-ffi.rs16
-rw-r--r--src/test/compile-fail/wrong-mul-method-signature.rs16
-rw-r--r--src/test/debuginfo/limited-debuginfo.rs6
-rw-r--r--src/test/pretty/trait-polarity.rs8
-rw-r--r--src/test/run-make/compiler-lookup-paths-2/Makefile8
-rw-r--r--src/test/run-make/compiler-lookup-paths-2/a.rs (renamed from src/librustc_driver/mod.rs)3
-rw-r--r--src/test/run-make/compiler-lookup-paths-2/b.rs (renamed from src/test/compile-fail/marker-no-share.rs)12
-rw-r--r--src/test/run-make/compiler-lookup-paths-2/c.rs13
-rw-r--r--src/test/run-make/extern-flag-disambiguates/Makefile2
-rw-r--r--src/test/run-make/extern-flag-disambiguates/a.rs4
-rw-r--r--src/test/run-make/extern-flag-disambiguates/b.rs6
-rw-r--r--src/test/run-make/extern-flag-disambiguates/c.rs6
-rw-r--r--src/test/run-make/extern-flag-disambiguates/d.rs2
-rw-r--r--src/test/run-make/graphviz-flowgraph/Makefile2
-rw-r--r--src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot2
-rw-r--r--src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot4
-rw-r--r--src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot4
-rw-r--r--src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot4
-rw-r--r--src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot4
-rw-r--r--src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot2
-rw-r--r--src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot8
-rw-r--r--src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot8
-rw-r--r--src/test/run-make/issue-19371/foo.rs6
-rw-r--r--src/test/run-make/simd-ffi/Makefile33
-rwxr-xr-xsrc/test/run-make/simd-ffi/simd.rs81
-rw-r--r--src/test/run-make/tools.mk2
-rw-r--r--src/test/run-pass-fulldeps/macro-crate.rs26
-rw-r--r--src/test/run-pass/associated-types-enum-field-named.rs43
-rw-r--r--src/test/run-pass/associated-types-enum-field-numbered.rs43
-rw-r--r--src/test/run-pass/associated-types-normalize-unifield-struct.rs32
-rw-r--r--src/test/run-pass/associated-types-projection-in-object-type.rs43
-rw-r--r--src/test/run-pass/associated-types-projection-in-where-clause.rs34
-rw-r--r--src/test/run-pass/associated-types-struct-field-named.rs41
-rw-r--r--src/test/run-pass/associated-types-struct-field-numbered.rs38
-rw-r--r--src/test/run-pass/backtrace.rs17
-rw-r--r--src/test/run-pass/coerce-expect-unsized.rs3
-rw-r--r--src/test/run-pass/coerce-unify-return.rs26
-rw-r--r--src/test/run-pass/coherence-negative-impls-safe.rs (renamed from src/test/compile-fail/marker-no-send.rs)15
-rw-r--r--src/test/run-pass/const-polymorphic-paths.rs30
-rw-r--r--src/test/run-pass/huge-largest-array.rs4
-rw-r--r--src/test/run-pass/ifmt.rs1
-rw-r--r--src/test/run-pass/issue-11958.rs1
-rw-r--r--src/test/run-pass/issue-16530.rs18
-rw-r--r--src/test/run-pass/issue-16671.rs1
-rw-r--r--src/test/run-pass/issue-17503.rs2
-rw-r--r--src/test/run-pass/issue-17718.rs6
-rw-r--r--src/test/run-pass/issue-20575.rs19
-rw-r--r--src/test/run-pass/issue-20676.rs20
-rw-r--r--src/test/run-pass/issue-21058.rs30
-rw-r--r--src/test/run-pass/issue-8898.rs2
-rw-r--r--src/test/run-pass/regions-debruijn-of-object.rs25
-rw-r--r--src/test/run-pass/slice-2.rs4
-rw-r--r--src/test/run-pass/syntax-trait-polarity.rs6
-rw-r--r--src/test/run-pass/tcp-accept-stress.rs4
-rw-r--r--src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs23
-rw-r--r--src/test/run-pass/traits-negative-impls.rs29
-rw-r--r--src/test/run-pass/ufcs-trait-object.rs25
-rw-r--r--src/test/run-pass/unwind-unique.rs2
-rw-r--r--src/test/run-pass/vector-sort-panic-safe.rs28
-rw-r--r--src/test/run-pass/weak-lang-item.rs2
-rw-r--r--src/test/run-pass/where-clause-bounds-inconsistency.rs28
-rw-r--r--src/test/run-pass/zero_sized_subslice_match.rs19
517 files changed, 11147 insertions, 5946 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs
index 802fb05796d..f3514c6e7bc 100644
--- a/src/compiletest/compiletest.rs
+++ b/src/compiletest/compiletest.rs
@@ -13,6 +13,7 @@
 #![feature(slicing_syntax, unboxed_closures)]
 #![feature(box_syntax)]
 #![feature(int_uint)]
+#![allow(unstable)]
 
 #![deny(warnings)]
 
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 5de93c52029..5579479c5e5 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -966,6 +966,16 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
         line.starts_with( prefix )
     }
 
+    // A multi-line error will have followup lines which will always
+    // start with one of these strings.
+    fn continuation( line: &str) -> bool {
+        line.starts_with(" expected") ||
+        line.starts_with("    found") ||
+        //                1234
+        // Should have 4 spaces: see issue 18946
+        line.starts_with("(")
+    }
+
     // Scan and extract our error/warning messages,
     // which look like:
     //    filename:line1:col1: line2:col2: *error:* msg
@@ -981,7 +991,7 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
                        ee.kind,
                        ee.msg,
                        line);
-                if prefix_matches(line, prefixes[i].as_slice()) &&
+                if (prefix_matches(line, prefixes[i].as_slice()) || continuation(line)) &&
                     line.contains(ee.kind.as_slice()) &&
                     line.contains(ee.msg.as_slice()) {
                     found_flags[i] = true;
diff --git a/src/doc/complement-lang-faq.md b/src/doc/complement-lang-faq.md
index a9a9e0858ec..8238dd3a5ba 100644
--- a/src/doc/complement-lang-faq.md
+++ b/src/doc/complement-lang-faq.md
@@ -10,7 +10,7 @@ There aren't many large programs yet. The Rust [compiler][rustc], 60,000+ lines
 
 A research browser engine called [Servo][servo], currently 30,000+ lines across more than a dozen crates, will be exercising a lot of Rust's distinctive type-system and concurrency features, and integrating many native libraries.
 
-[servo]: https://github.com/mozilla/servo
+[servo]: https://github.com/servo/servo
 
 Some examples that demonstrate different aspects of the language:
 
diff --git a/src/doc/complement-project-faq.md b/src/doc/complement-project-faq.md
index 1b463d77693..bb1805d694f 100644
--- a/src/doc/complement-project-faq.md
+++ b/src/doc/complement-project-faq.md
@@ -30,7 +30,7 @@ No. It started as a Graydon Hoare's part-time side project in 2006 and remained
 
 # What will Mozilla use Rust for?
 
-Mozilla intends to use Rust as a platform for prototyping experimental browser architectures. Specifically, the hope is to develop a browser that is more amenable to parallelization than existing ones, while also being less prone to common C++ coding errors that result in security exploits. The name of that project is _[Servo](http://github.com/mozilla/servo)_.
+Mozilla intends to use Rust as a platform for prototyping experimental browser architectures. Specifically, the hope is to develop a browser that is more amenable to parallelization than existing ones, while also being less prone to common C++ coding errors that result in security exploits. The name of that project is _[Servo](http://github.com/servo/servo)_.
 
 # Why a BSD-style permissive license rather than MPL or tri-license?
 
diff --git a/src/doc/intro.md b/src/doc/intro.md
index cb28586d103..3487738467f 100644
--- a/src/doc/intro.md
+++ b/src/doc/intro.md
@@ -5,7 +5,7 @@ accomplishes these goals by being memory safe without using garbage collection.
 
 This introduction will give you a rough idea of what Rust is like, eliding many
 details. It does not require prior experience with systems programming, but you
-may find the syntax easier if you've used a 'curly brace' programming language
+may find the syntax easier if you've used a "curly brace" programming language
 before, like C or JavaScript. The concepts are more important than the syntax,
 so don't worry if you don't get every last detail: you can read [The
 Rust Programming Language](book/index.html) to get a more complete explanation.
@@ -15,7 +15,7 @@ Rust to follow along. If you'd like to anyway, check out [the
 homepage](http://rust-lang.org) for explanation.
 
 To show off Rust, let's talk about how easy it is to get started with Rust.
-Then, we'll talk about Rust's most interesting feature, **ownership**, and
+Then, we'll talk about Rust's most interesting feature, *ownership*, and
 then discuss how it makes concurrency easier to reason about. Finally,
 we'll talk about how Rust breaks down the perceived dichotomy between speed
 and safety.
@@ -57,7 +57,7 @@ version = "0.0.1"
 authors = ["Your Name <you@example.com>"]
 ```
 
-This is called a **manifest**, and it contains all of the metadata that Cargo
+This is called a *manifest*, and it contains all of the metadata that Cargo
 needs to compile your project.
 
 Here's what's in `src/main.rs`:
@@ -68,7 +68,7 @@ fn main() {
 }
 ```
 
-Cargo generated a 'hello world' for us. We'll talk more about the syntax here
+Cargo generated a "Hello World" for us. We'll talk more about the syntax here
 later, but that's what Rust code looks like! Let's compile and run it:
 
 ```{bash}
@@ -106,9 +106,9 @@ use semver::Version;
 
 fn main() {
     assert!(Version::parse("1.2.3") == Ok(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
+        major: 1u64,
+        minor: 2u64,
+        patch: 3u64,
         pre: vec!(),
         build: vec!(),
     }));
@@ -146,8 +146,8 @@ Enough about tools, let's talk code!
 
 # Ownership
 
-Rust's defining feature is 'memory safety without garbage collection.' Let's
-take a moment to talk about what that means. **Memory safety** means that the
+Rust's defining feature is "memory safety without garbage collection". Let's
+take a moment to talk about what that means. *Memory safety* means that the
 programming language eliminates certain kinds of bugs, such as [buffer
 overflows](http://en.wikipedia.org/wiki/Buffer_overflow) and [dangling
 pointers](http://en.wikipedia.org/wiki/Dangling_pointer). These problems occur
@@ -170,7 +170,7 @@ We make an array, `v`, and then call `push` on it. `push` is a method which
 adds an element to the end of an array.
 
 Next, we make a new variable, `x`, that's equal to the first element of
-the array. Simple, but this is where the 'bug' will appear.
+the array. Simple, but this is where the "bug" will appear.
 
 Let's keep going. We then call `push` again, pushing "world" onto the
 end of the array. `v` now is `["Hello", "world"]`.
@@ -222,7 +222,7 @@ its length changes, we may need to allocate more memory. In Ruby, this happens
 as well, we just don't think about it very often. So why does the C++ version
 segfault when we allocate more memory?
 
-The answer is that in the C++ version, `x` is a **reference** to the memory
+The answer is that in the C++ version, `x` is a *reference* to the memory
 location where the first element of the array is stored. But in Ruby, `x` is a
 standalone value, not connected to the underyling array at all. Let's dig into
 the details for a moment. Your program has access to memory, provided to it by
@@ -332,11 +332,11 @@ error: aborting due to previous error
 
 When we try to mutate the array by `push`ing it the second time, Rust throws
 an error. It says that we "cannot borrow v as mutable because it is also
-borrowed as immutable." What's up with "borrowed"?
+borrowed as immutable." What does it mean by "borrowed"?
 
-In Rust, the type system encodes the notion of **ownership**. The variable `v`
-is an "owner" of the vector. When we make a reference to `v`, we let that
-variable (in this case, `x`) 'borrow' it for a while. Just like if you own a
+In Rust, the type system encodes the notion of *ownership*. The variable `v`
+is an *owner* of the vector. When we make a reference to `v`, we let that
+variable (in this case, `x`) *borrow* it for a while. Just like if you own a
 book, and you lend it to me, I'm borrowing the book.
 
 So, when I try to modify the vector with the second call to `push`, I need
@@ -392,22 +392,23 @@ Here's an example of a concurrent Rust program:
 use std::thread::Thread;
 
 fn main() {
-    for _ in range(0u, 10u) {
-        Thread::spawn(move || {
+    let guards: Vec<_> = (0..10).map(|_| {
+        Thread::scoped(|| {
             println!("Hello, world!");
-        });
-    }
+        })
+    }).collect();
 }
 ```
 
-This program creates ten threads, who all print `Hello, world!`. The
-`spawn` function takes one argument, a closure, indicated by the
-double bars `||`. (The `move` keyword indicates that the closure takes
-ownership of any data it uses; we'll have more on the significance of
-this shortly.) This closure is executed in a new thread created by
-`spawn`.
+This program creates ten threads, which all print `Hello, world!`. The `scoped`
+function takes one argument, a closure, indicated by the double bars `||`. This
+closure is executed in a new thread created by `scoped`. The method is called
+`scoped` because it returns a 'join guard', which will automatically join the
+child thread when it goes out of scope. Because we `collect` these guards into
+a `Vec<T>`, and that vector goes out of scope at the end of our program, our
+program will wait for every thread to finish before finishing.
 
-One common form of problem in concurrent programs is a 'data race.'
+One common form of problem in concurrent programs is a *data race*.
 This occurs when two different threads attempt to access the same
 location in memory in a non-synchronized way, where at least one of
 them is a write. If one thread is attempting to read, and one thread
@@ -423,11 +424,11 @@ Let's see an example. This Rust code will not compile:
 use std::thread::Thread;
 
 fn main() {
-    let mut numbers = vec![1i, 2i, 3i];
+    let mut numbers = vec![1is, 2, 3];
 
-    for i in range(0u, 3u) {
+    for i in 0..3 {
         Thread::spawn(move || {
-            for j in range(0, 3) { numbers[j] += 1 }
+            for j in 0..3 { numbers[j] += 1 }
         });
     }
 }
@@ -437,15 +438,15 @@ It gives us this error:
 
 ```text
 6:71 error: capture of moved value: `numbers`
-    for j in range(0, 3) { numbers[j] += 1 }
-               ^~~~~~~
+    for j in 0..3 { numbers[j] += 1 }
+                    ^~~~~~~
 7:50 note: `numbers` moved into closure environment here
     spawn(move || {
-        for j in range(0, 3) { numbers[j] += 1 }
+        for j in 0..3 { numbers[j] += 1 }
     });
 6:79 error: cannot assign to immutable dereference (dereference is implicit, due to indexing)
-        for j in range(0, 3) { numbers[j] += 1 }
-                           ^~~~~~~~~~~~~~~
+        for j in 0..3 { numbers[j] += 1 }
+                        ^~~~~~~~~~~~~~~
 ```
 
 It mentions that "numbers moved into closure environment". Because we
@@ -460,9 +461,9 @@ code tries to make three owners. This may cause a safety problem, so
 Rust disallows it.
 
 What to do here? Rust has two types that helps us: `Arc<T>` and `Mutex<T>`.
-"Arc" stands for "atomically reference counted." In other words, an Arc will
+*Arc* stands for "atomically reference counted". In other words, an Arc will
 keep track of the number of references to something, and not free the
-associated resource until the count is zero. The 'atomic' portion refers to an
+associated resource until the count is zero. The *atomic* portion refers to an
 Arc's usage of concurrency primitives to atomically update the count, making it
 safe across threads. If we use an Arc, we can have our three references. But,
 an Arc does not allow mutable borrows of the data it holds, and we want to
@@ -477,9 +478,9 @@ use std::thread::Thread;
 use std::sync::{Arc,Mutex};
 
 fn main() {
-    let numbers = Arc::new(Mutex::new(vec![1i, 2i, 3i]));
+    let numbers = Arc::new(Mutex::new(vec![1is, 2, 3]));
 
-    for i in range(0u, 3u) {
+    for i in 0..3 {
         let number = numbers.clone();
         Thread::spawn(move || {
             let mut array = number.lock().unwrap();
@@ -525,13 +526,13 @@ give us assurance _at compile time_ that we weren't doing something incorrect
 with regards to concurrency. In order to share ownership, we were forced to be
 explicit and use a mechanism to ensure that it would be properly handled.
 
-# Safety _and_ speed
+# Safety _and_ Speed
 
-Safety and speed are always presented as a continuum. On one hand, you have
-maximum speed, but no safety. On the other, you have absolute safety, with no
-speed. Rust seeks to break out of this mode by introducing safety at compile
-time, ensuring that you haven't done anything wrong, while compiling to the
-same low-level code you'd expect without the safety.
+Safety and speed are always presented as a continuum. At one end of the spectrum,
+you have maximum speed, but no safety. On the other end, you have absolute safety
+with no speed. Rust seeks to break out of this paradigm by introducing safety at
+compile time, ensuring that you haven't done anything wrong, while compiling to
+the same low-level code you'd expect without the safety.
 
 As an example, Rust's ownership system is _entirely_ at compile time. The
 safety check that makes this an error about moved values:
@@ -540,12 +541,12 @@ safety check that makes this an error about moved values:
 use std::thread::Thread;
 
 fn main() {
-    let vec = vec![1i, 2, 3];
+    let vec = vec![1is, 2, 3];
 
-    for i in range(0u, 3) {
+    for i in 0us..3 {
         Thread::spawn(move || {
             println!("{}", vec[i]);
-        }).detach();
+        });
     }
 }
 ```
@@ -556,9 +557,9 @@ you can remove it. As an example, this is a poor way to iterate through
 a vector:
 
 ```{rust}
-let vec = vec![1i, 2, 3];
+let vec = vec![1, 2, 3];
 
-for i in range(0u, vec.len()) {
+for i in 0..vec.len() {
      println!("{}", vec[i]);
 }
 ```
@@ -568,7 +569,7 @@ that we don't try to access an invalid index. However, we can remove this
 while retaining safety. The answer is iterators:
 
 ```{rust}
-let vec = vec![1i, 2, 3];
+let vec = vec![1, 2, 3];
 
 for x in vec.iter() {
     println!("{}", x);
diff --git a/src/doc/not_found.md b/src/doc/not_found.md
index bd4d9591097..c746c5773dd 100644
--- a/src/doc/not_found.md
+++ b/src/doc/not_found.md
@@ -12,6 +12,7 @@ Looks like you've taken a wrong turn.
 Some things that might be helpful to you though:
 
 ## Search
+
 * <form action="https://duckduckgo.com/">
     <input type="text" id="site-search" name="q" size="80"></input>
     <input type="submit" value="Search DuckDuckGo">
@@ -19,10 +20,12 @@ Some things that might be helpful to you though:
 * Rust doc search: <span id="core-search"></span>
 
 ## Reference
+
 * [The Rust official site](http://rust-lang.org)
-* [The Rust reference](http://doc.rust-lang.org/reference.html) (* [PDF](http://doc.rust-lang.org/reference.pdf))
+* [The Rust reference](http://doc.rust-lang.org/reference.html)
 
 ## Docs
+
 * [The standard library](http://doc.rust-lang.org/std/)
 
 <script>
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 2486466c869..a27d6c6e268 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -603,7 +603,7 @@ mod b {
 ```
 
 * Paths starting with the keyword `super` begin resolution relative to the
-  parent module. Each further identifier must resolve to an item
+  parent module. Each further identifier must resolve to an item.
 
 ```rust
 mod a {
@@ -985,7 +985,7 @@ top of [modules](#modules) and [blocks](#blocks).
 
 Use declarations support a number of convenient shortcuts:
 
-* Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`.
+* Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`
 * Simultaneously binding a list of paths differing only in their final element,
   using the glob-like brace syntax `use a::b::{c,d,e,f};`
 * Binding all paths matching a given prefix, using the asterisk wildcard syntax
@@ -1091,7 +1091,7 @@ set of *input* [*slots*](#memory-slots) as parameters, through which the caller
 passes arguments into the function, and an *output* [*slot*](#memory-slots)
 through which the function passes results back to the caller.
 
-A function may also be copied into a first class *value*, in which case the
+A function may also be copied into a first-class *value*, in which case the
 value has the corresponding [*function type*](#function-types), and can be used
 otherwise exactly as a function item (with a minor additional cost of calling
 the function indirectly).
@@ -1224,7 +1224,7 @@ the guarantee that these issues are never caused by safe code.
   * A value other than `false` (0) or `true` (1) in a `bool`
   * A discriminant in an `enum` not included in the type definition
   * A value in a `char` which is a surrogate or above `char::MAX`
-  * non-UTF-8 byte sequences in a `str`
+  * Non-UTF-8 byte sequences in a `str`
 * Unwinding into Rust from foreign code or unwinding from Rust into foreign
   code. Rust's failure system is not compatible with exception handling in
   other languages. Unwinding must be caught and handled at FFI boundaries.
@@ -1413,6 +1413,27 @@ a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 };
 In this example, `Cat` is a _struct-like enum variant_,
 whereas `Dog` is simply called an enum variant.
 
+Enums have a discriminant. You can assign them explicitly:
+
+```
+enum Foo {
+    Bar = 123,
+}
+```
+
+If a discriminant isn't assigned, they start at zero, and add one for each
+variant, in order.
+
+You can cast an enum to get this value:
+
+```
+# enum Foo { Bar = 123 }
+let x = Foo::Bar as u32; // x is now 123u32
+```
+
+This only works as long as none of the variants have data attached. If
+it were `Bar(i32)`, this is disallowed.
+
 ### Constant items
 
 ```{.ebnf .gram}
@@ -1588,7 +1609,6 @@ pointer values (pointing to a type for which an implementation of the given
 trait is in scope) to pointers to the trait name, used as a type.
 
 ```
-# use std::boxed::Box;
 # trait Shape { }
 # impl Shape for int { }
 # let mycircle = 0i;
@@ -1647,7 +1667,6 @@ fn radius_times_area<T: Circle>(c: T) -> f64 {
 Likewise, supertrait methods may also be called on trait objects.
 
 ```{.ignore}
-# use std::boxed::Box;
 # trait Shape { fn area(&self) -> f64; }
 # trait Circle : Shape { fn radius(&self) -> f64; }
 # impl Shape for int { fn area(&self) -> f64 { 0.0 } }
@@ -1827,7 +1846,7 @@ accesses in two cases:
 
 These two cases are surprisingly powerful for creating module hierarchies
 exposing public APIs while hiding internal implementation details. To help
-explain, here's a few use cases and what they would entail.
+explain, here's a few use cases and what they would entail:
 
 * A library developer needs to expose functionality to crates which link
   against their library. As a consequence of the first case, this means that
@@ -1858,7 +1877,7 @@ import/expression is only valid if the destination is in the current visibility
 scope.
 
 Here's an example of a program which exemplifies the three cases outlined
-above.
+above:
 
 ```
 // This module is private, meaning that no external crate can access this
@@ -2117,6 +2136,13 @@ macro scope.
   destructors from being run twice. Destructors might be run multiple times on
   the same object with this attribute.
 - `doc` - Doc comments such as `/// foo` are equivalent to `#[doc = "foo"]`.
+- `rustc_on_unimplemented` - Write a custom note to be shown along with the error
+   when the trait is found to be unimplemented on a type.
+   You may use format arguments like `{T}`, `{A}` to correspond to the
+   types at the point of use corresponding to the type parameters of the
+   trait of the same name. `{Self}` will be replaced with the type that is supposed
+   to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate
+   must be enabled.
 
 ### Conditional compilation
 
@@ -2163,7 +2189,7 @@ arbitrarily complex configurations through nesting.
 The following configurations must be defined by the implementation:
 
 * `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"`
-  `"mips"`, `"arm"`, or `"aarch64"`.
+  `"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`.
 * `target_endian = "..."`. Endianness of the target CPU, either `"little"` or
   `"big"`.
 * `target_family = "..."`. Operating system family of the target, e. g.
@@ -2213,7 +2239,7 @@ mod m1 {
 ```
 
 This example shows how one can use `allow` and `warn` to toggle a particular
-check on and off.
+check on and off:
 
 ```{.ignore}
 #[warn(missing_docs)]
@@ -2235,7 +2261,7 @@ mod m2{
 ```
 
 This example shows how one can use `forbid` to disallow uses of `allow` for
-that lint check.
+that lint check:
 
 ```{.ignore}
 #[forbid(missing_docs)]
@@ -2318,9 +2344,9 @@ These language items are traits:
 * `ord`
   : Elements have a partial ordering.
 * `deref`
-  : `*` can be applied, yielding a reference to another type
+  : `*` can be applied, yielding a reference to another type.
 * `deref_mut`
-  : `*` can be applied, yielding a mutable reference to another type
+  : `*` can be applied, yielding a mutable reference to another type.
 
 These are functions:
 
@@ -2341,7 +2367,7 @@ These are functions:
 * `type_id`
   : The type returned by the `type_id` intrinsic.
 * `unsafe`
-  : A type whose contents can be mutated through an immutable reference
+  : A type whose contents can be mutated through an immutable reference.
 
 #### Marker types
 
@@ -2350,11 +2376,11 @@ These types help drive the compiler's analysis
 * `begin_unwind`
   : ___Needs filling in___
 * `no_copy_bound`
-  : This type does not implement "copy", even if eligible
+  : This type does not implement "copy", even if eligible.
 * `no_send_bound`
-  : This type does not implement "send", even if eligible
+  : This type does not implement "send", even if eligible.
 * `no_sync_bound`
-  : This type does not implement "sync", even if eligible
+  : This type does not implement "sync", even if eligible.
 * `eh_personality`
   : ___Needs filling in___
 * `exchange_free`
@@ -2376,11 +2402,11 @@ These types help drive the compiler's analysis
 * `iterator`
   : ___Needs filling in___
 * `contravariant_lifetime`
-  : The lifetime parameter should be considered contravariant
+  : The lifetime parameter should be considered contravariant.
 * `covariant_lifetime`
-  : The lifetime parameter should be considered covariant
+  : The lifetime parameter should be considered covariant.
 * `invariant_lifetime`
-  : The lifetime parameter should be considered invariant
+  : The lifetime parameter should be considered invariant.
 * `malloc`
   : Allocate memory on the managed heap.
 * `owned_box`
@@ -2390,11 +2416,11 @@ These types help drive the compiler's analysis
 * `start`
   : ___Needs filling in___
 * `contravariant_type`
-  : The type parameter should be considered contravariant
+  : The type parameter should be considered contravariant.
 * `covariant_type`
-  : The type parameter should be considered covariant
+  : The type parameter should be considered covariant.
 * `invariant_type`
-  : The type parameter should be considered invariant
+  : The type parameter should be considered invariant.
 * `ty_desc`
   : ___Needs filling in___
 
@@ -2425,15 +2451,15 @@ There are three different types of inline attributes:
 * `#[inline(always)]` asks the compiler to always perform an inline expansion.
 * `#[inline(never)]` asks the compiler to never perform an inline expansion.
 
-### Deriving
+### Derive
 
-The `deriving` attribute allows certain traits to be automatically implemented
+The `derive` attribute allows certain traits to be automatically implemented
 for data structures. For example, the following will create an `impl` for the
 `PartialEq` and `Clone` traits for `Foo`, the type parameter `T` will be given
 the `PartialEq` or `Clone` constraints for the appropriate `impl`:
 
 ```
-#[deriving(PartialEq, Clone)]
+#[derive(PartialEq, Clone)]
 struct Foo<T> {
     a: int,
     b: T
@@ -2455,7 +2481,7 @@ impl<T: PartialEq> PartialEq for Foo<T> {
 }
 ```
 
-Supported traits for `deriving` are:
+Supported traits for `derive` are:
 
 * Comparison traits: `PartialEq`, `Eq`, `PartialOrd`, `Ord`.
 * Serialization: `Encodable`, `Decodable`. These require `serialize`.
@@ -2921,13 +2947,13 @@ automatically dereferenced to make the field access possible.
 ```{.ebnf .gram}
 array_expr : '[' "mut" ? vec_elems? ']' ;
 
-array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ;
+array_elems : [expr [',' expr]*] | [expr ';' expr] ;
 ```
 
 An [array](#array,-and-slice-types) _expression_ is written by enclosing zero
 or more comma-separated expressions of uniform type in square brackets.
 
-In the `[expr ',' ".." expr]` form, the expression after the `".."` must be a
+In the `[expr ';' expr]` form, the expression after the `';'` must be a
 constant expression that can be evaluated at compile time, such as a
 [literal](#literals) or a [static item](#static-items).
 
@@ -2960,8 +2986,8 @@ _panicked state_.
 
 ### Unary operator expressions
 
-Rust defines six symbolic unary operators. They are all written as prefix
-operators, before the expression they apply to.
+Rust defines three unary operators. They are all written as prefix operators,
+before the expression they apply to.
 
 * `-`
   : Negation. May only be applied to numeric types.
@@ -2979,13 +3005,6 @@ operators, before the expression they apply to.
   : Logical negation. On the boolean type, this flips between `true` and
     `false`. On integer types, this inverts the individual bits in the
     two's complement representation of the value.
-* `box`
-  : [Boxing](#pointer-types) operators. Allocate a box to hold the value they
-    are applied to, and store the value in it. `box` creates a box.
-* `&`
-  : Borrow operator. Returns a reference, pointing to its operand. The operand
-    of a borrow is statically proven to outlive the resulting pointer. If the
-    borrow-checker cannot prove this, it is a compilation error.
 
 ### Binary operator expressions
 
@@ -3219,11 +3238,11 @@ the simplest and least-expensive form (analogous to a ```|| { }``` expression),
 the lambda expression captures its environment by reference, effectively
 borrowing pointers to all outer variables mentioned inside the function.
 Alternately, the compiler may infer that a lambda expression should copy or
-move values (depending on their type.) from the environment into the lambda
+move values (depending on their type) from the environment into the lambda
 expression's captured environment.
 
 In this example, we define a function `ten_times` that takes a higher-order
-function argument, and call it with a lambda expression as an argument.
+function argument, and call it with a lambda expression as an argument:
 
 ```
 fn ten_times<F>(f: F) where F: Fn(int) {
@@ -3661,14 +3680,14 @@ within an object along with one byte past the end.
 The types `char` and `str` hold textual data.
 
 A value of type `char` is a [Unicode scalar value](
-http://www.unicode.org/glossary/#unicode_scalar_value) (ie. a code point that
+http://www.unicode.org/glossary/#unicode_scalar_value) (i.e. a code point that
 is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to
 0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 /
 UTF-32 string.
 
 A value of type `str` is a Unicode string, represented as an array of 8-bit
 unsigned bytes holding a sequence of UTF-8 codepoints. Since `str` is of
-unknown size, it is not a _first class_ type, but can only be instantiated
+unknown size, it is not a _first-class_ type, but can only be instantiated
 through a pointer type, such as `&str` or `String`.
 
 ### Tuple types
@@ -3698,7 +3717,7 @@ assert!(b != "world");
 
 Rust has two different types for a list of items:
 
-* `[T ..N]`, an 'array'
+* `[T; N]`, an 'array'.
 * `&[T]`, a 'slice'.
 
 An array has a fixed size, and can be allocated on either the stack or the
@@ -3710,9 +3729,9 @@ to, it borrows it.
 An example of each kind:
 
 ```{rust}
-let vec: Vec<int>  = vec![1, 2, 3];
-let arr: [int; 3] = [1, 2, 3];
-let s: &[int]      = vec.as_slice();
+let vec: Vec<i32> = vec![1, 2, 3];
+let arr: [i32; 3] = [1, 2, 3];
+let s: &[i32] = vec.as_slice();
 ```
 
 As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
@@ -3792,13 +3811,12 @@ enclosing `enum` or `struct` type itself. Such recursion has restrictions:
 An example of a *recursive* type and its use:
 
 ```
-# use std::boxed::Box;
 enum List<T> {
     Nil,
     Cons(T, Box<List<T>>)
 }
 
-let a: List<int> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
+let a: List<i32> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
 ```
 
 ### Pointer types
@@ -3905,7 +3923,6 @@ implementation of `R`, and the pointer value of `E`.
 An example of an object type:
 
 ```
-# use std::boxed::Box;
 trait Printable {
   fn stringify(&self) -> String;
 }
@@ -4113,7 +4130,6 @@ the type of a box is `std::owned::Box<T>`.
 An example of a box type and value:
 
 ```
-# use std::boxed::Box;
 let x: Box<int> = Box::new(10);
 ```
 
@@ -4123,7 +4139,6 @@ copy of a box to move ownership of the value. After a value has been moved,
 the source location cannot be used unless it is reinitialized.
 
 ```
-# use std::boxed::Box;
 let x: Box<int> = Box::new(10);
 let y = x;
 // attempting to use `x` will result in an error here
diff --git a/src/doc/rust.css b/src/doc/rust.css
index 128d75468e6..3f59f12e74c 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -195,6 +195,7 @@ h5 a:hover {text-decoration: none;}
 
 pre, code {
     font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", monospace;
+    word-wrap: break-word;
 }
 pre {
     border-left: 2px solid #eee;
@@ -204,7 +205,6 @@ pre {
     margin: 20px 0;
     font-size: 13px;
     word-break: break-all;
-    word-wrap: break-word;
 }
 code {
     padding: 0 2px;
@@ -315,6 +315,8 @@ hr {
 table {
     border-collapse: collapse;
     border-spacing: 0;
+    overflow-x: auto;
+    display: block;
 }
 
 table tr.odd {
diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md
index 054552559db..0b686eb76db 100644
--- a/src/doc/rustdoc.md
+++ b/src/doc/rustdoc.md
@@ -198,7 +198,7 @@ Rustdoc also supplies some extra sugar for helping with some tedious
 documentation examples. If a line is prefixed with `# `, then the line
 will not show up in the HTML documentation, but it will be used when
 testing the code block (NB. the space after the `#` is required, so
-that one can still write things like `#[deriving(Eq)]`).
+that one can still write things like `#[derive(Eq)]`).
 
 ~~~md
 ```
@@ -217,6 +217,35 @@ spawn(move || { fib(200); })
 The documentation online would look like `spawn(move || { fib(200); })`, but when
 testing this code, the `fib` function will be included (so it can compile).
 
+Rustdoc will automatically add a `main()` wrapper around your code, and in the right
+place. For example:
+
+```
+/// ```
+/// use std::rc::Rc;
+///
+/// let five = Rc::new(5);
+/// ```
+# fn foo() {}
+```
+
+This will end up testing:
+
+```
+fn main() {
+    use std::rc::Rc;
+    let five = Rc::new(5);
+}
+```
+
+Here's the full algorithm:
+
+1. Given a code block, if it does not contain `fn main`, it is wrapped in `fn main() { your_code }`
+2. Given that result, if it contains no `extern crate` directives but it also
+   contains the name of the crate being tested, then `extern crate <name>` is
+   injected at the top.
+3. Some common `allow` attributes are added for documentation examples at the top.
+
 ## Running tests (advanced)
 
 Running tests often requires some special configuration to filter tests, find
diff --git a/src/doc/trpl/README.md b/src/doc/trpl/README.md
index 67fcb94326c..eb9e2b24ac9 100644
--- a/src/doc/trpl/README.md
+++ b/src/doc/trpl/README.md
@@ -8,7 +8,7 @@ memory safe without using garbage collection.
 "The Rust Programming Language" is split into three sections, which you can
 navigate through the menu on the left.
 
-## Basics
+<h2 class="section-header"><a href="basic.html">Basics</a></h2>
 
 This section is a linear introduction to the basic syntax and semantics of
 Rust. It has individual sections on each part of Rust's syntax, and culminates
@@ -17,7 +17,7 @@ in a small project: a guessing game.
 After reading "Basics," you will have a good foundation to learn more about
 Rust, and can write very simple programs.
 
-## Intermediate
+<h2 class="section-header"><a href="intermediate.html">Intermediate</a></h2>
 
 This section contains individual chapters, which are self-contained. They focus
 on specific topics, and can be read in any order.
@@ -25,7 +25,7 @@ on specific topics, and can be read in any order.
 After reading "Intermediate," you will have a solid understanding of Rust,
 and will be able to understand most Rust code and write more complex programs.
 
-## Advanced
+<h2 class="section-header"><a href="advanced.html">Advanced</a></h2>
 
 In a similar fashion to "Intermediate," this section is full of individual,
 deep-dive chapters, which stand alone and can be read in any order. These
diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md
index 1a61c6d216b..aab03add905 100644
--- a/src/doc/trpl/SUMMARY.md
+++ b/src/doc/trpl/SUMMARY.md
@@ -26,7 +26,7 @@
     * [Iterators](iterators.md)
     * [Generics](generics.md)
     * [Traits](traits.md)
-    * [Tasks](tasks.md)
+    * [Threads](threads.md)
     * [Error Handling](error-handling.md)
 * [III: Advanced Topics](advanced.md)
     * [FFI](ffi.md)
diff --git a/src/doc/trpl/arrays-vectors-and-slices.md b/src/doc/trpl/arrays-vectors-and-slices.md
index 11ced4b9f3c..2df769b3c2c 100644
--- a/src/doc/trpl/arrays-vectors-and-slices.md
+++ b/src/doc/trpl/arrays-vectors-and-slices.md
@@ -5,7 +5,7 @@ things. The most basic is the *array*, a fixed-size list of elements of the
 same type. By default, arrays are immutable.
 
 ```{rust}
-let a = [1, 2, 3];     // a: [i32; 3]
+let a = [1, 2, 3]; // a: [i32; 3]
 let mut m = [1, 2, 3]; // mut m: [i32; 3]
 ```
 
@@ -68,7 +68,7 @@ let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
 
 nums.push(4);
 
-println!("The length of nums is now {}", nums.len());   // Prints 4
+println!("The length of nums is now {}", nums.len()); // Prints 4
 ```
 
 Vectors have many more useful methods.
@@ -82,10 +82,10 @@ arrays:
 
 ```{rust}
 let a = [0, 1, 2, 3, 4];
-let middle = a.slice(1, 4);     // A slice of a: just the elements [1,2,3]
+let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
 
 for e in middle.iter() {
-    println!("{}", e);          // Prints 1, 2, 3
+    println!("{}", e); // Prints 1, 2, 3
 }
 ```
 
@@ -94,6 +94,6 @@ backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover
 generics.
 
 We have now learned all of the most basic Rust concepts. We're ready to start
-building our guessing game, we just need to know one last thing: how to get
-input from the keyboard. You can't have a guessing game without the ability to
-guess!
+building ourselves a guessing game, we just need to know one last thing: how to
+get input from the keyboard. You can't have a guessing game without the ability
+to guess!
diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md
index cec9c1e7cf7..51a0bb69a7c 100644
--- a/src/doc/trpl/closures.md
+++ b/src/doc/trpl/closures.md
@@ -51,7 +51,7 @@ defined. The closure borrows any variables it uses, so this will error:
 
 ```{rust,ignore}
 fn main() {
-    let mut x = 5;
+    let mut x: i32 = 5;
 
     let printer = |&:| { println!("x is: {}", x); };
 
@@ -110,25 +110,27 @@ passing two variables: one is an i32, and one is a function."
 Next, let's look at how `twice` is defined:
 
 ```{rust,ignore}
-fn twice(x: i32, f: |i32| -> i32) -> i32 {
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
 ```
 
 `twice` takes two arguments, `x` and `f`. That's why we called it with two
 arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function,
-though, and that function takes an `i32` and returns an `i32`. Notice
-how the `|i32| -> i32` syntax looks a lot like our definition of `square`
-above, if we added the return type in:
-
-```{rust}
-let square = |&: x: i32| -> i32 { x * x };
-//           |i32|       -> i32
-```
-
-This function takes an `i32` and returns an `i32`.
+though, and that function takes an `i32` and returns an `i32`. This is
+what the requirement `Fn(i32) -> i32` for the type parameter `F` says.
+You might ask yourself: why do we need to introduce a type parameter here?
+That is because in Rust each closure has its own unique type.
+So, not only do closures with different signatures have different types,
+but different closures with the *same* signature have *different* types!
+You can think of it this way: the behaviour of a closure is part of its type.
+And since we want to support many different closures that all take
+an `i32` and return an `i32` we introduced a type parameter that is able
+to represent all these closures. 
 
 This is the most complicated function signature we've seen yet! Give it a read
 a few times until you can see how it works. It takes a teeny bit of practice, and
-then it's easy.
+then it's easy. The good news is that this kind of passing a closure around
+can be very efficient. With all the type information available at compile-time
+the compiler can do wonders.
 
 Finally, `twice` returns an `i32` as well.
 
diff --git a/src/doc/trpl/comments.md b/src/doc/trpl/comments.md
index fe7acaab5fc..3c211b007cf 100644
--- a/src/doc/trpl/comments.md
+++ b/src/doc/trpl/comments.md
@@ -40,7 +40,8 @@ fn hello(name: &str) {
 ```
 
 When writing doc comments, adding sections for any arguments, return values,
-and providing some examples of usage is very, very helpful.
+and providing some examples of usage is very, very helpful. Don't worry about
+the `&str`, we'll get to it soon.
 
 You can use the [`rustdoc`](../rustdoc.html) tool to generate HTML documentation
 from these doc comments.
diff --git a/src/doc/trpl/compound-data-types.md b/src/doc/trpl/compound-data-types.md
index 31d330b4022..0616f094e37 100644
--- a/src/doc/trpl/compound-data-types.md
+++ b/src/doc/trpl/compound-data-types.md
@@ -23,10 +23,10 @@ let x: (i32, &str) = (1, "hello");
 As you can see, the type of a tuple looks just like the tuple, but with each
 position having a type name rather than the value. Careful readers will also
 note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
-You haven't seen `&str` as a type before, and we'll discuss the details of
-strings later. In systems programming languages, strings are a bit more complex
-than in other languages. For now, just read `&str` as a *string slice*, and
-we'll learn more soon.
+You have briefly seen `&str` used as a type before, and we'll discuss the
+details of strings later. In systems programming languages, strings are a bit
+more complex than in other languages. For now, just read `&str` as a *string
+slice*, and we'll learn more soon.
 
 You can access the fields in a tuple through a *destructuring let*. Here's
 an example:
@@ -51,7 +51,7 @@ arity and contained types.
 
 ```rust
 let mut x = (1, 2); // x: (i32, i32)
-let y = (2, 3);     // y: (i32, i32)
+let y = (2, 3); // y: (i32, i32)
 
 x = y;
 ```
@@ -156,7 +156,7 @@ These two will not be equal, even if they have the same values:
 ```{rust}
 # struct Color(i32, i32, i32);
 # struct Point(i32, i32, i32);
-let black  = Color(0, 0, 0);
+let black = Color(0, 0, 0);
 let origin = Point(0, 0, 0);
 ```
 
@@ -182,7 +182,7 @@ and with a struct, we have actual names.
 
 There _is_ one case when a tuple struct is very useful, though, and that's a
 tuple struct with only one element. We call this a *newtype*, because it lets
-you create a new type that's a synonym for another one:
+you create a new type that's similar to another one:
 
 ```{rust}
 struct Inches(i32);
@@ -194,7 +194,8 @@ println!("length is {} inches", integer_length);
 ```
 
 As you can see here, you can extract the inner integer type through a
-destructuring `let`.
+destructuring `let`, as we discussed previously in 'tuples.' In this case, the
+`let Inches(integer_length)` assigns `10` to `integer_length`.
 
 ## Enums
 
@@ -296,7 +297,7 @@ enum StringResult {
 }
 ```
 Where a `StringResult` is either a `StringResult::StringOK`, with the result of
-a computation, or an `StringResult::ErrorReason` with a `String` explaining
+a computation, or a `StringResult::ErrorReason` with a `String` explaining
 what caused the computation to fail. These kinds of `enum`s are actually very
 useful and are even part of the standard library.
 
diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md
index c179a263b35..6c5c14fe311 100644
--- a/src/doc/trpl/crates-and-modules.md
+++ b/src/doc/trpl/crates-and-modules.md
@@ -1,4 +1,4 @@
-% The Rust Crates and Modules Guide
+% Crates and Modules
 
 When a project starts getting large, it's considered a good software
 engineering practice to split it up into a bunch of smaller pieces, and then
@@ -256,7 +256,7 @@ fn goodbye() -> String {
 }
 ```
 
-(This is "Sayoonara", if you're curious.)
+(This is "Sayōnara", if you're curious.)
 
 Now that we have our some functionality in our crate, let's try to use it from
 another crate.
@@ -559,7 +559,7 @@ Also, note that we `pub use`d before we declared our `mod`s. Rust requires that
 This will build and run:
 
 ```bash
-$ cargo build
+$ cargo run
    Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
      Running `target/phrases`
 Hello in English: Hello!
diff --git a/src/doc/trpl/error-handling.md b/src/doc/trpl/error-handling.md
index 6c444b741c5..d66142edf3f 100644
--- a/src/doc/trpl/error-handling.md
+++ b/src/doc/trpl/error-handling.md
@@ -1,6 +1,6 @@
-% Error Handling in Rust
+% Error Handling
 
-> The best-laid plans of mice and men
+> The best-laid plans of mice and men  
 > Often go awry
 >
 > "Tae a Moose", Robert Burns
@@ -60,12 +60,12 @@ fn probability(_: &Event) -> f64 {
 
 fn descriptive_probability(event: Event) -> &'static str {
     match probability(&event) {
-        1.00          => "certain",
-        0.00          => "impossible",
+        1.00 => "certain",
+        0.00 => "impossible",
         0.00 ... 0.25 => "very unlikely",
         0.25 ... 0.50 => "unlikely",
         0.50 ... 0.75 => "likely",
-        0.75 ... 1.00  => "very likely",
+        0.75 ... 1.00 => "very likely",
     }
 }
 
@@ -97,12 +97,12 @@ fn probability(_: &Event) -> f64 {
 
 fn descriptive_probability(event: Event) -> &'static str {
     match probability(&event) {
-        1.00          => "certain",
-        0.00          => "impossible",
+        1.00 => "certain",
+        0.00 => "impossible",
         0.00 ... 0.25 => "very unlikely",
         0.25 ... 0.50 => "unlikely",
         0.50 ... 0.75 => "likely",
-        0.75 ... 1.00  => "very likely",
+        0.75 ... 1.00 => "very likely",
         _ => unreachable!()
     }
 }
@@ -181,7 +181,7 @@ errors that can occur.
 # Non-recoverable errors with `panic!`
 
 In the case of an error that is unexpected and not recoverable, the `panic!`
-macro will induce a panic. This will crash the current task, and give an error:
+macro will induce a panic. This will crash the current thread, and give an error:
 
 ```{rust,ignore}
 panic!("boom");
@@ -190,7 +190,7 @@ panic!("boom");
 gives
 
 ```text
-task '<main>' panicked at 'boom', hello.rs:2
+thread '<main>' panicked at 'boom', hello.rs:2
 ```
 
 when you run it.
diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md
index a65325af7be..640f9cc388e 100644
--- a/src/doc/trpl/ffi.md
+++ b/src/doc/trpl/ffi.md
@@ -1,4 +1,4 @@
-% The Rust Foreign Function Interface Guide
+% Foreign Function Interface
 
 # Introduction
 
@@ -11,7 +11,7 @@ snappy includes a C interface (documented in
 The following is a minimal example of calling a foreign function which will
 compile if snappy is installed:
 
-~~~~no_run
+```no_run
 extern crate libc;
 use libc::size_t;
 
@@ -24,7 +24,7 @@ fn main() {
     let x = unsafe { snappy_max_compressed_length(100) };
     println!("max compressed length of a 100 byte buffer: {}", x);
 }
-~~~~
+```
 
 The `extern` block is a list of function signatures in a foreign library, in
 this case with the platform's C ABI. The `#[link(...)]` attribute is used to
@@ -44,7 +44,7 @@ keeping the binding correct at runtime.
 
 The `extern` block can be extended to cover the entire snappy API:
 
-~~~~no_run
+```no_run
 extern crate libc;
 use libc::{c_int, size_t};
 
@@ -66,7 +66,7 @@ extern {
                                          compressed_length: size_t) -> c_int;
 }
 # fn main() {}
-~~~~
+```
 
 # Creating a safe interface
 
@@ -79,7 +79,7 @@ vectors as pointers to memory. Rust's vectors are guaranteed to be a contiguous
 length is number of elements currently contained, and the capacity is the total size in elements of
 the allocated memory. The length is less than or equal to the capacity.
 
-~~~~
+```
 # extern crate libc;
 # use libc::{c_int, size_t};
 # unsafe fn snappy_validate_compressed_buffer(_: *const u8, _: size_t) -> c_int { 0 }
@@ -89,7 +89,7 @@ pub fn validate_compressed_buffer(src: &[u8]) -> bool {
         snappy_validate_compressed_buffer(src.as_ptr(), src.len() as size_t) == 0
     }
 }
-~~~~
+```
 
 The `validate_compressed_buffer` wrapper above makes use of an `unsafe` block, but it makes the
 guarantee that calling it is safe for all inputs by leaving off `unsafe` from the function
@@ -103,7 +103,7 @@ required capacity to hold the compressed output. The vector can then be passed t
 `snappy_compress` function as an output parameter. An output parameter is also passed to retrieve
 the true length after compression for setting the length.
 
-~~~~
+```
 # extern crate libc;
 # use libc::{size_t, c_int};
 # unsafe fn snappy_compress(a: *const u8, b: size_t, c: *mut u8,
@@ -116,20 +116,20 @@ pub fn compress(src: &[u8]) -> Vec<u8> {
         let psrc = src.as_ptr();
 
         let mut dstlen = snappy_max_compressed_length(srclen);
-        let mut dst = Vec::with_capacity(dstlen as uint);
+        let mut dst = Vec::with_capacity(dstlen as usize);
         let pdst = dst.as_mut_ptr();
 
         snappy_compress(psrc, srclen, pdst, &mut dstlen);
-        dst.set_len(dstlen as uint);
+        dst.set_len(dstlen as usize);
         dst
     }
 }
-~~~~
+```
 
 Decompression is similar, because snappy stores the uncompressed size as part of the compression
 format and `snappy_uncompressed_length` will retrieve the exact buffer size required.
 
-~~~~
+```
 # extern crate libc;
 # use libc::{size_t, c_int};
 # unsafe fn snappy_uncompress(compressed: *const u8,
@@ -148,45 +148,22 @@ pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
         let mut dstlen: size_t = 0;
         snappy_uncompressed_length(psrc, srclen, &mut dstlen);
 
-        let mut dst = Vec::with_capacity(dstlen as uint);
+        let mut dst = Vec::with_capacity(dstlen as usize);
         let pdst = dst.as_mut_ptr();
 
         if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
-            dst.set_len(dstlen as uint);
+            dst.set_len(dstlen as usize);
             Some(dst)
         } else {
             None // SNAPPY_INVALID_INPUT
         }
     }
 }
-~~~~
+```
 
 For reference, the examples used here are also available as an [library on
 GitHub](https://github.com/thestinger/rust-snappy).
 
-# Stack management
-
-Rust tasks by default run on a *large stack*. This is actually implemented as a
-reserving a large segment of the address space and then lazily mapping in pages
-as they are needed. When calling an external C function, the code is invoked on
-the same stack as the rust stack. This means that there is no extra
-stack-switching mechanism in place because it is assumed that the large stack
-for the rust task is plenty for the C function to have.
-
-A planned future improvement (not yet implemented at the time of this writing)
-is to have a guard page at the end of every rust stack. No rust function will
-hit this guard page (due to Rust's usage of LLVM's `__morestack`). The intention
-for this unmapped page is to prevent infinite recursion in C from overflowing
-onto other rust stacks. If the guard page is hit, then the process will be
-terminated with a message saying that the guard page was hit.
-
-For normal external function usage, this all means that there shouldn't be any
-need for any extra effort on a user's perspective. The C stack naturally
-interleaves with the rust stack, and it's "large enough" for both to
-interoperate. If, however, it is determined that a larger stack is necessary,
-there are appropriate functions in the task spawning API to control the size of
-the stack of the task which is spawned.
-
 # Destructors
 
 Foreign libraries often hand off ownership of resources to the calling code.
@@ -208,7 +185,7 @@ A basic example is:
 
 Rust code:
 
-~~~~no_run
+```no_run
 extern fn callback(a: i32) {
     println!("I'm called from C with value {0}", a);
 }
@@ -225,11 +202,11 @@ fn main() {
         trigger_callback(); // Triggers the callback
     }
 }
-~~~~
+```
 
 C code:
 
-~~~~c
+```c
 typedef void (*rust_callback)(int32_t);
 rust_callback cb;
 
@@ -241,7 +218,7 @@ int32_t register_callback(rust_callback callback) {
 void trigger_callback() {
   cb(7); // Will call callback(7) in Rust
 }
-~~~~
+```
 
 In this example Rust's `main()` will call `trigger_callback()` in C,
 which would, in turn, call back to `callback()` in Rust.
@@ -261,9 +238,7 @@ referenced Rust object.
 
 Rust code:
 
-~~~~no_run
-# use std::boxed::Box;
-
+```no_run
 #[repr(C)]
 struct RustObject {
     a: i32,
@@ -294,11 +269,11 @@ fn main() {
         trigger_callback();
     }
 }
-~~~~
+```
 
 C code:
 
-~~~~c
+```c
 typedef void (*rust_callback)(void*, int32_t);
 void* cb_target;
 rust_callback cb;
@@ -312,7 +287,7 @@ int32_t register_callback(void* callback_target, rust_callback callback) {
 void trigger_callback() {
   cb(cb_target, 7); // Will call callback(&rustObject, 7) in Rust
 }
-~~~~
+```
 
 ## Asynchronous callbacks
 
@@ -320,8 +295,7 @@ In the previously given examples the callbacks are invoked as a direct reaction
 to a function call to the external C library.
 The control over the current thread is switched from Rust to C to Rust for the
 execution of the callback, but in the end the callback is executed on the
-same thread (and Rust task) that lead called the function which triggered
-the callback.
+same thread that called the function which triggered the callback.
 
 Things get more complicated when the external library spawns its own threads
 and invokes callbacks from there.
@@ -329,7 +303,7 @@ In these cases access to Rust data structures inside the callbacks is
 especially unsafe and proper synchronization mechanisms must be used.
 Besides classical synchronization mechanisms like mutexes, one possibility in
 Rust is to use channels (in `std::comm`) to forward data from the C thread
-that invoked the callback into a Rust task.
+that invoked the callback into a Rust thread.
 
 If an asynchronous callback targets a special object in the Rust address space
 it is also absolutely necessary that no more callbacks are performed by the
@@ -392,13 +366,13 @@ the `link_args` attribute. This attribute is applied to `extern` blocks and
 specifies raw flags which need to get passed to the linker when producing an
 artifact. An example usage would be:
 
-~~~ no_run
+``` no_run
 #![feature(link_args)]
 
 #[link_args = "-foo -bar -baz"]
 extern {}
 # fn main() {}
-~~~
+```
 
 Note that this feature is currently hidden behind the `feature(link_args)` gate
 because this is not a sanctioned way of performing linking. Right now rustc
@@ -419,9 +393,9 @@ the compiler that the unsafety does not leak out of the block.
 Unsafe functions, on the other hand, advertise it to the world. An unsafe function is written like
 this:
 
-~~~~
+```
 unsafe fn kaboom(ptr: *const int) -> int { *ptr }
-~~~~
+```
 
 This function can only be called from an `unsafe` block or another `unsafe` function.
 
@@ -431,7 +405,7 @@ Foreign APIs often export a global variable which could do something like track
 global state. In order to access these variables, you declare them in `extern`
 blocks with the `static` keyword:
 
-~~~no_run
+```no_run
 extern crate libc;
 
 #[link(name = "readline")]
@@ -443,13 +417,13 @@ fn main() {
     println!("You have readline version {} installed.",
              rl_readline_version as int);
 }
-~~~
+```
 
 Alternatively, you may need to alter global state provided by a foreign
 interface. To do this, statics can be declared with `mut` so rust can mutate
 them.
 
-~~~no_run
+```no_run
 extern crate libc;
 
 use std::ffi::CString;
@@ -466,7 +440,7 @@ fn main() {
     // get a line, process it
     unsafe { rl_prompt = ptr::null(); }
 }
-~~~
+```
 
 # Foreign calling conventions
 
@@ -474,7 +448,7 @@ Most foreign code exposes a C ABI, and Rust uses the platform's C calling conven
 calling foreign functions. Some foreign functions, most notably the Windows API, use other calling
 conventions. Rust provides a way to tell the compiler which convention to use:
 
-~~~~
+```
 extern crate libc;
 
 #[cfg(all(target_os = "win32", target_arch = "x86"))]
@@ -484,7 +458,7 @@ extern "stdcall" {
     fn SetEnvironmentVariableA(n: *const u8, v: *const u8) -> libc::c_int;
 }
 # fn main() { }
-~~~~
+```
 
 This applies to the entire `extern` block. The list of supported ABI constraints
 are:
@@ -544,3 +518,22 @@ with one of the non-nullable types, it is represented as a single pointer,
 and the non-data variant is represented as the null pointer. So
 `Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
 function pointer using the C ABI.
+
+# Calling Rust code from C
+
+You may wish to compile Rust code in a way so that it can be called from C. This is
+fairly easy, but requires a few things:
+
+```
+#[no_mangle]
+pub extern fn hello_rust() -> *const u8 {
+    "Hello, world!\0".as_ptr()
+}
+# fn main() {}
+```
+
+The `extern` makes this function adhere to the C calling convention, as
+discussed above in "[Foreign Calling
+Conventions](guide-ffi.html#foreign-calling-conventions)". The `no_mangle`
+attribute turns off Rust's name mangling, so that it is easier to link to.
+
diff --git a/src/doc/trpl/functions.md b/src/doc/trpl/functions.md
index 2e32fdfa794..d0ecb606795 100644
--- a/src/doc/trpl/functions.md
+++ b/src/doc/trpl/functions.md
@@ -59,7 +59,7 @@ Unlike `let`, you _must_ declare the types of function arguments. This does
 not work:
 
 ```{ignore}
-fn print_number(x, y) {
+fn print_sum(x, y) {
     println!("x is: {}", x + y);
 }
 ```
@@ -67,7 +67,7 @@ fn print_number(x, y) {
 You get this error:
 
 ```text
-hello.rs:5:18: 5:19 error: expected `:` but found `,`
+hello.rs:5:18: 5:19 expected one of `!`, `:`, or `@`, found `)`
 hello.rs:5 fn print_number(x, y) {
 ```
 
@@ -142,5 +142,23 @@ fn foo(x: i32) -> i32 {
 }
 ```
 
+The previous definition without `return` may look a bit strange if you haven't
+worked in an expression-based language before, but it becomes intuitive over
+time. If this were production code, we wouldn't write it in that way anyway,
+we'd write this:
+
+```rust
+fn foo(x: i32) -> i32 {
+    if x < 5 {
+        x
+    } else {
+        x + 1
+    }
+}
+```
+
+Because `if` is an expression, and it's the only expression in this function,
+the value will be the result of the `if`.
+
 There are some additional ways to define functions, but they involve features
 that we haven't learned about yet, so let's just leave it at that for now.
diff --git a/src/doc/trpl/generics.md b/src/doc/trpl/generics.md
index 402f36cd74b..74cb4530935 100644
--- a/src/doc/trpl/generics.md
+++ b/src/doc/trpl/generics.md
@@ -5,7 +5,7 @@ multiple types of arguments. For example, remember our `OptionalInt` type?
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 ```
@@ -40,26 +40,26 @@ we substitute that type for the same type used in the generic. Here's an
 example of using `Option<T>`, with some extra type annotations:
 
 ```{rust}
-let x: Option<int> = Some(5i);
+let x: Option<i32> = Some(5);
 ```
 
-In the type declaration, we say `Option<int>`. Note how similar this looks to
-`Option<T>`. So, in this particular `Option`, `T` has the value of `int`. On
-the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5i`.
-Since that's an `int`, the two sides match, and Rust is happy. If they didn't
+In the type declaration, we say `Option<i32>`. Note how similar this looks to
+`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
+the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`.
+Since that's an `i32`, the two sides match, and Rust is happy. If they didn't
 match, we'd get an error:
 
 ```{rust,ignore}
-let x: Option<f64> = Some(5i);
-// error: mismatched types: expected `core::option::Option<f64>`
-// but found `core::option::Option<int>` (expected f64 but found int)
+let x: Option<f64> = Some(5);
+// error: mismatched types: expected `core::option::Option<f64>`,
+// found `core::option::Option<_>` (expected f64 but found integral variable)
 ```
 
 That doesn't mean we can't make `Option<T>`s that hold an `f64`! They just have to
 match up:
 
 ```{rust}
-let x: Option<int> = Some(5i);
+let x: Option<i32> = Some(5);
 let y: Option<f64> = Some(5.0f64);
 ```
 
@@ -88,9 +88,9 @@ enum Result<H, N> {
 if we wanted to. Convention says that the first generic parameter should be
 `T`, for 'type,' and that we use `E` for 'error.' Rust doesn't care, however.
 
-The `Result<T, E>` type is intended to
-be used to return the result of a computation, and to have the ability to
-return an error if it didn't work out. Here's an example:
+The `Result<T, E>` type is intended to be used to return the result of a
+computation, and to have the ability to return an error if it didn't work out.
+Here's an example:
 
 ```{rust}
 let x: Result<f64, String> = Ok(2.3f64);
diff --git a/src/doc/trpl/guessing-game.md b/src/doc/trpl/guessing-game.md
index 16bd1e347b7..6f67c88f2c0 100644
--- a/src/doc/trpl/guessing-game.md
+++ b/src/doc/trpl/guessing-game.md
@@ -239,7 +239,7 @@ use std::rand;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -283,7 +283,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -297,9 +297,9 @@ fn main() {
     println!("You guessed: {}", input);
 
     match cmp(input, secret_number) {
-        Ordering::Less    => println!("Too small!"),
+        Ordering::Less => println!("Too small!"),
         Ordering::Greater => println!("Too big!"),
-        Ordering::Equal   => println!("You win!"),
+        Ordering::Equal => println!("You win!"),
     }
 }
 
@@ -318,7 +318,7 @@ $ cargo build
 src/main.rs:20:15: 20:20 error: mismatched types: expected `i32` but found `collections::string::String` (expected i32 but found struct collections::string::String)
 src/main.rs:20     match cmp(input, secret_number) {
                              ^~~~~
-src/main.rs:20:22: 20:35 error: mismatched types: expected `i32` but found `uint` (expected i32 but found uint)
+src/main.rs:20:22: 20:35 error: mismatched types: expected `i32` but found `u32` (expected i32 but found u32)
 src/main.rs:20     match cmp(input, secret_number) {
                                     ^~~~~~~~~~~~~
 error: aborting due to 2 previous errors
@@ -328,7 +328,7 @@ This often happens when writing Rust programs, and is one of Rust's greatest
 strengths. You try out some code, see if it compiles, and Rust tells you that
 you've done something wrong. In this case, our `cmp` function works on integers,
 but we've given it unsigned integers. In this case, the fix is easy, because
-we wrote the `cmp` function! Let's change it to take `uint`s:
+we wrote the `cmp` function! Let's change it to take `u32`s:
 
 ```{rust,ignore}
 use std::io;
@@ -338,7 +338,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -352,13 +352,13 @@ fn main() {
     println!("You guessed: {}", input);
 
     match cmp(input, secret_number) {
-        Ordering::Less    => println!("Too small!"),
+        Ordering::Less => println!("Too small!"),
         Ordering::Greater => println!("Too big!"),
-        Ordering::Equal   => println!("You win!"),
+        Ordering::Equal => println!("You win!"),
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -370,13 +370,13 @@ And try compiling again:
 ```bash
 $ cargo build
    Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:20:15: 20:20 error: mismatched types: expected `uint` but found `collections::string::String` (expected uint but found struct collections::string::String)
+src/main.rs:20:15: 20:20 error: mismatched types: expected `u32` but found `collections::string::String` (expected u32 but found struct collections::string::String)
 src/main.rs:20     match cmp(input, secret_number) {
                              ^~~~~
 error: aborting due to previous error
 ```
 
-This error is similar to the last one: we expected to get a `uint`, but we got
+This error is similar to the last one: we expected to get a `u32`, but we got
 a `String` instead! That's because our `input` variable is coming from the
 standard input, and you can guess anything. Try it:
 
@@ -393,14 +393,14 @@ Oops! Also, you'll note that we just ran our program even though it didn't compi
 This works because the older version we did successfully compile was still lying
 around. Gotta be careful!
 
-Anyway, we have a `String`, but we need a `uint`. What to do? Well, there's
+Anyway, we have a `String`, but we need a `u32`. What to do? Well, there's
 a function for that:
 
 ```{rust,ignore}
 let input = io::stdin().read_line()
                        .ok()
                        .expect("Failed to read line");
-let input_num: Option<uint> = input.parse();
+let input_num: Option<u32> = input.parse();
 ```
 
 The `parse` function takes in a `&str` value and converts it into something.
@@ -408,22 +408,22 @@ We tell it what kind of something with a type hint. Remember our type hint with
 `random()`? It looked like this:
 
 ```{rust,ignore}
-rand::random::<uint>();
+rand::random::<u32>();
 ```
 
 There's an alternate way of providing a hint too, and that's declaring the type
 in a `let`:
 
 ```{rust,ignore}
-let x: uint = rand::random();
+let x: u32 = rand::random();
 ```
 
-In this case, we say `x` is a `uint` explicitly, so Rust is able to properly
+In this case, we say `x` is a `u32` explicitly, so Rust is able to properly
 tell `random()` what to generate. In a similar fashion, both of these work:
 
 ```{rust,ignore}
-let input_num = "5".parse::<uint>();         // input_num: Option<uint>
-let input_num: Option<uint> = "5".parse();   // input_num: Option<uint>
+let input_num = "5".parse::<u32>(); // input_num: Option<u32>
+let input_num: Option<u32> = "5".parse(); // input_num: Option<u32>
 ```
 
 Anyway, with us now converting our input to a number, our code looks like this:
@@ -436,7 +436,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -445,18 +445,18 @@ fn main() {
     let input = io::stdin().read_line()
                            .ok()
                            .expect("Failed to read line");
-    let input_num: Option<uint> = input.parse();
+    let input_num: Option<u32> = input.parse();
 
     println!("You guessed: {}", input_num);
 
     match cmp(input_num, secret_number) {
-        Ordering::Less    => println!("Too small!"),
+        Ordering::Less => println!("Too small!"),
         Ordering::Greater => println!("Too big!"),
-        Ordering::Equal   => println!("You win!"),
+        Ordering::Equal => println!("You win!"),
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -468,13 +468,13 @@ Let's try it out!
 ```bash
 $ cargo build
    Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:22:15: 22:24 error: mismatched types: expected `uint` but found `core::option::Option<uint>` (expected uint but found enum core::option::Option)
+src/main.rs:22:15: 22:24 error: mismatched types: expected `u32` but found `core::option::Option<u32>` (expected u32 but found enum core::option::Option)
 src/main.rs:22     match cmp(input_num, secret_number) {
                              ^~~~~~~~~
 error: aborting due to previous error
 ```
 
-Oh yeah! Our `input_num` has the type `Option<uint>`, rather than `uint`. We
+Oh yeah! Our `input_num` has the type `Option<u32>`, rather than `u32`. We
 need to unwrap the Option. If you remember from before, `match` is a great way
 to do that. Try this code:
 
@@ -486,7 +486,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -495,11 +495,11 @@ fn main() {
     let input = io::stdin().read_line()
                            .ok()
                            .expect("Failed to read line");
-    let input_num: Option<uint> = input.parse();
+    let input_num: Option<u32> = input.parse();
 
     let num = match input_num {
         Some(num) => num,
-        None      => {
+        None => {
             println!("Please input a number!");
             return;
         }
@@ -509,20 +509,20 @@ fn main() {
     println!("You guessed: {}", num);
 
     match cmp(num, secret_number) {
-        Ordering::Less    => println!("Too small!"),
+        Ordering::Less => println!("Too small!"),
         Ordering::Greater => println!("Too big!"),
-        Ordering::Equal   => println!("You win!"),
+        Ordering::Equal => println!("You win!"),
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
 }
 ```
 
-We use a `match` to either give us the `uint` inside of the `Option`, or else
+We use a `match` to either give us the `u32` inside of the `Option`, or else
 print an error message and return. Let's give this a shot:
 
 ```bash
@@ -553,7 +553,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -562,11 +562,11 @@ fn main() {
     let input = io::stdin().read_line()
                            .ok()
                            .expect("Failed to read line");
-    let input_num: Option<uint> = input.trim().parse();
+    let input_num: Option<u32> = input.trim().parse();
 
     let num = match input_num {
         Some(num) => num,
-        None      => {
+        None => {
             println!("Please input a number!");
             return;
         }
@@ -576,13 +576,13 @@ fn main() {
     println!("You guessed: {}", num);
 
     match cmp(num, secret_number) {
-        Ordering::Less    => println!("Too small!"),
+        Ordering::Less => println!("Too small!"),
         Ordering::Greater => println!("Too big!"),
-        Ordering::Equal   => println!("You win!"),
+        Ordering::Equal => println!("You win!"),
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -627,7 +627,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -638,11 +638,11 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
-            None      => {
+            None => {
                 println!("Please input a number!");
                 return;
             }
@@ -652,14 +652,14 @@ fn main() {
         println!("You guessed: {}", num);
 
         match cmp(num, secret_number) {
-            Ordering::Less    => println!("Too small!"),
+            Ordering::Less => println!("Too small!"),
             Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => println!("You win!"),
+            Ordering::Equal => println!("You win!"),
         }
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -703,7 +703,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -714,11 +714,11 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
-            None      => {
+            None => {
                 println!("Please input a number!");
                 return;
             }
@@ -728,9 +728,9 @@ fn main() {
         println!("You guessed: {}", num);
 
         match cmp(num, secret_number) {
-            Ordering::Less    => println!("Too small!"),
+            Ordering::Less => println!("Too small!"),
             Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => {
+            Ordering::Equal => {
                 println!("You win!");
                 return;
             },
@@ -738,7 +738,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -759,7 +759,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -770,11 +770,11 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
-            None      => {
+            None => {
                 println!("Please input a number!");
                 continue;
             }
@@ -784,9 +784,9 @@ fn main() {
         println!("You guessed: {}", num);
 
         match cmp(num, secret_number) {
-            Ordering::Less    => println!("Too small!"),
+            Ordering::Less => println!("Too small!"),
             Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => {
+            Ordering::Equal => {
                 println!("You win!");
                 return;
             },
@@ -794,7 +794,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -838,7 +838,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     loop {
 
@@ -847,11 +847,11 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
-            None      => {
+            None => {
                 println!("Please input a number!");
                 continue;
             }
@@ -861,9 +861,9 @@ fn main() {
         println!("You guessed: {}", num);
 
         match cmp(num, secret_number) {
-            Ordering::Less    => println!("Too small!"),
+            Ordering::Less => println!("Too small!"),
             Ordering::Greater => println!("Too big!"),
-            Ordering::Equal   => {
+            Ordering::Equal => {
                 println!("You win!");
                 return;
             },
@@ -871,7 +871,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
diff --git a/src/doc/trpl/hello-world.md b/src/doc/trpl/hello-world.md
index 3cb14df1210..640f0109b06 100644
--- a/src/doc/trpl/hello-world.md
+++ b/src/doc/trpl/hello-world.md
@@ -71,8 +71,8 @@ These lines define a *function* in Rust. The `main` function is special:
 it's the beginning of every Rust program. The first line says "I'm declaring a
 function named `main`, which takes no arguments and returns nothing." If there
 were arguments, they would go inside the parentheses (`(` and `)`), and because
-we aren't returning anything from this function, we've dropped that notation
-entirely.  We'll get to it later.
+we aren't returning anything from this function, we can omit the return type
+entirely. We'll get to it later.
 
 You'll also note that the function is wrapped in curly braces (`{` and `}`).
 Rust requires these around all function bodies. It is also considered good
diff --git a/src/doc/trpl/if.md b/src/doc/trpl/if.md
index 8c9d89652b6..ea1da167458 100644
--- a/src/doc/trpl/if.md
+++ b/src/doc/trpl/if.md
@@ -126,7 +126,7 @@ let y: i32 = if x == 5 { 10; } else { 15; };
 Note the semicolons after the 10 and 15. Rust will give us the following error:
 
 ```text
-error: mismatched types: expected `i32` but found `()` (expected i32 but found ())
+error: mismatched types: expected `i32`, found `()` (expected i32, found ())
 ```
 
 We expected an integer, but we got `()`. `()` is pronounced *unit*, and is a
diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md
index 8312f762c11..75b3f8b06fc 100644
--- a/src/doc/trpl/iterators.md
+++ b/src/doc/trpl/iterators.md
@@ -5,7 +5,7 @@ Let's talk about loops.
 Remember Rust's `for` loop? Here's an example:
 
 ```{rust}
-for x in range(0i, 10i) {
+for x in range(0, 10) {
     println!("{}", x);
 }
 ```
@@ -17,7 +17,7 @@ call the `.next()` method on repeatedly, and it gives us a sequence of things.
 Like this:
 
 ```{rust}
-let mut range = range(0i, 10i);
+let mut range = range(0, 10);
 
 loop {
     match range.next() {
@@ -32,8 +32,8 @@ loop {
 We make a mutable binding to the return value of `range`, which is our iterator.
 We then `loop`, with an inner `match`. This `match` is used on the result of
 `range.next()`, which gives us a reference to the next value of the iterator.
-`next` returns an `Option<int>`, in this case, which will be `Some(int)` when
-we have a value and `None` once we run out. If we get `Some(int)`, we print it
+`next` returns an `Option<i32>`, in this case, which will be `Some(i32)` when
+we have a value and `None` once we run out. If we get `Some(i32)`, we print it
 out, and if we get `None`, we `break` out of the loop.
 
 This code sample is basically the same as our `for` loop version. The `for`
@@ -50,9 +50,9 @@ primitive. For example, if you needed to iterate over the contents of
 a vector, you may be tempted to write this:
 
 ```{rust}
-let nums = vec![1i, 2i, 3i];
+let nums = vec![1, 2, 3];
 
-for i in range(0u, nums.len()) {
+for i in range(0, nums.len()) {
     println!("{}", nums[i]);
 }
 ```
@@ -62,7 +62,7 @@ vectors returns an iterator which iterates through a reference to each element
 of the vector in turn. So write this:
 
 ```{rust}
-let nums = vec![1i, 2i, 3i];
+let nums = vec![1, 2, 3];
 
 for num in nums.iter() {
     println!("{}", num);
@@ -79,12 +79,12 @@ very common with iterators: we can ignore unnecessary bounds checks, but still
 know that we're safe.
 
 There's another detail here that's not 100% clear because of how `println!`
-works. `num` is actually of type `&int`. That is, it's a reference to an `int`,
-not an `int` itself. `println!` handles the dereferencing for us, so we don't
+works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
+not an `i32` itself. `println!` handles the dereferencing for us, so we don't
 see it. This code works fine too:
 
 ```{rust}
-let nums = vec![1i, 2i, 3i];
+let nums = vec![1, 2, 3];
 
 for num in nums.iter() {
     println!("{}", *num);
@@ -118,7 +118,7 @@ The most common consumer is `collect()`. This code doesn't quite compile,
 but it shows the intention:
 
 ```{rust,ignore}
-let one_to_one_hundred = range(1i, 101i).collect();
+let one_to_one_hundred = range(1, 101).collect();
 ```
 
 As you can see, we call `collect()` on our iterator. `collect()` takes
@@ -128,7 +128,7 @@ type of things you want to collect, and so you need to let it know.
 Here's the version that does compile:
 
 ```{rust}
-let one_to_one_hundred = range(1i, 101i).collect::<Vec<int>>();
+let one_to_one_hundred = range(1, 101).collect::<Vec<i32>>();
 ```
 
 If you remember, the `::<>` syntax allows us to give a type hint,
@@ -138,12 +138,12 @@ and so we tell it that we want a vector of integers.
 is one:
 
 ```{rust}
-let greater_than_forty_two = range(0i, 100i)
+let greater_than_forty_two = range(0, 100)
                              .find(|x| *x > 42);
 
 match greater_than_forty_two {
     Some(_) => println!("We got some numbers!"),
-    None    => println!("No numbers found :("),
+    None => println!("No numbers found :("),
 }
 ```
 
@@ -155,8 +155,8 @@ element, `find` returns an `Option` rather than the element itself.
 Another important consumer is `fold`. Here's what it looks like:
 
 ```{rust}
-let sum = range(1i, 4i)
-              .fold(0i, |sum, x| sum + x);
+let sum = range(1, 4)
+              .fold(0, |sum, x| sum + x);
 ```
 
 `fold()` is a consumer that looks like this:
@@ -172,24 +172,24 @@ in this iterator:
 
 | base | accumulator | element | closure result |
 |------|-------------|---------|----------------|
-| 0i   | 0i          | 1i      | 1i             |
-| 0i   | 1i          | 2i      | 3i             |
-| 0i   | 3i          | 3i      | 6i             |
+| 0    | 0           | 1       | 1              |
+| 0    | 1           | 2       | 3              |
+| 0    | 3           | 3       | 6              |
 
 We called `fold()` with these arguments:
 
 ```{rust}
-# range(1i, 4i)
-.fold(0i, |sum, x| sum + x);
+# range(1, 4)
+.fold(0, |sum, x| sum + x);
 ```
 
-So, `0i` is our base, `sum` is our accumulator, and `x` is our element.  On the
-first iteration, we set `sum` to `0i`, and `x` is the first element of `nums`,
-`1i`. We then add `sum` and `x`, which gives us `0i + 1i = 1i`. On the second
+So, `0` is our base, `sum` is our accumulator, and `x` is our element.  On the
+first iteration, we set `sum` to `0`, and `x` is the first element of `nums`,
+`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second
 iteration, that value becomes our accumulator, `sum`, and the element is
-the second element of the array, `2i`. `1i + 2i = 3i`, and so that becomes
+the second element of the array, `2`. `1 + 2 = 3`, and so that becomes
 the value of the accumulator for the last iteration. On that iteration,
-`x` is the last element, `3i`, and `3i + 3i = 6i`, which is our final
+`x` is the last element, `3`, and `3 + 3 = 6`, which is our final
 result for our sum. `1 + 2 + 3 = 6`, and that's the result we got.
 
 Whew. `fold` can be a bit strange the first few times you see it, but once it
@@ -210,14 +210,14 @@ This code, for example, does not actually generate the numbers
 `1-100`, and just creates a value that represents the sequence:
 
 ```{rust}
-let nums = range(1i, 100i);
+let nums = range(1, 100);
 ```
 
 Since we didn't do anything with the range, it didn't generate the sequence.
 Let's add the consumer:
 
 ```{rust}
-let nums = range(1i, 100i).collect::<Vec<int>>();
+let nums = range(1, 100).collect::<Vec<i32>>();
 ```
 
 Now, `collect()` will require that `range()` give it some numbers, and so
@@ -228,7 +228,7 @@ which you've used before. `iter()` can turn a vector into a simple iterator
 that gives you each element in turn:
 
 ```{rust}
-let nums = [1i, 2i, 3i];
+let nums = [1, 2, 3];
 
 for num in nums.iter() {
    println!("{}", num);
@@ -239,12 +239,12 @@ These two basic iterators should serve you well. There are some more
 advanced iterators, including ones that are infinite. Like `count`:
 
 ```{rust}
-std::iter::count(1i, 5i);
+std::iter::count(1, 5);
 ```
 
 This iterator counts up from one, adding five each time. It will give
 you a new integer every time, forever (well, technically, until it reaches the
-maximum number representable by an `int`). But since iterators are lazy,
+maximum number representable by an `i32`). But since iterators are lazy,
 that's okay! You probably don't want to use `collect()` on it, though...
 
 That's enough about iterators. Iterator adapters are the last concept
@@ -256,7 +256,7 @@ we need to talk about with regards to iterators. Let's get to it!
 a new iterator. The simplest one is called `map`:
 
 ```{rust,ignore}
-range(1i, 100i).map(|x| x + 1i);
+range(1, 100).map(|x| x + 1);
 ```
 
 `map` is called upon another iterator, and produces a new iterator where each
@@ -267,7 +267,7 @@ compile the example, you'll get a warning:
 ```{notrust,ignore}
 warning: unused result which must be used: iterator adaptors are lazy and
          do nothing unless consumed, #[warn(unused_must_use)] on by default
- range(1i, 100i).map(|x| x + 1i);
+ range(1, 100).map(|x| x + 1);
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ```
 
@@ -275,7 +275,7 @@ Laziness strikes again! That closure will never execute. This example
 doesn't print any numbers:
 
 ```{rust,ignore}
-range(1i, 100i).map(|x| println!("{}", x));
+range(1, 100).map(|x| println!("{}", x));
 ```
 
 If you are trying to execute a closure on an iterator for its side effects,
@@ -287,7 +287,7 @@ has no side effect on the original iterator. Let's try it out with our infinite
 iterator from before, `count()`:
 
 ```{rust}
-for i in std::iter::count(1i, 5i).take(5) {
+for i in std::iter::count(1, 5).take(5) {
     println!("{}", i);
 }
 ```
@@ -307,7 +307,7 @@ returns `true` or `false`. The new iterator `filter()` produces
 only the elements that that closure returns `true` for:
 
 ```{rust}
-for i in range(1i, 100i).filter(|&x| x % 2 == 0) {
+for i in range(1, 100).filter(|&x| x % 2 == 0) {
     println!("{}", i);
 }
 ```
@@ -322,11 +322,11 @@ You can chain all three things together: start with an iterator, adapt it
 a few times, and then consume the result. Check it out:
 
 ```{rust}
-range(1i, 1000i)
+range(1, 1000)
     .filter(|&x| x % 2 == 0)
     .filter(|&x| x % 3 == 0)
     .take(5)
-    .collect::<Vec<int>>();
+    .collect::<Vec<i32>>();
 ```
 
 This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
diff --git a/src/doc/trpl/looping.md b/src/doc/trpl/looping.md
index f54084a7fb9..28f02b1ffe1 100644
--- a/src/doc/trpl/looping.md
+++ b/src/doc/trpl/looping.md
@@ -18,7 +18,7 @@ for (x = 0; x < 10; x++) {
 Instead, it looks like this:
 
 ```{rust}
-for x in range(0, 10) {
+for x in 0..10 {
     println!("{}", x); // x: i32
 }
 ```
@@ -38,7 +38,7 @@ valid for the loop body. Once the body is over, the next value is fetched from
 the iterator, and we loop another time. When there are no more values, the
 `for` loop is over.
 
-In our example, `range` is a function that takes a start and an end position,
+In our example, `0..10` is an expression that takes a start and an end position,
 and gives an iterator over those values. The upper bound is exclusive, though,
 so our loop will print `0` through `9`, not `10`.
 
@@ -54,7 +54,7 @@ The other kind of looping construct in Rust is the `while` loop. It looks like
 this:
 
 ```{rust}
-let mut x = 5u;       // mut x: uint
+let mut x = 5; // mut x: u32
 let mut done = false; // mut done: bool
 
 while !done {
@@ -91,7 +91,7 @@ can do with safety and code generation, so you should always prefer
 Let's take a look at that `while` loop we had earlier:
 
 ```{rust}
-let mut x = 5u;
+let mut x = 5;
 let mut done = false;
 
 while !done {
@@ -108,7 +108,7 @@ modifying iteration: `break` and `continue`.
 In this case, we can write the loop in a better way with `break`:
 
 ```{rust}
-let mut x = 5u;
+let mut x = 5;
 
 loop {
     x += x - 3;
@@ -123,7 +123,7 @@ We now loop forever with `loop` and use `break` to break out early.
 iteration. This will only print the odd numbers:
 
 ```{rust}
-for x in range(0, 10) {
+for x in 0..10 {
     if x % 2 == 0 { continue; }
 
     println!("{}", x);
diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md
index c73fbefb2a4..e0bccb1b86f 100644
--- a/src/doc/trpl/macros.md
+++ b/src/doc/trpl/macros.md
@@ -1,4 +1,4 @@
-% The Rust Macros Guide
+% Macros
 
 # Introduction
 
@@ -11,8 +11,8 @@ which both pattern-match on their input and both return early in one case,
 doing nothing otherwise:
 
 ~~~~
-# enum T { SpecialA(uint), SpecialB(uint) }
-# fn f() -> uint {
+# enum T { SpecialA(u32), SpecialB(u32) }
+# fn f() -> u32 {
 # let input_1 = T::SpecialA(0);
 # let input_2 = T::SpecialA(0);
 match input_1 {
@@ -24,7 +24,7 @@ match input_2 {
     T::SpecialB(x) => { return x; }
     _ => {}
 }
-# return 0u;
+# return 0;
 # }
 ~~~~
 
@@ -37,12 +37,12 @@ lightweight custom syntax extensions, themselves defined using the
 the pattern in the above code:
 
 ~~~~
-# enum T { SpecialA(uint), SpecialB(uint) }
-# fn f() -> uint {
+# enum T { SpecialA(u32), SpecialB(u32) }
+# fn f() -> u32 {
 # let input_1 = T::SpecialA(0);
 # let input_2 = T::SpecialA(0);
 macro_rules! early_return {
-    ($inp:expr, $sp:path) => ( // invoke it like `(input_5 SpecialE)`
+    ($inp:expr, $sp:path) => ( // invoke it like `(input_5, SpecialE)`
         match $inp {
             $sp(x) => { return x; }
             _ => {}
@@ -59,7 +59,7 @@ early_return!(input_2, T::SpecialB);
 ~~~~
 
 Macros are defined in pattern-matching style: in the above example, the text
-`($inp:expr $sp:ident)` that appears on the left-hand side of the `=>` is the
+`($inp:expr, $sp:path)` that appears on the left-hand side of the `=>` is the
 *macro invocation syntax*, a pattern denoting how to write a call to the
 macro. The text on the right-hand side of the `=>`, beginning with `match
 $inp`, is the *macro transcription syntax*: what the macro expands to.
@@ -74,6 +74,8 @@ conforms to the following rules:
 2. `$` has special meaning (described below).
 3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
 forbidden.
+4. Some arguments can be followed only by a limited set of separators, to
+avoid ambiguity (described below).
 
 Otherwise, the invocation syntax is free-form.
 
@@ -86,7 +88,8 @@ To take a fragment of Rust code as an argument, write `$` followed by a name
   `foo`.)
 * `expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`;
   `f(42)`.)
-* `ty` (a type. Examples: `int`, `Vec<(char, String)>`, `&T`.)
+* `ty` (a type. Examples: `i32`, `Vec<(char, String)>`, `&T`.)
+* `path` (a path to struct or enum variant. Example: `T::SpecialA`)
 * `pat` (a pattern, usually appearing in a `match` or on the left-hand side of
   a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.)
 * `block` (a sequence of actions. Example: `{ log(error, "hi"); return 12; }`)
@@ -97,6 +100,12 @@ rules of tokenization apply,
 So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macro
 that could be invoked like: `my_macro!(i->(( 2+2 )))`.
 
+To avoid ambiguity, macro invocation syntax must conform to the following rules:
+* `expr` must be followed by `=>`, `,` or `;`.
+* `ty` and `path` must be followed by `=>`, `,`, `:`, `=`, `>` or `as`.
+* `pat` must be followed by `=>`, `,` or `=`.
+* `ident` and `block` can be followed by any token.
+
 ## Invocation location
 
 A macro invocation may take the place of (and therefore expand to) an
@@ -156,8 +165,8 @@ separator token (a comma-separated list could be written `$(...),*`), and `+`
 instead of `*` to mean "at least one".
 
 ~~~~
-# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}
-# fn f() -> uint {
+# enum T { SpecialA(u32), SpecialB(u32), SpecialC(u32), SpecialD(u32) }
+# fn f() -> u32 {
 # let input_1 = T::SpecialA(0);
 # let input_2 = T::SpecialA(0);
 macro_rules! early_return {
@@ -217,10 +226,10 @@ solves the problem.
 Now consider code like the following:
 
 ~~~~
-# enum T1 { Good1(T2, uint), Bad1}
+# enum T1 { Good1(T2, u32), Bad1}
 # struct T2 { body: T3 }
-# enum T3 { Good2(uint), Bad2}
-# fn f(x: T1) -> uint {
+# enum T3 { Good2(u32), Bad2}
+# fn f(x: T1) -> u32 {
 match x {
     T1::Good1(g1, val) => {
         match g1.body {
@@ -264,10 +273,10 @@ macro_rules! biased_match {
     )
 }
 
-# enum T1 { Good1(T2, uint), Bad1}
+# enum T1 { Good1(T2, u32), Bad1}
 # struct T2 { body: T3 }
-# enum T3 { Good2(uint), Bad2}
-# fn f(x: T1) -> uint {
+# enum T3 { Good2(u32), Bad2}
+# fn f(x: T1) -> u32 {
 biased_match!((x)       -> (T1::Good1(g1, val)) else { return 0 };
               binds g1, val );
 biased_match!((g1.body) -> (T3::Good2(result) )
@@ -374,10 +383,10 @@ macro_rules! biased_match {
 }
 
 
-# enum T1 { Good1(T2, uint), Bad1}
+# enum T1 { Good1(T2, u32), Bad1}
 # struct T2 { body: T3 }
-# enum T3 { Good2(uint), Bad2}
-# fn f(x: T1) -> uint {
+# enum T3 { Good2(u32), Bad2}
+# fn f(x: T1) -> u32 {
 biased_match!(
     (x)       -> (T1::Good1(g1, val)) else { return 0 };
     (g1.body) -> (T3::Good2(result) ) else { panic!("Didn't get Good2") };
@@ -519,7 +528,7 @@ A further difficulty occurs when a macro is used in multiple crates.  Say that
 `mylib` defines
 
 ```rust
-pub fn increment(x: uint) -> uint {
+pub fn increment(x: u32) -> u32 {
     x + 1
 }
 
@@ -571,7 +580,7 @@ intermediate states out, and passing the flag `--pretty expanded` as a
 command-line argument to the compiler will show the result of expansion.
 
 If Rust's macro system can't do what you need, you may want to write a
-[compiler plugin](plugin.html) instead. Compared to `macro_rules!`
+[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
 macros, this is significantly more work, the interfaces are much less stable,
 and the warnings about debugging apply ten-fold. In exchange you get the
 flexibility of running arbitrary Rust code within the compiler. Syntax
diff --git a/src/doc/trpl/match.md b/src/doc/trpl/match.md
index 1833b05591b..73bc775a1b2 100644
--- a/src/doc/trpl/match.md
+++ b/src/doc/trpl/match.md
@@ -84,9 +84,9 @@ fn main() {
     let y = 10;
 
     match cmp(x, y) {
-        Ordering::Less    => println!("less"),
+        Ordering::Less => println!("less"),
         Ordering::Greater => println!("greater"),
-        Ordering::Equal   => println!("equal"),
+        Ordering::Equal => println!("equal"),
     }
 }
 ```
@@ -112,12 +112,12 @@ fn main() {
 
     match x {
         OptionalInt::Value(n) => println!("x is {}", n),
-        OptionalInt::Missing  => println!("x is missing!"),
+        OptionalInt::Missing => println!("x is missing!"),
     }
 
     match y {
         OptionalInt::Value(n) => println!("y is {}", n),
-        OptionalInt::Missing  => println!("y is missing!"),
+        OptionalInt::Missing => println!("y is missing!"),
     }
 }
 ```
@@ -146,9 +146,9 @@ fn main() {
     let y = 10;
 
     println!("{}", match cmp(x, y) {
-        Ordering::Less    => "less",
+        Ordering::Less => "less",
         Ordering::Greater => "greater",
-        Ordering::Equal   => "equal",
+        Ordering::Equal => "equal",
     });
 }
 ```
diff --git a/src/doc/trpl/ownership.md b/src/doc/trpl/ownership.md
index 946d0eee7df..9ced5bb656c 100644
--- a/src/doc/trpl/ownership.md
+++ b/src/doc/trpl/ownership.md
@@ -1,4 +1,4 @@
-% The Rust Ownership Guide
+% Ownership
 
 This guide presents Rust's ownership system. This is one of Rust's most unique
 and compelling features, with which Rust developers should become quite
@@ -81,15 +81,14 @@ therefore deallocates the memory for you. Here's the equivalent example in
 Rust:
 
 ```rust
-# use std::boxed::Box;
 {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 }
 ```
 
-The `Box::new` function creates a `Box<T>` (specifically `Box<int>` in this
+The `Box::new` function creates a `Box<T>` (specifically `Box<i32>` in this
 case) by allocating a small segment of memory on the heap with enough space to
-fit an `int`. But where in the code is the box deallocated? We said before that
+fit an `i32`. But where in the code is the box deallocated? We said before that
 we must have a deallocation for each allocation. Rust handles this for you. It
 knows that our handle, `x`, is the owning reference to our box. Rust knows that
 `x` will go out of scope at the end of the block, and so it inserts a call to
@@ -101,14 +100,13 @@ This is pretty straightforward, but what happens when we want to pass our box
 to a function? Let's look at some code:
 
 ```rust
-# use std::boxed::Box;
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     add_one(x);
 }
 
-fn add_one(mut num: Box<int>) {
+fn add_one(mut num: Box<i32>) {
     *num += 1;
 }
 ```
@@ -117,16 +115,15 @@ This code works, but it's not ideal. For example, let's add one more line of
 code, where we print out the value of `x`:
 
 ```{rust,ignore}
-# use std::boxed::Box;
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     add_one(x);
 
     println!("{}", x);
 }
 
-fn add_one(mut num: Box<int>) {
+fn add_one(mut num: Box<i32>) {
     *num += 1;
 }
 ```
@@ -151,16 +148,15 @@ To fix this, we can have `add_one` give ownership back when it's done with the
 box:
 
 ```rust
-# use std::boxed::Box;
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     let y = add_one(x);
 
     println!("{}", y);
 }
 
-fn add_one(mut num: Box<int>) -> Box<int> {
+fn add_one(mut num: Box<i32>) -> Box<i32> {
     *num += 1;
 
     num
@@ -179,7 +175,7 @@ to something another handle owns. It's called *borrowing*, and it's done with
 Here's the current state of our `add_one` function:
 
 ```rust
-fn add_one(mut num: Box<int>) -> Box<int> {
+fn add_one(mut num: Box<i32>) -> Box<i32> {
     *num += 1;
 
     num
@@ -199,14 +195,34 @@ period. This is also called *borrowing*. Here's a version of `add_one` which
 borrows its argument rather than taking ownership:
 
 ```rust
-fn add_one(num: &mut int) {
+fn add_one(num: &mut i32) {
     *num += 1;
 }
 ```
 
-This function borrows an `int` from its caller, and then increments it. When
+This function borrows an `i32` from its caller, and then increments it. When
 the function is over, and `num` goes out of scope, the borrow is over.
 
+We have to change our `main` a bit too:
+
+```rust
+fn main() {
+    let mut x = 5;
+
+    add_one(&mut x);
+
+    println!("{}", x);
+}
+
+fn add_one(num: &mut i32) {
+    *num += 1;
+}
+```
+
+We don't need to assign the result of `add_one()` anymore, because it doesn't
+return anything anymore. This is because we're not passing ownership back,
+since we just borrow, not take ownership.
+
 # Lifetimes
 
 Lending out a reference to a resource that someone else owns can be
@@ -225,10 +241,10 @@ To fix this, we have to make sure that step four never happens after step
 three. The ownership system in Rust does this through a concept called
 *lifetimes*, which describe the scope that a reference is valid for.
 
-Let's look at that function which borrows an `int` again:
+Remember the function that borrowed an `i32`? Let's look at it again.
 
 ```rust
-fn add_one(num: &int) -> int {
+fn add_one(num: &i32) -> i32 {
     *num + 1
 }
 ```
@@ -239,7 +255,7 @@ cover the others later. Without eliding the lifetimes, `add_one` looks like
 this:
 
 ```rust
-fn add_one<'a>(num: &'a int) -> int {
+fn add_one<'a>(num: &'a i32) -> i32 {
     *num + 1
 }
 ```
@@ -262,22 +278,22 @@ fn add_two<'a, 'b>(...)
 Then in our parameter list, we use the lifetimes we've named:
 
 ```{rust,ignore}
-...(num: &'a int) -> ...
+...(num: &'a i32) -> ...
 ```
 
-If you compare `&int` to `&'a int`, they're the same, it's just that the
-lifetime `'a` has snuck in between the `&` and the `int`. We read `&int` as "a
-reference to an int" and `&'a int` as "a reference to an int with the lifetime 'a.'"
+If you compare `&i32` to `&'a i32`, they're the same, it's just that the
+lifetime `'a` has snuck in between the `&` and the `i32`. We read `&i32` as "a
+reference to an i32" and `&'a i32` as "a reference to an i32 with the lifetime 'a.'"
 
 Why do lifetimes matter? Well, for example, here's some code:
 
 ```rust
 struct Foo<'a> {
-    x: &'a int,
+    x: &'a i32,
 }
 
 fn main() {
-    let y = &5i; // this is the same as `let _y = 5; let y = &_y;
+    let y = &5; // this is the same as `let _y = 5; let y = &_y;
     let f = Foo { x: y };
 
     println!("{}", f.x);
@@ -288,7 +304,7 @@ As you can see, `struct`s can also have lifetimes. In a similar way to functions
 
 ```{rust}
 struct Foo<'a> {
-# x: &'a int,
+# x: &'a i32,
 # }
 ```
 
@@ -296,12 +312,12 @@ declares a lifetime, and
 
 ```rust
 # struct Foo<'a> {
-x: &'a int,
+x: &'a i32,
 # }
 ```
 
 uses it. So why do we need a lifetime here? We need to ensure that any reference
-to a `Foo` cannot outlive the reference to an `int` it contains.
+to a `Foo` cannot outlive the reference to an `i32` it contains.
 
 ## Thinking in scopes
 
@@ -310,7 +326,7 @@ valid for. For example:
 
 ```rust
 fn main() {
-    let y = &5i;    // -+ y goes into scope
+    let y = &5;     // -+ y goes into scope
                     //  |
     // stuff        //  |
                     //  |
@@ -321,11 +337,11 @@ Adding in our `Foo`:
 
 ```rust
 struct Foo<'a> {
-    x: &'a int,
+    x: &'a i32,
 }
 
 fn main() {
-    let y = &5i;          // -+ y goes into scope
+    let y = &5;           // -+ y goes into scope
     let f = Foo { x: y }; // -+ f goes into scope
     // stuff              //  |
                           //  |
@@ -337,14 +353,14 @@ This code won't work:
 
 ```{rust,ignore}
 struct Foo<'a> {
-    x: &'a int,
+    x: &'a i32,
 }
 
 fn main() {
     let x;                    // -+ x goes into scope
                               //  |
     {                         //  |
-        let y = &5i;          // ---+ y goes into scope
+        let y = &5;           // ---+ y goes into scope
         let f = Foo { x: y }; // ---+ f goes into scope
         x = &f.x;             //  | | error here
     }                         // ---+ f and y go out of scope
@@ -375,12 +391,12 @@ alive: they are baked into the data segment of the final binary. Another
 example are globals:
 
 ```rust
-static FOO: int = 5i;
-let x: &'static int = &FOO;
+static FOO: i32 = 5;
+let x: &'static i32 = &FOO;
 ```
 
-This adds an `int` to the data segment of the binary, and FOO is a reference to
-it.
+This adds an `i32` to the data segment of the binary, and `FOO` is a reference
+to it.
 
 # Shared Ownership
 
@@ -395,14 +411,14 @@ struct Car {
 }
 
 struct Wheel {
-    size: int,
+    size: i32,
     owner: Car,
 }
 
 fn main() {
     let car = Car { name: "DeLorean".to_string() };
 
-    for _ in range(0u, 4) {
+    for _ in range(0, 4) {
         Wheel { size: 360, owner: car };
     }
 }
@@ -431,7 +447,7 @@ struct Car {
 }
 
 struct Wheel {
-    size: int,
+    size: i32,
     owner: Rc<Car>,
 }
 
@@ -440,7 +456,7 @@ fn main() {
 
     let car_owner = Rc::new(car);
 
-    for _ in range(0u, 4) {
+    for _ in range(0, 4) {
         Wheel { size: 360, owner: car_owner.clone() };
     }
 }
@@ -501,31 +517,31 @@ Here are some examples of functions with elided lifetimes, and the version of
 what the elided lifetimes are expand to:
 
 ```{rust,ignore}
-fn print(s: &str);                                      // elided
-fn print<'a>(s: &'a str);                               // expanded
+fn print(s: &str); // elided
+fn print<'a>(s: &'a str); // expanded
 
-fn debug(lvl: uint, s: &str);                           // elided
-fn debug<'a>(lvl: uint, s: &'a str);                    // expanded
+fn debug(lvl: u32, s: &str); // elided
+fn debug<'a>(lvl: u32, s: &'a str); // expanded
 
 // In the preceeding example, `lvl` doesn't need a lifetime because it's not a
 // reference (`&`). Only things relating to references (such as a `struct`
 // which contains a reference) need lifetimes.
 
-fn substr(s: &str, until: uint) -> &str;                // elided
-fn substr<'a>(s: &'a str, until: uint) -> &'a str;      // expanded
+fn substr(s: &str, until: u32) -> &str; // elided
+fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
 
-fn get_str() -> &str;                                   // ILLEGAL, no inputs
+fn get_str() -> &str; // ILLEGAL, no inputs
 
-fn frob(s: &str, t: &str) -> &str;                      // ILLEGAL, two inputs
+fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
 
-fn get_mut(&mut self) -> &mut T;                        // elided
-fn get_mut<'a>(&'a mut self) -> &'a mut T;              // expanded
+fn get_mut(&mut self) -> &mut T; // elided
+fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
 
-fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command                  // elided
+fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
 fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
 
-fn new(buf: &mut [u8]) -> BufWriter;                    // elided
-fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>          // expanded
+fn new(buf: &mut [u8]) -> BufWriter; // elided
+fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
 ```
 
 # Related Resources
diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md
index c54d502b4ed..5c7b406a6fc 100644
--- a/src/doc/trpl/patterns.md
+++ b/src/doc/trpl/patterns.md
@@ -8,7 +8,7 @@ A quick refresher: you can match against literals directly, and `_` acts as an
 *any* case:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     1 => println!("one"),
@@ -21,7 +21,7 @@ match x {
 You can match multiple patterns with `|`:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     1 | 2 => println!("one or two"),
@@ -33,7 +33,7 @@ match x {
 You can match a range of values with `...`:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     1 ... 5 => println!("one through five"),
@@ -47,7 +47,7 @@ If you're matching multiple things, via a `|` or a `...`, you can bind
 the value to a name with `@`:
 
 ```{rust}
-let x = 1i;
+let x = 1;
 
 match x {
     e @ 1 ... 5 => println!("got a range element {}", e),
@@ -60,15 +60,15 @@ ignore the value and type in the variant:
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 
-let x = OptionalInt::Value(5i);
+let x = OptionalInt::Value(5);
 
 match x {
     OptionalInt::Value(..) => println!("Got an int!"),
-    OptionalInt::Missing   => println!("No such luck."),
+    OptionalInt::Missing => println!("No such luck."),
 }
 ```
 
@@ -76,16 +76,16 @@ You can introduce *match guards* with `if`:
 
 ```{rust}
 enum OptionalInt {
-    Value(int),
+    Value(i32),
     Missing,
 }
 
-let x = OptionalInt::Value(5i);
+let x = OptionalInt::Value(5);
 
 match x {
     OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
     OptionalInt::Value(..) => println!("Got an int!"),
-    OptionalInt::Missing   => println!("No such luck."),
+    OptionalInt::Missing => println!("No such luck."),
 }
 ```
 
@@ -93,33 +93,33 @@ If you're matching on a pointer, you can use the same syntax as you declared it
 with. First, `&`:
 
 ```{rust}
-let x = &5i;
+let x = &5;
 
 match x {
     &val => println!("Got a value: {}", val),
 }
 ```
 
-Here, the `val` inside the `match` has type `int`. In other words, the left-hand
-side of the pattern destructures the value. If we have `&5i`, then in `&val`, `val`
-would be `5i`.
+Here, the `val` inside the `match` has type `i32`. In other words, the left-hand
+side of the pattern destructures the value. If we have `&5`, then in `&val`, `val`
+would be `5`.
 
 If you want to get a reference, use the `ref` keyword:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 
 match x {
     ref r => println!("Got a reference to {}", r),
 }
 ```
 
-Here, the `r` inside the `match` has the type `&int`. In other words, the `ref`
+Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
 keyword _creates_ a reference, for use in the pattern. If you need a mutable
 reference, `ref mut` will work in the same way:
 
 ```{rust}
-let mut x = 5i;
+let mut x = 5;
 
 match x {
     ref mut mr => println!("Got a mutable reference to {}", mr),
@@ -131,11 +131,11 @@ If you have a struct, you can destructure it inside of a pattern:
 ```{rust}
 # #![allow(non_shorthand_field_patterns)]
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-let origin = Point { x: 0i, y: 0i };
+let origin = Point { x: 0, y: 0 };
 
 match origin {
     Point { x: x, y: y } => println!("({},{})", x, y),
@@ -147,11 +147,11 @@ If we only care about some of the values, we don't have to give them all names:
 ```{rust}
 # #![allow(non_shorthand_field_patterns)]
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-let origin = Point { x: 0i, y: 0i };
+let origin = Point { x: 0, y: 0 };
 
 match origin {
     Point { x: x, .. } => println!("x is {}", x),
@@ -163,11 +163,11 @@ You can do this kind of match on any member, not just the first:
 ```{rust}
 # #![allow(non_shorthand_field_patterns)]
 struct Point {
-    x: int,
-    y: int,
+    x: i32,
+    y: i32,
 }
 
-let origin = Point { x: 0i, y: 0i };
+let origin = Point { x: 0, y: 0 };
 
 match origin {
     Point { y: y, .. } => println!("y is {}", y),
diff --git a/src/doc/trpl/plugins.md b/src/doc/trpl/plugins.md
index 2fc361ca1b2..6e8e2c7ffe2 100644
--- a/src/doc/trpl/plugins.md
+++ b/src/doc/trpl/plugins.md
@@ -1,4 +1,4 @@
-% The Rust Compiler Plugins Guide
+% Compiler Plugins
 
 <div class="unstable-feature">
 
@@ -68,7 +68,7 @@ use rustc::plugin::Registry;
 fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
         -> Box<MacResult + 'static> {
 
-    static NUMERALS: &'static [(&'static str, uint)] = &[
+    static NUMERALS: &'static [(&'static str, u32)] = &[
         ("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
         ("C",  100), ("XC",  90), ("L",  50), ("XL",  40),
         ("X",   10), ("IX",   9), ("V",   5), ("IV",   4),
@@ -83,7 +83,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
     };
 
     let mut text = text.as_slice();
-    let mut total = 0u;
+    let mut total = 0;
     while !text.is_empty() {
         match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
             Some(&(rn, val)) => {
@@ -118,7 +118,7 @@ fn main() {
 }
 ```
 
-The advantages over a simple `fn(&str) -> uint` are:
+The advantages over a simple `fn(&str) -> u32` are:
 
 * The (arbitrarily complex) conversion is done at compile time.
 * Input validation is also performed at compile time.
@@ -126,7 +126,7 @@ The advantages over a simple `fn(&str) -> uint` are:
   a way to define new literal syntax for any data type.
 
 In addition to procedural macros, you can define new
-[`deriving`](../reference.html#deriving)-like attributes and other kinds of
+[`derive`](../reference.html#derive)-like attributes and other kinds of
 extensions.  See
 [`Registry::register_syntax_extension`](../rustc/plugin/registry/struct.Registry.html#method.register_syntax_extension)
 and the [`SyntaxExtension`
diff --git a/src/doc/trpl/pointers.md b/src/doc/trpl/pointers.md
index 63c16ef191e..d74c10b8145 100644
--- a/src/doc/trpl/pointers.md
+++ b/src/doc/trpl/pointers.md
@@ -1,4 +1,4 @@
-% The Rust Pointer Guide
+% Pointers
 
 Rust's pointers are one of its more unique and compelling features. Pointers
 are also one of the more confusing topics for newcomers to Rust. They can also
@@ -28,9 +28,10 @@ question](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-
 as the rest of this guide assumes you know the difference.) Like this:
 
 ```{rust}
-let x = 5i;
-let y = 8i;
+let x = 5;
+let y = 8;
 ```
+
 | location | value |
 |----------|-------|
 | 0xd3e030 | 5	   |
@@ -46,10 +47,11 @@ Let's introduce a pointer. In some languages, there is just one type of
 *reference*, which is the simplest kind of pointer.
 
 ```{rust}
-let x = 5i;
-let y = 8i;
+let x = 5;
+let y = 8;
 let z = &y;
 ```
+
 |location | value    |
 |-------- |----------|
 |0xd3e030 | 5        |
@@ -58,12 +60,12 @@ let z = &y;
 
 See the difference? Rather than contain a value, the value of a pointer is a
 location in memory. In this case, the location of `y`. `x` and `y` have the
-type `int`, but `z` has the type `&int`. We can print this location using the
+type `i32`, but `z` has the type `&i32`. We can print this location using the
 `{:p}` format string:
 
 ```{rust}
-let x = 5i;
-let y = 8i;
+let x = 5;
+let y = 8;
 let z = &y;
 
 println!("{:p}", z);
@@ -71,12 +73,12 @@ println!("{:p}", z);
 
 This would print `0xd3e028`, with our fictional memory addresses.
 
-Because `int` and `&int` are different types, we can't, for example, add them
+Because `i32` and `&i32` are different types, we can't, for example, add them
 together:
 
 ```{rust,ignore}
-let x = 5i;
-let y = 8i;
+let x = 5;
+let y = 8;
 let z = &y;
 
 println!("{}", x + z);
@@ -85,7 +87,7 @@ println!("{}", x + z);
 This gives us an error:
 
 ```text
-hello.rs:6:24: 6:25 error: mismatched types: expected `int` but found `&int` (expected int but found &-ptr)
+hello.rs:6:24: 6:25 error: mismatched types: expected `i32` but found `&i32` (expected i32 but found &-ptr)
 hello.rs:6     println!("{}", x + z);
                                   ^
 ```
@@ -95,8 +97,8 @@ pointer means accessing the value at the location stored in the pointer. This
 will work:
 
 ```{rust}
-let x = 5i;
-let y = 8i;
+let x = 5;
+let y = 8;
 let z = &y;
 
 println!("{}", x + *z);
@@ -153,7 +155,7 @@ So what do pointers have to do with this? Well, since pointers point to a
 location in memory...
 
 ```text
-func foo(&int x) {
+func foo(&i32 x) {
     *x = 5
 }
 
@@ -252,7 +254,7 @@ The most basic type of pointer that Rust has is called a *reference*. Rust
 references look like this:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 let y = &x;
 
 println!("{}", *y);
@@ -269,18 +271,18 @@ referent, because `println!` will automatically dereference it for us.
 Here's a function that takes a reference:
 
 ```{rust}
-fn succ(x: &int) -> int { *x + 1 }
+fn succ(x: &i32) -> i32 { *x + 1 }
 ```
 
 You can also use `&` as an operator to create a reference, so we can
 call this function in two different ways:
 
 ```{rust}
-fn succ(x: &int) -> int { *x + 1 }
+fn succ(x: &i32) -> i32 { *x + 1 }
 
 fn main() {
 
-    let x = 5i;
+    let x = 5;
     let y = &x;
 
     println!("{}", succ(y));
@@ -294,13 +296,13 @@ Of course, if this were real code, we wouldn't bother with the reference, and
 just write:
 
 ```{rust}
-fn succ(x: int) -> int { x + 1 }
+fn succ(x: i32) -> i32 { x + 1 }
 ```
 
 References are immutable by default:
 
 ```{rust,ignore}
-let x = 5i;
+let x = 5;
 let y = &x;
 
 *y = 5; // error: cannot assign to immutable dereference of `&`-pointer `*y`
@@ -310,21 +312,21 @@ They can be made mutable with `mut`, but only if its referent is also mutable.
 This works:
 
 ```{rust}
-let mut x = 5i;
+let mut x = 5;
 let y = &mut x;
 ```
 
 This does not:
 
 ```{rust,ignore}
-let x = 5i;
+let x = 5;
 let y = &mut x; // error: cannot borrow immutable local variable `x` as mutable
 ```
 
 Immutable pointers are allowed to alias:
 
 ```{rust}
-let x = 5i;
+let x = 5;
 let y = &x;
 let z = &x;
 ```
@@ -332,7 +334,7 @@ let z = &x;
 Mutable ones, however, are not:
 
 ```{rust,ignore}
-let mut x = 5i;
+let mut x = 5;
 let y = &mut x;
 let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time
 ```
@@ -359,7 +361,7 @@ duration a *lifetime*. Let's try a more complex example:
 
 ```{rust}
 fn main() {
-    let x = &mut 5i;
+    let x = &mut 5;
 
     if *x < 10 {
         let y = &x;
@@ -380,7 +382,7 @@ mutated, and therefore, lets us pass. This wouldn't work:
 
 ```{rust,ignore}
 fn main() {
-    let x = &mut 5i;
+    let x = &mut 5;
 
     if *x < 10 {
         let y = &x;
@@ -425,13 +427,13 @@ References just borrow ownership, which is more polite if you don't need the
 ownership. In other words, prefer:
 
 ```{rust}
-fn succ(x: &int) -> int { *x + 1 }
+fn succ(x: &i32) -> i32 { *x + 1 }
 ```
 
 to
 
 ```{rust}
-fn succ(x: Box<int>) -> int { *x + 1 }
+fn succ(x: Box<i32>) -> i32 { *x + 1 }
 ```
 
 As a corollary to that rule, references allow you to accept a wide variety of
@@ -439,7 +441,7 @@ other pointers, and so are useful so that you don't have to write a number
 of variants per pointer. In other words, prefer:
 
 ```{rust}
-fn succ(x: &int) -> int { *x + 1 }
+fn succ(x: &i32) -> i32 { *x + 1 }
 ```
 
 to
@@ -447,22 +449,21 @@ to
 ```{rust}
 use std::rc::Rc;
 
-fn box_succ(x: Box<int>) -> int { *x + 1 }
+fn box_succ(x: Box<i32>) -> i32 { *x + 1 }
 
-fn rc_succ(x: Rc<int>) -> int { *x + 1 }
+fn rc_succ(x: Rc<i32>) -> i32 { *x + 1 }
 ```
 
 Note that the caller of your function will have to modify their calls slightly:
 
 ```{rust}
-# use std::boxed::Box;
 use std::rc::Rc;
 
-fn succ(x: &int) -> int { *x + 1 }
+fn succ(x: &i32) -> i32 { *x + 1 }
 
-let ref_x = &5i;
-let box_x = Box::new(5i);
-let rc_x  = Rc::new(5i);
+let ref_x = &5;
+let box_x = Box::new(5);
+let rc_x = Rc::new(5);
 
 succ(ref_x);
 succ(&*box_x);
@@ -478,17 +479,15 @@ those contents.
 heap allocation in Rust. Creating a box looks like this:
 
 ```{rust}
-# use std::boxed::Box;
-let x = Box::new(5i);
+let x = Box::new(5);
 ```
 
 Boxes are heap allocated and they are deallocated automatically by Rust when
 they go out of scope:
 
 ```{rust}
-# use std::boxed::Box;
 {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     // stuff happens
 
@@ -507,9 +506,8 @@ You don't need to fully grok the theory of affine types or regions to grok
 boxes, though. As a rough approximation, you can treat this Rust code:
 
 ```{rust}
-# use std::boxed::Box;
 {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     // stuff happens
 }
@@ -548,13 +546,12 @@ for more detail on how lifetimes work.
 Using boxes and references together is very common. For example:
 
 ```{rust}
-# use std::boxed::Box;
-fn add_one(x: &int) -> int {
+fn add_one(x: &i32) -> i32 {
     *x + 1
 }
 
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     println!("{}", add_one(&*x));
 }
@@ -566,13 +563,12 @@ function, and since it's only reading the value, allows it.
 We can borrow `x` multiple times, as long as it's not simultaneous:
 
 ```{rust}
-# use std::boxed::Box;
-fn add_one(x: &int) -> int {
+fn add_one(x: &i32) -> i32 {
     *x + 1
 }
 
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     println!("{}", add_one(&*x));
     println!("{}", add_one(&*x));
@@ -583,13 +579,12 @@ fn main() {
 Or as long as it's not a mutable borrow. This will error:
 
 ```{rust,ignore}
-# use std::boxed::Box;
-fn add_one(x: &mut int) -> int {
+fn add_one(x: &mut i32) -> i32 {
     *x + 1
 }
 
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     println!("{}", add_one(&*x)); // error: cannot borrow immutable dereference
                                   // of `&`-pointer as mutable
@@ -610,7 +605,6 @@ Sometimes, you need a recursive data structure. The simplest is known as a
 
 
 ```{rust}
-# use std::boxed::Box;
 #[derive(Show)]
 enum List<T> {
     Cons(T, Box<List<T>>),
@@ -618,7 +612,7 @@ enum List<T> {
 }
 
 fn main() {
-    let list: List<int> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
+    let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
     println!("{:?}", list);
 }
 ```
@@ -666,12 +660,11 @@ In many languages with pointers, you'd return a pointer from a function
 so as to avoid copying a large data structure. For example:
 
 ```{rust}
-# use std::boxed::Box;
 struct BigStruct {
-    one: int,
-    two: int,
+    one: i32,
+    two: i32,
     // etc
-    one_hundred: int,
+    one_hundred: i32,
 }
 
 fn foo(x: Box<BigStruct>) -> Box<BigStruct> {
@@ -695,12 +688,11 @@ than the hundred `int`s that make up the `BigStruct`.
 This is an antipattern in Rust. Instead, write this:
 
 ```{rust}
-# use std::boxed::Box;
 struct BigStruct {
-    one: int,
-    two: int,
+    one: i32,
+    two: i32,
     // etc
-    one_hundred: int,
+    one_hundred: i32,
 }
 
 fn foo(x: Box<BigStruct>) -> BigStruct {
@@ -721,11 +713,10 @@ fn main() {
 This gives you flexibility without sacrificing performance.
 
 You may think that this gives us terrible performance: return a value and then
-immediately box it up ?! Isn't that the worst of both worlds? Rust is smarter
-than that. There is no copy in this code. `main` allocates enough room for the
-`box`, passes a pointer to that memory into `foo` as `x`, and then `foo` writes
-the value straight into that pointer. This writes the return value directly into
-the allocated box.
+immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is
+smarter than that. There is no copy in this code. `main` allocates enough room
+for the `box`, passes a pointer to that memory into `foo` as `x`, and then
+`foo` writes the value straight into the `Box<T>`.
 
 This is important enough that it bears repeating: pointers are not for
 optimizing returning values from your code. Allow the caller to choose how they
diff --git a/src/doc/trpl/standard-input.md b/src/doc/trpl/standard-input.md
index c4d171bb3a9..7145139bba5 100644
--- a/src/doc/trpl/standard-input.md
+++ b/src/doc/trpl/standard-input.md
@@ -83,12 +83,12 @@ fn main() {
 
     match x {
         OptionalInt::Value(n) => println!("x is {}", n),
-        OptionalInt::Missing  => println!("x is missing!"),
+        OptionalInt::Missing => println!("x is missing!"),
     }
 
     match y {
         OptionalInt::Value(n) => println!("y is {}", n),
-        OptionalInt::Missing  => println!("y is missing!"),
+        OptionalInt::Missing => println!("y is missing!"),
     }
 }
 ```
@@ -141,11 +141,11 @@ use std::io;
 fn main() {
     println!("Type something!");
 
-                                                  // here, we'll show the types at each step
+    // here, we'll show the types at each step
 
-    let input = io::stdin()                       // std::io::stdio::StdinReader
-                  .read_line()                    // IoResult<String>
-                  .ok()                           // Option<String>
+    let input = io::stdin() // std::io::stdio::StdinReader
+                  .read_line() // IoResult<String>
+                  .ok() // Option<String>
                   .expect("Failed to read line"); // String
 
     println!("{}", input);
diff --git a/src/doc/trpl/testing.md b/src/doc/trpl/testing.md
index 66da6395a5e..1c93fd351b6 100644
--- a/src/doc/trpl/testing.md
+++ b/src/doc/trpl/testing.md
@@ -1,4 +1,4 @@
-% The Rust Testing Guide
+% Testing
 
 > Program testing can be a very effective way to show the presence of bugs, but
 > it is hopelessly inadequate for showing their absence. 
@@ -96,7 +96,7 @@ test it_works ... FAILED
 failures:
 
 ---- it_works stdout ----
-        task 'it_works' panicked at 'assertion failed: false', /home/steve/tmp/adder/src/lib.rs:3
+        thread 'it_works' panicked at 'assertion failed: false', /home/steve/tmp/adder/src/lib.rs:3
 
 
 
@@ -105,7 +105,7 @@ failures:
 
 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
 
-task '<main>' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247
+thread '<main>' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247
 ```
 
 Rust indicates that our test failed:
@@ -254,7 +254,6 @@ a large module, and so this is a common use of the `glob` feature. Let's change
 our `src/lib.rs` to make use of it:
 
 ```{rust,ignore}
-#![feature(globs)]
 
 pub fn add_two(a: i32) -> i32 {
     a + 2
@@ -271,8 +270,7 @@ mod tests {
 }
 ```
 
-Note the `feature` attribute, as well as the different `use` line. Now we run
-our tests:
+Note the different `use` line. Now we run our tests:
 
 ```bash
 $ cargo test
@@ -370,8 +368,6 @@ with examples:
 //! assert_eq!(4, adder::add_two(2));
 //! ```
 
-#![feature(globs)]
-
 /// This function adds two to its argument.
 ///
 /// # Examples
@@ -440,8 +436,6 @@ Rust also supports benchmark tests, which can test the performance of your
 code. Let's make our `src/lib.rs` look like this (comments elided):
 
 ```{rust,ignore}
-#![feature(globs)]
-
 extern crate test;
 
 pub fn add_two(a: i32) -> i32 {
@@ -518,7 +512,7 @@ use test::Bencher;
 #[bench]
 fn bench_xor_1000_ints(b: &mut Bencher) {
     b.iter(|| {
-        range(0u, 1000).fold(0, |old, new| old ^ new);
+        range(0, 1000).fold(0, |old, new| old ^ new);
     });
 }
 ```
@@ -543,7 +537,7 @@ computation entirely. This could be done for the example above by adjusting the
 # impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
 b.iter(|| {
     // note lack of `;` (could also use an explicit `return`).
-    range(0u, 1000).fold(0, |old, new| old ^ new)
+    range(0, 1000).fold(0, |old, new| old ^ new)
 });
 ```
 
diff --git a/src/doc/trpl/tasks.md b/src/doc/trpl/threads.md
index 4c6a7f1323f..1bad09b4b6e 100644
--- a/src/doc/trpl/tasks.md
+++ b/src/doc/trpl/threads.md
@@ -51,13 +51,15 @@ closure is limited to capturing `Send`-able data from its environment
 ensures that `spawn` can safely move the entire closure and all its
 associated state into an entirely different thread for execution.
 
-```{rust,ignore}
-# use std::thread::spawn;
-# fn generate_thread_number() -> int { 0 }
+```rust
+use std::thread::Thread;
+
+fn generate_thread_number() -> i32 { 4 } // a very simple generation
+
 // Generate some state locally
 let child_thread_number = generate_thread_number();
 
-spawn(move || {
+Thread::spawn(move || {
     // Capture it in the remote thread. The `move` keyword indicates
     // that this closure should move `child_thread_number` into its
     // environment, rather than capturing a reference into the
@@ -77,20 +79,22 @@ The simplest way to create a channel is to use the `channel` function to create
 of a channel, and a *receiver* is the receiving endpoint. Consider the following
 example of calculating two results concurrently:
 
-```{rust,ignore}
-# use std::thread::spawn;
+```rust
+use std::thread::Thread;
+use std::sync::mpsc;
 
-let (tx, rx): (Sender<int>, Receiver<int>) = channel();
+let (tx, rx): (mpsc::Sender<u32>, mpsc::Receiver<u32>) = mpsc::channel();
 
-spawn(move || {
+Thread::spawn(move || {
     let result = some_expensive_computation();
     tx.send(result);
 });
 
 some_other_expensive_computation();
 let result = rx.recv();
-# fn some_expensive_computation() -> int { 42 }
-# fn some_other_expensive_computation() {}
+
+fn some_expensive_computation() -> u32 { 42 } // very expensive ;)
+fn some_other_expensive_computation() {}      // even more so
 ```
 
 Let's examine this example in detail. First, the `let` statement creates a
@@ -98,19 +102,21 @@ stream for sending and receiving integers (the left-hand side of the `let`,
 `(tx, rx)`, is an example of a destructuring let: the pattern separates a tuple
 into its component parts).
 
-```{rust,ignore}
-let (tx, rx): (Sender<int>, Receiver<int>) = channel();
+```rust
+# use std::sync::mpsc;
+let (tx, rx): (mpsc::Sender<u32>, mpsc::Receiver<u32>) = mpsc::channel();
 ```
 
 The child thread will use the sender to send data to the parent thread, which will
 wait to receive the data on the receiver. The next statement spawns the child
 thread.
 
-```{rust,ignore}
-# use std::thread::spawn;
-# fn some_expensive_computation() -> int { 42 }
-# let (tx, rx) = channel();
-spawn(move || {
+```rust
+# use std::thread::Thread;
+# use std::sync::mpsc;
+# fn some_expensive_computation() -> u32 { 42 }
+# let (tx, rx) = mpsc::channel();
+Thread::spawn(move || {
     let result = some_expensive_computation();
     tx.send(result);
 });
@@ -125,9 +131,10 @@ computation, then sends the result over the captured channel.
 Finally, the parent continues with some other expensive computation, then waits
 for the child's result to arrive on the receiver:
 
-```{rust,ignore}
+```rust
+# use std::sync::mpsc;
 # fn some_other_expensive_computation() {}
-# let (tx, rx) = channel::<int>();
+# let (tx, rx) = mpsc::channel::<u32>();
 # tx.send(0);
 some_other_expensive_computation();
 let result = rx.recv();
@@ -140,8 +147,9 @@ single `Receiver` value.  What if our example needed to compute multiple
 results across a number of threads? The following program is ill-typed:
 
 ```{rust,ignore}
-# fn some_expensive_computation() -> int { 42 }
-let (tx, rx) = channel();
+# use std::sync::mpsc;
+# fn some_expensive_computation() -> u32 { 42 }
+let (tx, rx) = mpsc::channel();
 
 spawn(move || {
     tx.send(some_expensive_computation());
@@ -156,19 +164,22 @@ spawn(move || {
 
 Instead we can clone the `tx`, which allows for multiple senders.
 
-```{rust,ignore}
-let (tx, rx) = channel();
+```rust
+use std::thread::Thread;
+use std::sync::mpsc;
+
+let (tx, rx) = mpsc::channel();
 
-for init_val in range(0u, 3) {
+for init_val in 0 .. 3 {
     // Create a new channel handle to distribute to the child thread
     let child_tx = tx.clone();
-    spawn(move || {
+    Thread::spawn(move || {
         child_tx.send(some_expensive_computation(init_val));
     });
 }
 
-let result = rx.recv() + rx.recv() + rx.recv();
-# fn some_expensive_computation(_i: uint) -> int { 42 }
+let result = rx.recv().unwrap() + rx.recv().unwrap() + rx.recv().unwrap();
+# fn some_expensive_computation(_i: u32) -> u32 { 42 }
 ```
 
 Cloning a `Sender` produces a new handle to the same channel, allowing multiple
@@ -181,21 +192,22 @@ Note that the above cloning example is somewhat contrived since you could also
 simply use three `Sender` pairs, but it serves to illustrate the point. For
 reference, written with multiple streams, it might look like the example below.
 
-```{rust,ignore}
-# use std::thread::spawn;
+```rust
+use std::thread::Thread;
+use std::sync::mpsc;
 
 // Create a vector of ports, one for each child thread
-let rxs = Vec::from_fn(3, |init_val| {
-    let (tx, rx) = channel();
-    spawn(move || {
+let rxs = (0 .. 3).map(|&:init_val| {
+    let (tx, rx) = mpsc::channel();
+    Thread::spawn(move || {
         tx.send(some_expensive_computation(init_val));
     });
     rx
-});
+}).collect::<Vec<_>>();
 
 // Wait on each port, accumulating the results
-let result = rxs.iter().fold(0, |accum, rx| accum + rx.recv() );
-# fn some_expensive_computation(_i: uint) -> int { 42 }
+let result = rxs.iter().fold(0, |&:accum, rx| accum + rx.recv().unwrap() );
+# fn some_expensive_computation(_i: u32) -> u32 { 42 }
 ```
 
 ## Backgrounding computations: Futures
@@ -212,7 +224,7 @@ use std::sync::Future;
 # fn main() {
 # fn make_a_sandwich() {};
 fn fib(n: u64) -> u64 {
-    // lengthy computation returning an uint
+    // lengthy computation returning an 64
     12586269025
 }
 
@@ -237,7 +249,7 @@ computations. The workload will be distributed on the available cores.
 # #![allow(deprecated)]
 # use std::num::Float;
 # use std::sync::Future;
-fn partial_sum(start: uint) -> f64 {
+fn partial_sum(start: u64) -> f64 {
     let mut local_sum = 0f64;
     for num in range(start*100000, (start+1)*100000) {
         local_sum += (num as f64 + 1.0).powf(-2.0);
@@ -277,7 +289,7 @@ use std::num::Float;
 use std::rand;
 use std::sync::Arc;
 
-fn pnorm(nums: &[f64], p: uint) -> f64 {
+fn pnorm(nums: &[f64], p: u64) -> f64 {
     nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64))
 }
 
@@ -285,7 +297,7 @@ fn main() {
     let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
     let numbers_arc = Arc::new(numbers);
 
-    for num in range(1u, 10) {
+    for num in range(1, 10) {
         let thread_numbers = numbers_arc.clone();
 
         spawn(move || {
@@ -316,7 +328,7 @@ if it were local.
 ```{rust,ignore}
 # use std::rand;
 # use std::sync::Arc;
-# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
+# fn pnorm(nums: &[f64], p: u64) -> f64 { 4.0 }
 # fn main() {
 # let numbers=Vec::from_fn(1000000, |_| rand::random::<f64>());
 # let numbers_arc = Arc::new(numbers);
@@ -345,16 +357,16 @@ each other if they panic. The simplest way of handling a panic is with the
 `try` function, which is similar to `spawn`, but immediately blocks and waits
 for the child thread to finish. `try` returns a value of type
 `Result<T, Box<Any + Send>>`. `Result` is an `enum` type with two variants:
-`Ok` and `Err`. In this case, because the type arguments to `Result` are `int`
+`Ok` and `Err`. In this case, because the type arguments to `Result` are `i32`
 and `()`, callers can pattern-match on a result to check whether it's an `Ok`
-result with an `int` field (representing a successful result) or an `Err` result
+result with an `i32` field (representing a successful result) or an `Err` result
 (representing termination with an error).
 
 ```{rust,ignore}
 # use std::thread::Thread;
 # fn some_condition() -> bool { false }
-# fn calculate_result() -> int { 0 }
-let result: Result<int, Box<std::any::Any + Send>> = Thread::spawn(move || {
+# fn calculate_result() -> i32 { 0 }
+let result: Result<i32, Box<std::any::Any + Send>> = Thread::spawn(move || {
     if some_condition() {
         calculate_result()
     } else {
diff --git a/src/doc/trpl/traits.md b/src/doc/trpl/traits.md
index acbcb0b5dd9..d12480d7dd9 100644
--- a/src/doc/trpl/traits.md
+++ b/src/doc/trpl/traits.md
@@ -145,7 +145,7 @@ As you can see, `print_area` is now generic, but also ensures that we
 have passed in the correct types. If we pass in an incorrect type:
 
 ```{rust,ignore}
-print_area(5i);
+print_area(5);
 ```
 
 We get a compile-time error:
@@ -156,14 +156,14 @@ error: failed to find an implementation of trait main::HasArea for int
 
 So far, we've only added trait implementations to structs, but you can
 implement a trait for any type. So technically, we _could_ implement
-`HasArea` for `int`:
+`HasArea` for `i32`:
 
 ```{rust}
 trait HasArea {
     fn area(&self) -> f64;
 }
 
-impl HasArea for int {
+impl HasArea for i32 {
     fn area(&self) -> f64 {
         println!("this is silly");
 
@@ -171,7 +171,7 @@ impl HasArea for int {
     }
 }
 
-5i.area();
+5.area();
 ```
 
 It is considered poor style to implement methods on such primitive types, even
@@ -264,8 +264,8 @@ it won't affect you, unless you `use` that trait.
 
 There's one more restriction on implementing traits. Either the trait or the
 type you're writing the `impl` for must be inside your crate. So, we could
-implement the `HasArea` type for `int`, because `HasArea` is in our crate.  But
-if we tried to implement `Float`, a trait provided by Rust, for `int`, we could
+implement the `HasArea` type for `i32`, because `HasArea` is in our crate.  But
+if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could
 not, because both the trait and the type aren't in our crate.
 
 One last thing about traits: generic functions with a trait bound use
@@ -315,3 +315,76 @@ The names don't actually change to this, it's just for illustration. But
 as you can see, there's no overhead of deciding which version to call here,
 hence *statically dispatched*. The downside is that we have two copies of
 the same function, so our binary is a little bit larger.
+
+## Our `inverse` Example
+
+Back in [Generics](generics.html), we were trying to write code like this:
+
+```{rust,ignore}
+fn inverse<T>(x: T) -> Result<T, String> {
+    if x == 0.0 { return Err("x cannot be zero!".to_string()); }
+
+    Ok(1.0 / x)
+}
+```
+
+If we try to compile it, we get this error:
+
+```text
+error: binary operation `==` cannot be applied to type `T`
+```
+
+This is because `T` is too generic: we don't know if a random `T` can be
+compared. For that, we can use trait bounds. It doesn't quite work, but try
+this:
+
+```{rust,ignore}
+fn inverse<T: PartialEq>(x: T) -> Result<T, String> {
+    if x == 0.0 { return Err("x cannot be zero!".to_string()); }
+
+    Ok(1.0 / x)
+}
+```
+
+You should get this error:
+
+```text
+error: mismatched types:
+ expected `T`,
+    found `_`
+(expected type parameter,
+    found floating-point variable)
+```
+
+So this won't work. While our `T` is `PartialEq`, we expected to have another `T`,
+but instead, we found a floating-point variable. We need a different bound. `Float`
+to the rescue:
+
+```
+use std::num::Float;
+
+fn inverse<T: Float>(x: T) -> Result<T, String> {
+    if x == Float::zero() { return Err("x cannot be zero!".to_string()) }
+
+    let one: T = Float::one();
+    Ok(one / x)
+}
+```
+
+We've had to replace our generic `0.0` and `1.0` with the appropriate methods
+from the `Float` trait. Both `f32` and `f64` implement `Float`, so our function
+works just fine:
+
+```
+# use std::num::Float;
+# fn inverse<T: Float>(x: T) -> Result<T, String> {
+#     if x == Float::zero() { return Err("x cannot be zero!".to_string()) }
+#     let one: T = Float::one();
+#     Ok(one / x)
+# }
+println!("the inverse of {} is {:?}", 2.0f32, inverse(2.0f32));
+println!("the inverse of {} is {:?}", 2.0f64, inverse(2.0f64));
+
+println!("the inverse of {} is {:?}", 0.0f32, inverse(0.0f32));
+println!("the inverse of {} is {:?}", 0.0f64, inverse(0.0f64));
+```
diff --git a/src/doc/trpl/unsafe.md b/src/doc/trpl/unsafe.md
index 38427875a62..de6d311be57 100644
--- a/src/doc/trpl/unsafe.md
+++ b/src/doc/trpl/unsafe.md
@@ -1,4 +1,4 @@
-% Writing Unsafe and Low-Level Code in Rust
+% Unsafe and Low-Level Code
 
 # Introduction
 
@@ -95,7 +95,7 @@ offered by the Rust language and libraries. For example, they
   use-after-free;
 - are considered sendable (if their contents is considered sendable),
   so the compiler offers no assistance with ensuring their use is
-  thread-safe; for example, one can concurrently access a `*mut int`
+  thread-safe; for example, one can concurrently access a `*mut i32`
   from two threads without synchronization.
 - lack any form of lifetimes, unlike `&`, and so the compiler cannot
   reason about dangling pointers; and
@@ -182,7 +182,7 @@ code:
 - implement the `Drop` for resource clean-up via a destructor, and use
   RAII (Resource Acquisition Is Initialization). This reduces the need
   for any manual memory management by users, and automatically ensures
-  that clean-up is always run, even when the task panics.
+  that clean-up is always run, even when the thread panics.
 - ensure that any data stored behind a raw pointer is destroyed at the
   appropriate time.
 
@@ -197,7 +197,6 @@ extern crate libc;
 use libc::{c_void, size_t, malloc, free};
 use std::mem;
 use std::ptr;
-# use std::boxed::Box;
 
 // Define a wrapper around the handle returned by the foreign code.
 // Unique<T> has the same semantics as Box<T>
@@ -266,12 +265,12 @@ impl<T: Send> Drop for Unique<T> {
 // A comparison between the built-in `Box` and this reimplementation
 fn main() {
     {
-        let mut x = Box::new(5i);
+        let mut x = Box::new(5);
         *x = 10;
     } // `x` is freed here
 
     {
-        let mut y = Unique::new(5i);
+        let mut y = Unique::new(5);
         *y.borrow_mut() = 10;
     } // `y` is freed here
 }
@@ -368,7 +367,7 @@ expressions must be mutable lvalues:
 ```
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn add(a: int, b: int) -> int {
+fn add(a: i32, b: i32) -> i32 {
     let mut c = 0;
     unsafe {
         asm!("add $2, $0"
@@ -379,7 +378,7 @@ fn add(a: int, b: int) -> int {
     c
 }
 # #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
-# fn add(a: int, b: int) -> int { a + b }
+# fn add(a: i32, b: i32) -> i32 { a + b }
 
 fn main() {
     assert_eq!(add(3, 14159), 14162)
@@ -455,7 +454,7 @@ extern crate libc;
 
 // Entry point for this program
 #[start]
-fn start(_argc: int, _argv: *const *const u8) -> int {
+fn start(_argc: isize, _argv: *const *const u8) -> isize {
     0
 }
 
@@ -481,7 +480,7 @@ compiler's name mangling too:
 extern crate libc;
 
 #[no_mangle] // ensure that this symbol is called `main` in the output
-pub extern fn main(argc: int, argv: *const *const u8) -> int {
+pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
     0
 }
 
@@ -499,7 +498,7 @@ library, but without it you must define your own.
 The first of these three functions, `stack_exhausted`, is invoked whenever stack
 overflow is detected.  This function has a number of restrictions about how it
 can be called and what it must do, but if the stack limit register is not being
-maintained then a task always has an "infinite stack" and this function
+maintained then a thread always has an "infinite stack" and this function
 shouldn't get triggered.
 
 The second of these three functions, `eh_personality`, is used by the
@@ -530,7 +529,6 @@ vectors provided from C, using idiomatic Rust practices.
 
 ```
 #![no_std]
-#![feature(globs)]
 #![feature(lang_items)]
 
 # extern crate libc;
@@ -554,8 +552,8 @@ pub extern fn dot_product(a: *const u32, a_len: u32,
     // cannot tell the pointers are valid.
     let (a_slice, b_slice): (&[u32], &[u32]) = unsafe {
         mem::transmute((
-            Slice { data: a, len: a_len as uint },
-            Slice { data: b, len: b_len as uint },
+            Slice { data: a, len: a_len as usize },
+            Slice { data: b, len: b_len as usize },
         ))
     };
 
@@ -569,14 +567,14 @@ pub extern fn dot_product(a: *const u32, a_len: u32,
 
 #[lang = "panic_fmt"]
 extern fn panic_fmt(args: &core::fmt::Arguments,
-                       file: &str,
-                       line: uint) -> ! {
+                    file: &str,
+                    line: u32) -> ! {
     loop {}
 }
 
 #[lang = "stack_exhausted"] extern fn stack_exhausted() {}
 #[lang = "eh_personality"] extern fn eh_personality() {}
-# #[start] fn start(argc: int, argv: *const *const u8) -> int { 0 }
+# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 }
 # fn main() {}
 ```
 
@@ -630,7 +628,7 @@ via a declaration like
 extern "rust-intrinsic" {
     fn transmute<T, U>(x: T) -> U;
 
-    fn offset<T>(dst: *const T, offset: int) -> *const T;
+    fn offset<T>(dst: *const T, offset: isize) -> *const T;
 }
 ```
 
@@ -667,24 +665,24 @@ extern {
 pub struct Box<T>(*mut T);
 
 #[lang="exchange_malloc"]
-unsafe fn allocate(size: uint, _align: uint) -> *mut u8 {
+unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
     let p = libc::malloc(size as libc::size_t) as *mut u8;
 
     // malloc failed
-    if p as uint == 0 {
+    if p as usize == 0 {
         abort();
     }
 
     p
 }
 #[lang="exchange_free"]
-unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
+unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
     libc::free(ptr as *mut libc::c_void)
 }
 
 #[start]
-fn main(argc: int, argv: *const *const u8) -> int {
-    let x = box 1i;
+fn main(argc: isize, argv: *const *const u8) -> isize {
+    let x = box 1;
 
     0
 }
diff --git a/src/doc/trpl/variable-bindings.md b/src/doc/trpl/variable-bindings.md
index aa99caa731f..41c0e9de9b5 100644
--- a/src/doc/trpl/variable-bindings.md
+++ b/src/doc/trpl/variable-bindings.md
@@ -1,4 +1,4 @@
-% Variable bindings
+% Variable Bindings
 
 The first thing we'll learn about are *variable bindings*. They look like this:
 
@@ -89,25 +89,7 @@ what you need, so it's not verboten.
 
 Let's get back to bindings. Rust variable bindings have one more aspect that
 differs from other languages: bindings are required to be initialized with a
-value before you're allowed to use them. If we try...
-
-```{ignore}
-let x;
-```
-
-...we'll get an error:
-
-```text
-src/main.rs:2:9: 2:10 error: cannot determine a type for this local variable: unconstrained type
-src/main.rs:2     let x;
-                      ^
-```
-
-Giving it a type will compile, though:
-
-```{rust}
-let x: i32;
-```
+value before you're allowed to use them.
 
 Let's try it out. Change your `src/main.rs` file to look like this:
 
diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md
index f6e64d89960..87f3a0c765c 100644
--- a/src/doc/tutorial.md
+++ b/src/doc/tutorial.md
@@ -1,3 +1,3 @@
 % The Rust Tutorial
 
-This tutorial has been deprecated in favor of [the Guide](guide.html). Go check that out instead!
+This tutorial has been deprecated in favor of [the Book](book/index.html). Go check that out instead!
diff --git a/src/driver/driver.rs b/src/driver/driver.rs
index 5c29cb4ec72..5f086280a65 100644
--- a/src/driver/driver.rs
+++ b/src/driver/driver.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(unstable)]
+
 #[cfg(rustdoc)]
 extern crate "rustdoc" as this;
 
diff --git a/src/etc/emacs/rust-mode.el b/src/etc/emacs/rust-mode.el
index 661dc21e2dc..f25a59015fc 100644
--- a/src/etc/emacs/rust-mode.el
+++ b/src/etc/emacs/rust-mode.el
@@ -31,6 +31,11 @@
     (modify-syntax-entry ?\" "\"" table)
     (modify-syntax-entry ?\\ "\\" table)
 
+    ;; mark _ as a word constituent so that identifiers
+    ;; such as xyz_type don't cause type to be highlighted
+    ;; as a keyword
+    (modify-syntax-entry ?_ "w" table)
+
     ;; Comments
     (modify-syntax-entry ?/  ". 124b" table)
     (modify-syntax-entry ?*  ". 23"   table)
diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim
index 678cb3e1602..a37b7b6d57d 100644
--- a/src/etc/vim/syntax/rust.vim
+++ b/src/etc/vim/syntax/rust.vim
@@ -59,7 +59,7 @@ syn match rustMacroVariable "$\w\+"
 syn keyword   rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override macro
 
 " Built-in types {{{2
-syn keyword   rustType        int isize uint usize float char bool u8 u16 u32 u64 f32
+syn keyword   rustType        isize usize float char bool u8 u16 u32 u64 f32
 syn keyword   rustType        f64 i8 i16 i32 i64 str Self
 
 " Things from the prelude (src/libstd/prelude.rs) {{{2
@@ -95,8 +95,6 @@ syn keyword rustTrait Vec
 syn keyword rustTrait Path GenericPath
 " FIXME: remove when I/O reform lands
 syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude
-" FIXME: remove when range syntax lands
-syn keyword rustFunction range
 
 " Other syntax {{{2
 syn keyword   rustSelf        self
@@ -139,10 +137,10 @@ syn region    rustAttribute   start="#!\?\[" end="\]" contains=rustString,rustDe
 syn region    rustDerive      start="derive(" end=")" contained contains=rustTrait
 
 " Number literals
-syn match     rustDecNumber   display "\<[0-9][0-9_]*\%([iu]\%(8\|16\|32\|64\)\=\)\="
-syn match     rustHexNumber   display "\<0x[a-fA-F0-9_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
-syn match     rustOctNumber   display "\<0o[0-7_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
-syn match     rustBinNumber   display "\<0b[01_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
+syn match     rustDecNumber   display "\<[0-9][0-9_]*\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match     rustHexNumber   display "\<0x[a-fA-F0-9_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match     rustOctNumber   display "\<0o[0-7_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match     rustBinNumber   display "\<0b[01_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
 
 " Special case for numbers of the form "1." which are float literals, unless followed by
 " an identifier, which makes them integer literals with a method call or field access,
diff --git a/src/grammar/RustLexer.g4 b/src/grammar/RustLexer.g4
index 88de5db41fe..7d071d5e724 100644
--- a/src/grammar/RustLexer.g4
+++ b/src/grammar/RustLexer.g4
@@ -194,8 +194,13 @@ LIT_STR_RAW
   : 'r' LIT_STR_RAW_INNER SUFFIX?
   ;
 
+
+QUESTION : '?';
+
 IDENT : XID_start XID_continue* ;
 
+fragment QUESTION_IDENTIFIER : QUESTION? IDENT;
+
 LIFETIME : '\'' IDENT ;
 
 WHITESPACE : [ \r\n\t]+ ;
diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs
index 9194c7a4766..e9409a61061 100644
--- a/src/grammar/verify.rs
+++ b/src/grammar/verify.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(globs, plugin)]
+#![feature(plugin)]
 
 extern crate syntax;
 extern crate rustc;
@@ -107,13 +107,14 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
             "LE"                => token::Le,
             "LIT_BINARY"        => token::Literal(token::Binary(Name(0)), None),
             "LIT_BINARY_RAW"    => token::Literal(token::BinaryRaw(Name(0), 0), None),
+            "QUESTION"          => token::Question,
             _                   => continue,
         };
 
         res.insert(num.to_string(), tok);
     }
 
-    debug!("Token map: {}", res);
+    debug!("Token map: {:?}", res);
     res
 }
 
@@ -161,7 +162,7 @@ fn fixchar(mut lit: &str) -> ast::Name {
     parse::token::intern(lit.slice(1, lit.len() - 1))
 }
 
-fn count(lit: &str) -> uint {
+fn count(lit: &str) -> usize {
     lit.chars().take_while(|c| *c == '#').count()
 }
 
@@ -176,12 +177,12 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>) -> TokenAn
     let toknum = m.name("toknum").unwrap_or("");
     let content = m.name("content").unwrap_or("");
 
-    let proto_tok = tokens.get(toknum).expect(format!("didn't find token {} in the map",
+    let proto_tok = tokens.get(toknum).expect(format!("didn't find token {:?} in the map",
                                                               toknum).as_slice());
 
     let nm = parse::token::intern(content);
 
-    debug!("What we got: content (`{}`), proto: {}", content, proto_tok);
+    debug!("What we got: content (`{}`), proto: {:?}", content, proto_tok);
 
     let real_tok = match *proto_tok {
         token::BinOp(..)           => token::BinOp(str_to_binop(content)),
@@ -265,7 +266,7 @@ fn main() {
             continue
         }
 
-        assert!(rustc_tok.sp == antlr_tok.sp, "{} and {} have different spans", rustc_tok,
+        assert!(rustc_tok.sp == antlr_tok.sp, "{:?} and {:?} have different spans", rustc_tok,
                 antlr_tok);
 
         macro_rules! matches {
@@ -276,12 +277,12 @@ fn main() {
                             if !tok_cmp(&rustc_tok.tok, &antlr_tok.tok) {
                                 // FIXME #15677: needs more robust escaping in
                                 // antlr
-                                warn!("Different names for {} and {}", rustc_tok, antlr_tok);
+                                warn!("Different names for {:?} and {:?}", rustc_tok, antlr_tok);
                             }
                         }
-                        _ => panic!("{} is not {}", antlr_tok, rustc_tok)
+                        _ => panic!("{:?} is not {:?}", antlr_tok, rustc_tok)
                     },)*
-                    ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok)
+                    ref c => assert!(c == &antlr_tok.tok, "{:?} is not {:?}", rustc_tok, antlr_tok)
                 }
             )
         }
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 290dd21d666..c0cd034abfa 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -137,8 +137,8 @@ unsafe impl<T: Sync + Send> Send for Weak<T> { }
 unsafe impl<T: Sync + Send> Sync for Weak<T> { }
 
 struct ArcInner<T> {
-    strong: atomic::AtomicUint,
-    weak: atomic::AtomicUint,
+    strong: atomic::AtomicUsize,
+    weak: atomic::AtomicUsize,
     data: T,
 }
 
@@ -161,8 +161,8 @@ impl<T> Arc<T> {
         // Start the weak pointer count as 1 which is the weak pointer that's
         // held by all the strong pointers (kinda), see std/rc.rs for more info
         let x = box ArcInner {
-            strong: atomic::AtomicUint::new(1),
-            weak: atomic::AtomicUint::new(1),
+            strong: atomic::AtomicUsize::new(1),
+            weak: atomic::AtomicUsize::new(1),
             data: data,
         };
         Arc { _ptr: unsafe { NonZero::new(mem::transmute(x)) } }
@@ -619,7 +619,7 @@ mod tests {
     use super::{Arc, Weak, weak_count, strong_count};
     use std::sync::Mutex;
 
-    struct Canary(*mut atomic::AtomicUint);
+    struct Canary(*mut atomic::AtomicUsize);
 
     impl Drop for Canary
     {
@@ -743,16 +743,16 @@ mod tests {
 
     #[test]
     fn drop_arc() {
-        let mut canary = atomic::AtomicUint::new(0);
-        let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint));
+        let mut canary = atomic::AtomicUsize::new(0);
+        let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize));
         drop(x);
         assert!(canary.load(Acquire) == 1);
     }
 
     #[test]
     fn drop_arc_weak() {
-        let mut canary = atomic::AtomicUint::new(0);
-        let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint));
+        let mut canary = atomic::AtomicUsize::new(0);
+        let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize));
         let arc_weak = arc.downgrade();
         assert!(canary.load(Acquire) == 0);
         drop(arc);
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 458eb3dce57..8ad0c152dc8 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -117,14 +117,6 @@ impl<T: ?Sized + Ord> Ord for Box<T> {
 #[stable]
 impl<T: ?Sized + Eq> Eq for Box<T> {}
 
-#[cfg(stage0)]
-impl<S: hash::Writer, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 02933c763ef..b7bc1b47646 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -119,7 +119,8 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
           not(feature = "external_crate"),
           any(target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel")))]
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 const MIN_ALIGN: uint = 8;
 #[cfg(all(not(feature = "external_funcs"),
           not(feature = "external_crate"),
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 4a85637625a..811e32e747d 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -66,8 +66,10 @@
 
 #![no_std]
 #![allow(unknown_features)]
+#![allow(unstable)]
 #![feature(lang_items, unsafe_destructor)]
 #![feature(box_syntax)]
+#![feature(optin_builtin_traits)]
 #![allow(unknown_features)] #![feature(int_uint)]
 
 #[macro_use]
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index f42c6dbdc15..7191a7af346 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -174,6 +174,7 @@ struct RcBox<T> {
 /// See the [module level documentation](../index.html) for more details.
 #[unsafe_no_drop_flag]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct Rc<T> {
     // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
     // type via Deref
@@ -182,6 +183,24 @@ pub struct Rc<T> {
     _noshare: marker::NoSync
 }
 
+/// An immutable reference-counted pointer type.
+///
+/// See the [module level documentation](../index.html) for more details.
+#[unsafe_no_drop_flag]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct Rc<T> {
+    // FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
+    // type via Deref
+    _ptr: NonZero<*mut RcBox<T>>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<T> !marker::Send for Rc<T> {}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<T> !marker::Sync for Rc<T> {}
+
 impl<T> Rc<T> {
     /// Constructs a new `Rc<T>`.
     ///
@@ -193,6 +212,7 @@ impl<T> Rc<T> {
     /// let five = Rc::new(5i);
     /// ```
     #[stable]
+    #[cfg(stage0)] // NOTE remove after next snapshot
     pub fn new(value: T) -> Rc<T> {
         unsafe {
             Rc {
@@ -210,6 +230,32 @@ impl<T> Rc<T> {
         }
     }
 
+    /// Constructs a new `Rc<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    /// ```
+    #[stable]
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    pub fn new(value: T) -> Rc<T> {
+        unsafe {
+            Rc {
+                // there is an implicit weak pointer owned by all the strong pointers, which
+                // ensures that the weak destructor never frees the allocation while the strong
+                // destructor is running, even if the weak pointer is stored inside the strong one.
+                _ptr: NonZero::new(transmute(box RcBox {
+                    value: value,
+                    strong: Cell::new(1),
+                    weak: Cell::new(1)
+                })),
+            }
+        }
+    }
+
     /// Downgrades the `Rc<T>` to a `Weak<T>` reference.
     ///
     /// # Examples
@@ -221,6 +267,7 @@ impl<T> Rc<T> {
     ///
     /// let weak_five = five.downgrade();
     /// ```
+    #[cfg(stage0)] // NOTE remove after next snapshot
     #[unstable = "Weak pointers may not belong in this module"]
     pub fn downgrade(&self) -> Weak<T> {
         self.inc_weak();
@@ -230,6 +277,24 @@ impl<T> Rc<T> {
             _noshare: marker::NoSync
         }
     }
+
+    /// Downgrades the `Rc<T>` to a `Weak<T>` reference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    ///
+    /// let weak_five = five.downgrade();
+    /// ```
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    #[unstable = "Weak pointers may not belong in this module"]
+    pub fn downgrade(&self) -> Weak<T> {
+        self.inc_weak();
+        Weak { _ptr: self._ptr }
+    }
 }
 
 /// Get the number of weak references to this value.
@@ -432,10 +497,31 @@ impl<T> Clone for Rc<T> {
     /// five.clone();
     /// ```
     #[inline]
+    #[cfg(stage0)] // NOTE remove after next snapshot
     fn clone(&self) -> Rc<T> {
         self.inc_strong();
         Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
     }
+
+    /// Makes a clone of the `Rc<T>`.
+    ///
+    /// This increases the strong reference count.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    ///
+    /// five.clone();
+    /// ```
+    #[inline]
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn clone(&self) -> Rc<T> {
+        self.inc_strong();
+        Rc { _ptr: self._ptr }
+    }
 }
 
 #[stable]
@@ -600,14 +686,6 @@ impl<T: Ord> Ord for Rc<T> {
 }
 
 // FIXME (#18248) Make `T` `Sized?`
-#[cfg(stage0)]
-impl<S: hash::Writer, T: Hash<S>> Hash<S> for Rc<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
@@ -636,6 +714,7 @@ impl<T: fmt::String> fmt::String for Rc<T> {
 /// See the [module level documentation](../index.html) for more.
 #[unsafe_no_drop_flag]
 #[unstable = "Weak pointers may not belong in this module."]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct Weak<T> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -644,6 +723,29 @@ pub struct Weak<T> {
     _noshare: marker::NoSync
 }
 
+/// A weak version of `Rc<T>`.
+///
+/// Weak references do not count when determining if the inner value should be dropped.
+///
+/// See the [module level documentation](../index.html) for more.
+#[unsafe_no_drop_flag]
+#[unstable = "Weak pointers may not belong in this module."]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct Weak<T> {
+    // FIXME #12808: strange names to try to avoid interfering with
+    // field accesses of the contained type via Deref
+    _ptr: NonZero<*mut RcBox<T>>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+#[allow(unstable)]
+impl<T> !marker::Send for Weak<T> {}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+#[allow(unstable)]
+impl<T> !marker::Sync for Weak<T> {}
+
+
 #[unstable = "Weak pointers may not belong in this module."]
 impl<T> Weak<T> {
     /// Upgrades a weak reference to a strong reference.
@@ -663,6 +765,7 @@ impl<T> Weak<T> {
     ///
     /// let strong_five: Option<Rc<_>> = weak_five.upgrade();
     /// ```
+    #[cfg(stage0)] // NOTE remove after next snapshot
     pub fn upgrade(&self) -> Option<Rc<T>> {
         if self.strong() == 0 {
             None
@@ -671,6 +774,33 @@ impl<T> Weak<T> {
             Some(Rc { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync })
         }
     }
+
+    /// Upgrades a weak reference to a strong reference.
+    ///
+    /// Upgrades the `Weak<T>` reference to an `Rc<T>`, if possible.
+    ///
+    /// Returns `None` if there were no strong references and the data was destroyed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let five = Rc::new(5i);
+    ///
+    /// let weak_five = five.downgrade();
+    ///
+    /// let strong_five: Option<Rc<_>> = weak_five.upgrade();
+    /// ```
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    pub fn upgrade(&self) -> Option<Rc<T>> {
+        if self.strong() == 0 {
+            None
+        } else {
+            self.inc_strong();
+            Some(Rc { _ptr: self._ptr })
+        }
+    }
 }
 
 #[unsafe_destructor]
@@ -733,10 +863,31 @@ impl<T> Clone for Weak<T> {
     /// weak_five.clone();
     /// ```
     #[inline]
+    #[cfg(stage0)] // NOTE remove after next snapshot
     fn clone(&self) -> Weak<T> {
         self.inc_weak();
         Weak { _ptr: self._ptr, _nosend: marker::NoSend, _noshare: marker::NoSync }
     }
+
+    /// Makes a clone of the `Weak<T>`.
+    ///
+    /// This increases the weak reference count.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let weak_five = Rc::new(5i).downgrade();
+    ///
+    /// weak_five.clone();
+    /// ```
+    #[inline]
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn clone(&self) -> Weak<T> {
+        self.inc_weak();
+        Weak { _ptr: self._ptr }
+    }
 }
 
 #[unstable = "Show is experimental."]
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index e3d075c0f39..7458cc60c15 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -34,6 +34,7 @@
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![allow(missing_docs)]
+#![allow(unstable)]
 
 extern crate alloc;
 
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index c1b34c52fcc..efd056b0d66 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -156,7 +156,7 @@ static FALSE: bool = false;
 /// println!("{:?}", bv);
 /// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
 /// ```
-#[stable]
+#[unstable = "RFC 509"]
 pub struct Bitv {
     /// Internal representation of the bit vector
     storage: Vec<u32>,
@@ -1107,7 +1107,7 @@ impl<'a> RandomAccessIterator for Iter<'a> {
 /// assert!(bv[3]);
 /// ```
 #[derive(Clone)]
-#[stable]
+#[unstable = "RFC 509"]
 pub struct BitvSet {
     bitv: Bitv,
 }
@@ -2526,7 +2526,7 @@ mod bitv_bench {
             for _ in range(0u, 100) {
                 bitv |= 1 << ((r.next_u32() as uint) % u32::BITS);
             }
-            black_box(&bitv)
+            black_box(&bitv);
         });
     }
 
@@ -2538,7 +2538,7 @@ mod bitv_bench {
             for _ in range(0u, 100) {
                 bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
             }
-            black_box(&bitv)
+            black_box(&bitv);
         });
     }
 
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 3e1533dd35f..3ac6b2775bf 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -24,8 +24,6 @@ use core::cmp::Ordering;
 use core::default::Default;
 use core::fmt::Show;
 use core::hash::{Hash, Hasher};
-#[cfg(stage0)]
-use core::hash::Writer;
 use core::iter::{Map, FromIterator};
 use core::ops::{Index, IndexMut};
 use core::{iter, fmt, mem};
@@ -822,16 +820,6 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
 }
 
 #[stable]
-#[cfg(stage0)]
-impl<S: Writer, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
-    fn hash(&self, state: &mut S) {
-        for elt in self.iter() {
-            elt.hash(state);
-        }
-    }
-}
-#[stable]
-#[cfg(not(stage0))]
 impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
     fn hash(&self, state: &mut S) {
         for elt in self.iter() {
@@ -1422,7 +1410,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
 #[cfg(test)]
 mod test {
     use prelude::*;
-    use std::borrow::BorrowFrom;
 
     use super::{BTreeMap, Occupied, Vacant};
 
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index 812cff6fab7..6e048e0e83c 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -18,6 +18,8 @@ use core::cmp::Ordering::{self, Less, Greater, Equal};
 use core::default::Default;
 use core::fmt::Show;
 use core::fmt;
+// NOTE(stage0) remove import after a snapshot
+#[cfg(stage0)]
 use core::hash::Hash;
 use core::iter::{Peekable, Map, FromIterator};
 use core::ops::{BitOr, BitAnd, BitXor, Sub};
diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs
index 0b426f6016c..cce8cf398e1 100644
--- a/src/libcollections/dlist.rs
+++ b/src/libcollections/dlist.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -221,13 +221,16 @@ impl<T> DList<T> {
         DList{list_head: None, list_tail: Rawlink::none(), length: 0}
     }
 
-    /// Adds all elements from `other` to the end of the list.
+    /// Moves all elements from `other` to the end of the list.
     ///
-    /// This operation should compute in O(1) time.
+    /// This reuses all the nodes from `other` and moves them into `self`. After
+    /// this operation, `other` becomes empty.
+    ///
+    /// This operation should compute in O(1) time and O(1) memory.
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::collections::DList;
     ///
     /// let mut a = DList::new();
@@ -237,16 +240,20 @@ impl<T> DList<T> {
     /// b.push_back(3i);
     /// b.push_back(4);
     ///
-    /// a.append(b);
+    /// a.append(&mut b);
     ///
     /// for e in a.iter() {
     ///     println!("{}", e); // prints 1, then 2, then 3, then 4
     /// }
+    /// println!("{}", b.len()); // prints 0
     /// ```
-    #[unstable = "append should be by-mutable-reference"]
-    pub fn append(&mut self, mut other: DList<T>) {
+    pub fn append(&mut self, other: &mut DList<T>) {
         match self.list_tail.resolve() {
-            None => *self = other,
+            None => {
+                self.length = other.length;
+                self.list_head = other.list_head.take();
+                self.list_tail = other.list_tail.take();
+            },
             Some(tail) => {
                 // Carefully empty `other`.
                 let o_tail = other.list_tail.take();
@@ -261,6 +268,7 @@ impl<T> DList<T> {
                 }
             }
         }
+        other.length = 0;
     }
 
     /// Provides a forward iterator.
@@ -296,6 +304,18 @@ impl<T> DList<T> {
     /// Returns `true` if the `DList` is empty.
     ///
     /// This operation should compute in O(1) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    /// assert!(dl.is_empty());
+    ///
+    /// dl.push_front("foo");
+    /// assert!(!dl.is_empty());
+    /// ```
     #[inline]
     #[stable]
     pub fn is_empty(&self) -> bool {
@@ -305,6 +325,24 @@ impl<T> DList<T> {
     /// Returns the length of the `DList`.
     ///
     /// This operation should compute in O(1) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    ///
+    /// dl.push_front(2is);
+    /// assert_eq!(dl.len(), 1);
+    ///
+    /// dl.push_front(1);
+    /// assert_eq!(dl.len(), 2);
+    ///
+    /// dl.push_back(3);
+    /// assert_eq!(dl.len(), 3);
+    ///
+    /// ```
     #[inline]
     #[stable]
     pub fn len(&self) -> uint {
@@ -314,6 +352,24 @@ impl<T> DList<T> {
     /// Removes all elements from the `DList`.
     ///
     /// This operation should compute in O(n) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    ///
+    /// dl.push_front(2is);
+    /// dl.push_front(1);
+    /// assert_eq!(dl.len(), 2);
+    /// assert_eq!(dl.front(), Some(&1is));
+    ///
+    /// dl.clear();
+    /// assert_eq!(dl.len(), 0);
+    /// assert_eq!(dl.front(), None);
+    ///
+    /// ```
     #[inline]
     #[stable]
     pub fn clear(&mut self) {
@@ -322,6 +378,19 @@ impl<T> DList<T> {
 
     /// Provides a reference to the front element, or `None` if the list is
     /// empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    /// assert_eq!(dl.front(), None);
+    ///
+    /// dl.push_front(1);
+    /// assert_eq!(dl.front(), Some(&1is));
+    ///
+    /// ```
     #[inline]
     #[stable]
     pub fn front(&self) -> Option<&T> {
@@ -330,6 +399,25 @@ impl<T> DList<T> {
 
     /// Provides a mutable reference to the front element, or `None` if the list
     /// is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    /// assert_eq!(dl.front(), None);
+    ///
+    /// dl.push_front(1);
+    /// assert_eq!(dl.front(), Some(&1is));
+    ///
+    /// match dl.front_mut() {
+    ///     None => {},
+    ///     Some(x) => *x = 5is,
+    /// }
+    /// assert_eq!(dl.front(), Some(&5is));
+    ///
+    /// ```
     #[inline]
     #[stable]
     pub fn front_mut(&mut self) -> Option<&mut T> {
@@ -338,6 +426,19 @@ impl<T> DList<T> {
 
     /// Provides a reference to the back element, or `None` if the list is
     /// empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    /// assert_eq!(dl.back(), None);
+    ///
+    /// dl.push_back(1);
+    /// assert_eq!(dl.back(), Some(&1is));
+    ///
+    /// ```
     #[inline]
     #[stable]
     pub fn back(&self) -> Option<&T> {
@@ -346,6 +447,25 @@ impl<T> DList<T> {
 
     /// Provides a mutable reference to the back element, or `None` if the list
     /// is empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    /// assert_eq!(dl.back(), None);
+    ///
+    /// dl.push_back(1);
+    /// assert_eq!(dl.back(), Some(&1is));
+    ///
+    /// match dl.back_mut() {
+    ///     None => {},
+    ///     Some(x) => *x = 5is,
+    /// }
+    /// assert_eq!(dl.back(), Some(&5is));
+    ///
+    /// ```
     #[inline]
     #[stable]
     pub fn back_mut(&mut self) -> Option<&mut T> {
@@ -355,6 +475,21 @@ impl<T> DList<T> {
     /// Adds an element first in the list.
     ///
     /// This operation should compute in O(1) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut dl = DList::new();
+    ///
+    /// dl.push_front(2is);
+    /// assert_eq!(dl.front().unwrap(), &2is);
+    ///
+    /// dl.push_front(1);
+    /// assert_eq!(dl.front().unwrap(), &1);
+    ///
+    /// ```
     #[stable]
     pub fn push_front(&mut self, elt: T) {
         self.push_front_node(box Node::new(elt))
@@ -364,6 +499,23 @@ impl<T> DList<T> {
     /// empty.
     ///
     /// This operation should compute in O(1) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut d = DList::new();
+    /// assert_eq!(d.pop_front(), None);
+    ///
+    /// d.push_front(1is);
+    /// d.push_front(3);
+    /// assert_eq!(d.pop_front(), Some(3));
+    /// assert_eq!(d.pop_front(), Some(1));
+    /// assert_eq!(d.pop_front(), None);
+    ///
+    /// ```
+    ///
     #[stable]
     pub fn pop_front(&mut self) -> Option<T> {
         self.pop_front_node().map(|box Node{value, ..}| value)
@@ -373,7 +525,7 @@ impl<T> DList<T> {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::collections::DList;
     ///
     /// let mut d = DList::new();
@@ -391,7 +543,7 @@ impl<T> DList<T> {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::collections::DList;
     ///
     /// let mut d = DList::new();
@@ -404,6 +556,67 @@ impl<T> DList<T> {
     pub fn pop_back(&mut self) -> Option<T> {
         self.pop_back_node().map(|box Node{value, ..}| value)
     }
+
+    /// Splits the list into two at the given index. Returns everything after the given index,
+    /// including the index.
+    ///
+    /// This operation should compute in O(n) time.
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::DList;
+    ///
+    /// let mut d = DList::new();
+    ///
+    /// d.push_front(1is);
+    /// d.push_front(2);
+    /// d.push_front(3);
+    ///
+    /// let mut splitted = d.split_off(2);
+    ///
+    /// assert_eq!(splitted.pop_front(), Some(1));
+    /// assert_eq!(splitted.pop_front(), None);
+    /// ```
+    #[stable]
+    pub fn split_off(&mut self, at: uint) -> DList<T> {
+        let len = self.len();
+        assert!(at < len, "Cannot split off at a nonexistent index");
+        if at == 0 {
+            return mem::replace(self, DList::new());
+        }
+
+        // Below, we iterate towards the `i-1`th node, either from the start or the end,
+        // depending on which would be faster.
+        let mut split_node = if at - 1 <= len - 1 - (at - 1) {
+            let mut iter = self.iter_mut();
+            // instead of skipping using .skip() (which creates a new struct),
+            // we skip manually so we can access the head field without
+            // depending on implementation details of Skip
+            for _ in range(0, at - 1) {
+                iter.next();
+            }
+            iter.head
+        }  else {
+            // better off starting from the end
+            let mut iter = self.iter_mut();
+            for _ in range(0, len - 1 - (at - 1)) {
+                iter.next_back();
+            }
+            iter.tail
+        };
+
+        let mut splitted_list = DList {
+            list_head: None,
+            list_tail: self.list_tail,
+            length: len - at
+        };
+
+        mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
+        self.list_tail = split_node;
+        self.length = at;
+
+        splitted_list
+    }
 }
 
 #[unsafe_destructor]
@@ -540,7 +753,7 @@ impl<'a, A> IterMut<'a, A> {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::collections::DList;
     ///
     /// let mut list: DList<int> = vec![1, 3, 4].into_iter().collect();
@@ -566,7 +779,7 @@ impl<'a, A> IterMut<'a, A> {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::collections::DList;
     ///
     /// let mut list: DList<int> = vec![1, 2, 3].into_iter().collect();
@@ -778,6 +991,108 @@ mod tests {
     }
 
     #[test]
+    fn test_append() {
+        // Empty to empty
+        {
+            let mut m: DList<int> = DList::new();
+            let mut n = DList::new();
+            m.append(&mut n);
+            check_links(&m);
+            assert_eq!(m.len(), 0);
+            assert_eq!(n.len(), 0);
+        }
+        // Non-empty to empty
+        {
+            let mut m = DList::new();
+            let mut n = DList::new();
+            n.push_back(2i);
+            m.append(&mut n);
+            check_links(&m);
+            assert_eq!(m.len(), 1);
+            assert_eq!(m.pop_back(), Some(2));
+            assert_eq!(n.len(), 0);
+            check_links(&m);
+        }
+        // Empty to non-empty
+        {
+            let mut m = DList::new();
+            let mut n = DList::new();
+            m.push_back(2i);
+            m.append(&mut n);
+            check_links(&m);
+            assert_eq!(m.len(), 1);
+            assert_eq!(m.pop_back(), Some(2));
+            check_links(&m);
+        }
+
+        // Non-empty to non-empty
+        let v = vec![1i,2,3,4,5];
+        let u = vec![9i,8,1,2,3,4,5];
+        let mut m = list_from(v.as_slice());
+        let mut n = list_from(u.as_slice());
+        m.append(&mut n);
+        check_links(&m);
+        let mut sum = v;
+        sum.push_all(u.as_slice());
+        assert_eq!(sum.len(), m.len());
+        for elt in sum.into_iter() {
+            assert_eq!(m.pop_front(), Some(elt))
+        }
+        assert_eq!(n.len(), 0);
+        // let's make sure it's working properly, since we
+        // did some direct changes to private members
+        n.push_back(3);
+        assert_eq!(n.len(), 1);
+        assert_eq!(n.pop_front(), Some(3));
+        check_links(&n);
+    }
+
+    #[test]
+    fn test_split_off() {
+        // singleton
+        {
+            let mut m = DList::new();
+            m.push_back(1i);
+
+            let p = m.split_off(0);
+            assert_eq!(m.len(), 0);
+            assert_eq!(p.len(), 1);
+            assert_eq!(p.back(), Some(&1));
+            assert_eq!(p.front(), Some(&1));
+        }
+
+        // not singleton, forwards
+        {
+            let u = vec![1i,2,3,4,5];
+            let mut m = list_from(u.as_slice());
+            let mut n = m.split_off(2);
+            assert_eq!(m.len(), 2);
+            assert_eq!(n.len(), 3);
+            for elt in range(1i, 3) {
+                assert_eq!(m.pop_front(), Some(elt));
+            }
+            for elt in range(3i, 6) {
+                assert_eq!(n.pop_front(), Some(elt));
+            }
+        }
+        // not singleton, backwards
+        {
+            let u = vec![1i,2,3,4,5];
+            let mut m = list_from(u.as_slice());
+            let mut n = m.split_off(4);
+            assert_eq!(m.len(), 4);
+            assert_eq!(n.len(), 1);
+            for elt in range(1i, 5) {
+                assert_eq!(m.pop_front(), Some(elt));
+            }
+            for elt in range(5i, 6) {
+                assert_eq!(n.pop_front(), Some(elt));
+            }
+        }
+
+    }
+
+    #[test]
     fn test_iterator() {
         let m = generate_test();
         for (i, elt) in m.iter().enumerate() {
@@ -1065,41 +1380,6 @@ mod tests {
         assert_eq!(i, v.len());
     }
 
-    #[allow(deprecated)]
-    #[test]
-    fn test_append() {
-        {
-            let mut m = DList::new();
-            let mut n = DList::new();
-            n.push_back(2i);
-            m.append(n);
-            assert_eq!(m.len(), 1);
-            assert_eq!(m.pop_back(), Some(2));
-            check_links(&m);
-        }
-        {
-            let mut m = DList::new();
-            let n = DList::new();
-            m.push_back(2i);
-            m.append(n);
-            assert_eq!(m.len(), 1);
-            assert_eq!(m.pop_back(), Some(2));
-            check_links(&m);
-        }
-
-        let v = vec![1i,2,3,4,5];
-        let u = vec![9i,8,1,2,3,4,5];
-        let mut m = list_from(v.as_slice());
-        m.append(list_from(u.as_slice()));
-        check_links(&m);
-        let mut sum = v;
-        sum.push_all(u.as_slice());
-        assert_eq!(sum.len(), m.len());
-        for elt in sum.into_iter() {
-            assert_eq!(m.pop_front(), Some(elt))
-        }
-    }
-
     #[bench]
     fn bench_collect_into(b: &mut test::Bencher) {
         let v = &[0i; 64];
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 54ab26c4f77..797042c3216 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -28,6 +28,7 @@
 #![feature(unboxed_closures)]
 #![feature(old_impl_check)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 #![no_std]
 
 #[macro_use]
@@ -70,12 +71,12 @@ pub mod string;
 pub mod vec;
 pub mod vec_map;
 
-#[stable]
+#[unstable = "RFC 509"]
 pub mod bitv {
     pub use bit::{Bitv, Iter};
 }
 
-#[stable]
+#[unstable = "RFC 509"]
 pub mod bitv_set {
     pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
     pub use bit::SetIter as Iter;
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 9a1f22ef7a6..4812ecc2c0b 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -1631,7 +1631,7 @@ mod tests {
     #[test]
     fn test_slice_from() {
         let vec: &[int] = &[1, 2, 3, 4];
-        assert_eq!(&vec[0..], vec);
+        assert_eq!(&vec[], vec);
         let b: &[int] = &[3, 4];
         assert_eq!(&vec[2..], b);
         let b: &[int] = &[];
@@ -1641,11 +1641,11 @@ mod tests {
     #[test]
     fn test_slice_to() {
         let vec: &[int] = &[1, 2, 3, 4];
-        assert_eq!(&vec[0..4], vec);
+        assert_eq!(&vec[..4], vec);
         let b: &[int] = &[1, 2];
-        assert_eq!(&vec[0..2], b);
+        assert_eq!(&vec[..2], b);
         let b: &[int] = &[];
-        assert_eq!(&vec[0..0], b);
+        assert_eq!(&vec[..0], b);
     }
 
 
@@ -2538,7 +2538,7 @@ mod tests {
             let (left, right) = values.split_at_mut(2);
             {
                 let left: &[_] = left;
-                assert!(left[0..left.len()] == [1, 2][]);
+                assert!(left[..left.len()] == [1, 2][]);
             }
             for p in left.iter_mut() {
                 *p += 1;
@@ -2546,7 +2546,7 @@ mod tests {
 
             {
                 let right: &[_] = right;
-                assert!(right[0..right.len()] == [3, 4, 5][]);
+                assert!(right[..right.len()] == [3, 4, 5][]);
             }
             for p in right.iter_mut() {
                 *p += 2;
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index ccf654ac0a0..f7668930660 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -807,7 +807,7 @@ pub trait StrExt: Index<FullRange, Output = str> {
     /// out of bounds.
     ///
     /// See also `slice`, `slice_from` and `slice_chars`.
-    #[unstable = "use slice notation [0..a] instead"]
+    #[unstable = "use slice notation [..a] instead"]
     fn slice_to(&self, end: uint) -> &str {
         core_str::StrExt::slice_to(&self[], end)
     }
@@ -2841,7 +2841,7 @@ mod bench {
         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
 
         b.iter(|| {
-            for ch in s.chars() { black_box(ch) }
+            for ch in s.chars() { black_box(ch); }
         });
     }
 
@@ -2869,7 +2869,7 @@ mod bench {
         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
 
         b.iter(|| {
-            for ch in s.chars().rev() { black_box(ch) }
+            for ch in s.chars().rev() { black_box(ch); }
         });
     }
 
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 5991fc832e9..5d35d8a8679 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -168,7 +168,7 @@ impl String {
 
         if i > 0 {
             unsafe {
-                res.as_mut_vec().push_all(&v[0..i])
+                res.as_mut_vec().push_all(&v[..i])
             };
         }
 
@@ -302,6 +302,7 @@ impl String {
     /// assert_eq!(String::from_utf16_lossy(v),
     ///            "𝄞mus\u{FFFD}ic\u{FFFD}".to_string());
     /// ```
+    #[inline]
     #[stable]
     pub fn from_utf16_lossy(v: &[u16]) -> String {
         unicode_str::utf16_items(v).map(|c| c.to_char_lossy()).collect()
@@ -556,6 +557,7 @@ impl String {
     /// assert_eq!(s.remove(1), 'o');
     /// assert_eq!(s.remove(0), 'o');
     /// ```
+    #[inline]
     #[stable]
     pub fn remove(&mut self, idx: uint) -> char {
         let len = self.len();
@@ -582,6 +584,7 @@ impl String {
     ///
     /// If `idx` does not lie on a character boundary or is out of bounds, then
     /// this function will panic.
+    #[inline]
     #[stable]
     pub fn insert(&mut self, idx: uint, ch: char) {
         let len = self.len();
@@ -618,6 +621,7 @@ impl String {
     /// }
     /// assert_eq!(s.as_slice(), "olleh");
     /// ```
+    #[inline]
     #[stable]
     pub unsafe fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec<u8> {
         &mut self.vec
@@ -645,6 +649,7 @@ impl String {
     /// v.push('a');
     /// assert!(!v.is_empty());
     /// ```
+    #[inline]
     #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
@@ -801,6 +806,7 @@ impl Str for String {
 
 #[stable]
 impl Default for String {
+    #[inline]
     #[stable]
     fn default() -> String {
         String::new()
@@ -809,6 +815,7 @@ impl Default for String {
 
 #[stable]
 impl fmt::String for String {
+    #[inline]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::String::fmt(&**self, f)
     }
@@ -816,21 +823,13 @@ impl fmt::String for String {
 
 #[unstable = "waiting on fmt stabilization"]
 impl fmt::Show for String {
+    #[inline]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Show::fmt(&**self, f)
     }
 }
 
 #[unstable = "waiting on Hash stabilization"]
-#[cfg(stage0)]
-impl<H: hash::Writer> hash::Hash<H> for String {
-    #[inline]
-    fn hash(&self, hasher: &mut H) {
-        (**self).hash(hasher)
-    }
-}
-#[unstable = "waiting on Hash stabilization"]
-#[cfg(not(stage0))]
 impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
     #[inline]
     fn hash(&self, hasher: &mut H) {
@@ -842,6 +841,7 @@ impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
 impl<'a> Add<&'a str> for String {
     type Output = String;
 
+    #[inline]
     fn add(mut self, other: &str) -> String {
         self.push_str(other);
         self
@@ -881,6 +881,7 @@ impl ops::Index<ops::FullRange> for String {
 impl ops::Deref for String {
     type Target = str;
 
+    #[inline]
     fn deref<'a>(&'a self) -> &'a str {
         unsafe { mem::transmute(&self.vec[]) }
     }
@@ -895,6 +896,7 @@ pub struct DerefString<'a> {
 impl<'a> Deref for DerefString<'a> {
     type Target = String;
 
+    #[inline]
     fn deref<'b>(&'b self) -> &'b String {
         unsafe { mem::transmute(&*self.x) }
     }
@@ -933,6 +935,7 @@ pub trait ToString {
 }
 
 impl<T: fmt::String + ?Sized> ToString for T {
+    #[inline]
     fn to_string(&self) -> String {
         use core::fmt::Writer;
         let mut buf = String::new();
@@ -943,12 +946,14 @@ impl<T: fmt::String + ?Sized> ToString for T {
 }
 
 impl IntoCow<'static, String, str> for String {
+    #[inline]
     fn into_cow(self) -> CowString<'static> {
         Cow::Owned(self)
     }
 }
 
 impl<'a> IntoCow<'a, String, str> for &'a str {
+    #[inline]
     fn into_cow(self) -> CowString<'a> {
         Cow::Borrowed(self)
     }
@@ -966,6 +971,7 @@ impl<'a> Str for CowString<'a> {
 }
 
 impl fmt::Writer for String {
+    #[inline]
     fn write_str(&mut self, s: &str) -> fmt::Result {
         self.push_str(s);
         Ok(())
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 47afc78bc12..689d96b4b29 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! A growable list type, written `Vec<T>` but pronounced 'vector.'
+//! A growable list type with heap-allocated contents, written `Vec<T>` but pronounced 'vector.'
 //!
 //! Vectors have `O(1)` indexing, push (to the end) and pop (from the end).
 //!
@@ -681,6 +681,43 @@ impl<T> Vec<T> {
         }
     }
 
+    /// Moves all the elements of `other` into `Self`, leaving `other` empty.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the number of elements in the vector overflows a `uint`.
+    ///
+    /// # Examples
+    /// ```rust
+    /// let mut vec = vec![1, 2, 3];
+    /// let mut vec2 = vec![4, 5, 6];
+    /// vec.append(&mut vec2);
+    /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
+    /// assert_eq!(vec2, vec![]);
+    /// ```
+    #[inline]
+    #[unstable = "new API, waiting for dust to settle"]
+    pub fn append(&mut self, other: &mut Self) {
+        if mem::size_of::<T>() == 0 {
+            // zero-size types consume no memory, so we can't rely on the
+            // address space running out
+            self.len = self.len.checked_add(other.len()).expect("length overflow");
+            unsafe { other.set_len(0) }
+            return;
+        }
+        self.reserve(other.len());
+        let len = self.len();
+        unsafe {
+            ptr::copy_nonoverlapping_memory(
+                self.get_unchecked_mut(len),
+                other.as_ptr(),
+                other.len());
+        }
+
+        self.len += other.len();
+        unsafe { other.set_len(0); }
+    }
+
     /// Creates a draining iterator that clears the `Vec` and iterates over
     /// the removed items from start to end.
     ///
@@ -1185,14 +1222,6 @@ impl<T:Clone> Clone for Vec<T> {
     }
 }
 
-#[cfg(stage0)]
-impl<S: hash::Writer, T: Hash<S>> Hash<S> for Vec<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.as_slice().hash(state);
-    }
-}
-#[cfg(not(stage0))]
 impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
     #[inline]
     fn hash(&self, state: &mut S) {
@@ -1511,6 +1540,9 @@ pub struct IntoIter<T> {
     end: *const T
 }
 
+unsafe impl<T: Send> Send for IntoIter<T> { }
+unsafe impl<T: Sync> Sync for IntoIter<T> { }
+
 impl<T> IntoIter<T> {
     #[inline]
     /// Drops all items that have not yet been moved and returns the empty vector.
@@ -2199,7 +2231,7 @@ mod tests {
 
     #[test]
     fn test_map_in_place_zero_drop_count() {
-        use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
+        use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 
         #[derive(Clone, PartialEq, Show)]
         struct Nothing;
@@ -2213,7 +2245,7 @@ mod tests {
             }
         }
         const NUM_ELEMENTS: uint = 2;
-        static DROP_COUNTER: AtomicUint = ATOMIC_UINT_INIT;
+        static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
 
         let v = repeat(Nothing).take(NUM_ELEMENTS).collect::<Vec<_>>();
 
@@ -2295,6 +2327,15 @@ mod tests {
         assert_eq!(ys.as_slice(), [1u, 2, 3]);
     }
 
+    #[test]
+    fn test_append() {
+        let mut vec = vec![1, 2, 3];
+        let mut vec2 = vec![4, 5, 6];
+        vec.append(&mut vec2);
+        assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
+        assert_eq!(vec2, vec![]);
+    }
+
     #[bench]
     fn bench_new(b: &mut Bencher) {
         b.iter(|| {
diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs
index e740a929252..aa93d9ed837 100644
--- a/src/libcore/atomic.rs
+++ b/src/libcore/atomic.rs
@@ -15,7 +15,7 @@
 //! types.
 //!
 //! This module defines atomic versions of a select number of primitive
-//! types, including `AtomicBool`, `AtomicInt`, `AtomicUint`, and `AtomicOption`.
+//! types, including `AtomicBool`, `AtomicIsize`, `AtomicUsize`, and `AtomicOption`.
 //! Atomic types present operations that, when used correctly, synchronize
 //! updates between threads.
 //!
@@ -41,11 +41,11 @@
 //!
 //! ```
 //! use std::sync::Arc;
-//! use std::sync::atomic::{AtomicUint, Ordering};
+//! use std::sync::atomic::{AtomicUsize, Ordering};
 //! use std::thread::Thread;
 //!
 //! fn main() {
-//!     let spinlock = Arc::new(AtomicUint::new(1));
+//!     let spinlock = Arc::new(AtomicUsize::new(1));
 //!
 //!     let spinlock_clone = spinlock.clone();
 //!     Thread::spawn(move|| {
@@ -60,9 +60,9 @@
 //! Keep a global count of live tasks:
 //!
 //! ```
-//! use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
+//! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 //!
-//! static GLOBAL_TASK_COUNT: AtomicUint = ATOMIC_UINT_INIT;
+//! static GLOBAL_TASK_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
 //!
 //! let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, Ordering::SeqCst);
 //! println!("live tasks: {}", old_task_count + 1);
@@ -80,31 +80,31 @@ use cell::UnsafeCell;
 /// A boolean type which can be safely shared between threads.
 #[stable]
 pub struct AtomicBool {
-    v: UnsafeCell<uint>,
+    v: UnsafeCell<usize>,
 }
 
 unsafe impl Sync for AtomicBool {}
 
 /// A signed integer type which can be safely shared between threads.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub struct AtomicInt {
-    v: UnsafeCell<int>,
+#[stable]
+pub struct AtomicIsize {
+    v: UnsafeCell<isize>,
 }
 
-unsafe impl Sync for AtomicInt {}
+unsafe impl Sync for AtomicIsize {}
 
 /// An unsigned integer type which can be safely shared between threads.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub struct AtomicUint {
-    v: UnsafeCell<uint>,
+#[stable]
+pub struct AtomicUsize {
+    v: UnsafeCell<usize>,
 }
 
-unsafe impl Sync for AtomicUint {}
+unsafe impl Sync for AtomicUsize {}
 
 /// A raw pointer type which can be safely shared between threads.
 #[stable]
 pub struct AtomicPtr<T> {
-    p: UnsafeCell<uint>,
+    p: UnsafeCell<usize>,
 }
 
 unsafe impl<T> Sync for AtomicPtr<T> {}
@@ -149,17 +149,17 @@ pub enum Ordering {
 #[stable]
 pub const ATOMIC_BOOL_INIT: AtomicBool =
         AtomicBool { v: UnsafeCell { value: 0 } };
-/// An `AtomicInt` initialized to `0`.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub const ATOMIC_INT_INIT: AtomicInt =
-        AtomicInt { v: UnsafeCell { value: 0 } };
-/// An `AtomicUint` initialized to `0`.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub const ATOMIC_UINT_INIT: AtomicUint =
-        AtomicUint { v: UnsafeCell { value: 0, } };
+/// An `AtomicIsize` initialized to `0`.
+#[stable]
+pub const ATOMIC_ISIZE_INIT: AtomicIsize =
+        AtomicIsize { v: UnsafeCell { value: 0 } };
+/// An `AtomicUsize` initialized to `0`.
+#[stable]
+pub const ATOMIC_USIZE_INIT: AtomicUsize =
+        AtomicUsize { v: UnsafeCell { value: 0, } };
 
 // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
-const UINT_TRUE: uint = -1;
+const UINT_TRUE: usize = -1;
 
 impl AtomicBool {
     /// Creates a new `AtomicBool`.
@@ -199,7 +199,7 @@ impl AtomicBool {
     #[inline]
     #[stable]
     pub fn load(&self, order: Ordering) -> bool {
-        unsafe { atomic_load(self.v.get() as *const uint, order) > 0 }
+        unsafe { atomic_load(self.v.get() as *const usize, order) > 0 }
     }
 
     /// Stores a value into the bool.
@@ -323,7 +323,7 @@ impl AtomicBool {
     ///
     /// let foo = AtomicBool::new(true);
     /// assert_eq!(true, foo.fetch_nand(true, Ordering::SeqCst));
-    /// assert_eq!(0, foo.load(Ordering::SeqCst) as int);
+    /// assert_eq!(0, foo.load(Ordering::SeqCst) as usize);
     /// assert_eq!(false, foo.load(Ordering::SeqCst));
     ///
     /// let foo = AtomicBool::new(false);
@@ -403,23 +403,23 @@ impl AtomicBool {
     }
 }
 
-#[unstable = "awaiting int/uint conventions, types may change"]
-impl AtomicInt {
-    /// Creates a new `AtomicInt`.
+#[stable]
+impl AtomicIsize {
+    /// Creates a new `AtomicIsize`.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::AtomicInt;
+    /// use std::sync::atomic::AtomicIsize;
     ///
-    /// let atomic_forty_two  = AtomicInt::new(42);
+    /// let atomic_forty_two  = AtomicIsize::new(42);
     /// ```
     #[inline]
-    pub fn new(v: int) -> AtomicInt {
-        AtomicInt {v: UnsafeCell::new(v)}
+    pub fn new(v: isize) -> AtomicIsize {
+        AtomicIsize {v: UnsafeCell::new(v)}
     }
 
-    /// Loads a value from the int.
+    /// Loads a value from the isize.
     ///
     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
@@ -430,58 +430,58 @@ impl AtomicInt {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_int.load(Ordering::Relaxed);
+    /// let value = some_isize.load(Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn load(&self, order: Ordering) -> int {
-        unsafe { atomic_load(self.v.get() as *const int, order) }
+    pub fn load(&self, order: Ordering) -> isize {
+        unsafe { atomic_load(self.v.get() as *const isize, order) }
     }
 
-    /// Stores a value into the int.
+    /// Stores a value into the isize.
     ///
     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// some_int.store(10, Ordering::Relaxed);
+    /// some_isize.store(10, Ordering::Relaxed);
     /// ```
     ///
     /// # Panics
     ///
     /// Panics if `order` is `Acquire` or `AcqRel`.
     #[inline]
-    pub fn store(&self, val: int, order: Ordering) {
+    pub fn store(&self, val: isize, order: Ordering) {
         unsafe { atomic_store(self.v.get(), val, order); }
     }
 
-    /// Stores a value into the int, returning the old value.
+    /// Stores a value into the isize, returning the old value.
     ///
     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_int.swap(10, Ordering::Relaxed);
+    /// let value = some_isize.swap(10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn swap(&self, val: int, order: Ordering) -> int {
+    pub fn swap(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_swap(self.v.get(), val, order) }
     }
 
-    /// Stores a value into the int if the current value is the same as the expected value.
+    /// Stores a value into the isize if the current value is the same as the expected value.
     ///
     /// If the return value is equal to `old` then the value was updated.
     ///
@@ -491,112 +491,112 @@ impl AtomicInt {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_int.compare_and_swap(5, 10, Ordering::Relaxed);
+    /// let value = some_isize.compare_and_swap(5, 10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
+    pub fn compare_and_swap(&self, old: isize, new: isize, order: Ordering) -> isize {
         unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
     }
 
-    /// Add an int to the current value, returning the previous value.
+    /// Add an isize to the current value, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0);
+    /// let foo = AtomicIsize::new(0);
     /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
     /// assert_eq!(10, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_add(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_add(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_add(self.v.get(), val, order) }
     }
 
-    /// Subtract an int from the current value, returning the previous value.
+    /// Subtract an isize from the current value, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0);
+    /// let foo = AtomicIsize::new(0);
     /// assert_eq!(0, foo.fetch_sub(10, Ordering::SeqCst));
     /// assert_eq!(-10, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_sub(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_sub(self.v.get(), val, order) }
     }
 
-    /// Bitwise and with the current int, returning the previous value.
+    /// Bitwise and with the current isize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0b101101);
+    /// let foo = AtomicIsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_and(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_and(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_and(self.v.get(), val, order) }
     }
 
-    /// Bitwise or with the current int, returning the previous value.
+    /// Bitwise or with the current isize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0b101101);
+    /// let foo = AtomicIsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_or(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_or(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_or(self.v.get(), val, order) }
     }
 
-    /// Bitwise xor with the current int, returning the previous value.
+    /// Bitwise xor with the current isize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0b101101);
+    /// let foo = AtomicIsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_xor(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_xor(self.v.get(), val, order) }
     }
 }
 
-#[unstable = "awaiting int/uint conventions, types may change"]
-impl AtomicUint {
-    /// Creates a new `AtomicUint`.
+#[stable]
+impl AtomicUsize {
+    /// Creates a new `AtomicUsize`.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::AtomicUint;
+    /// use std::sync::atomic::AtomicUsize;
     ///
-    /// let atomic_forty_two = AtomicUint::new(42u);
+    /// let atomic_forty_two = AtomicUsize::new(42u);
     /// ```
     #[inline]
-    pub fn new(v: uint) -> AtomicUint {
-        AtomicUint { v: UnsafeCell::new(v) }
+    pub fn new(v: usize) -> AtomicUsize {
+        AtomicUsize { v: UnsafeCell::new(v) }
     }
 
-    /// Loads a value from the uint.
+    /// Loads a value from the usize.
     ///
     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
@@ -607,58 +607,58 @@ impl AtomicUint {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize = AtomicUsize::new(5);
     ///
-    /// let value = some_uint.load(Ordering::Relaxed);
+    /// let value = some_usize.load(Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn load(&self, order: Ordering) -> uint {
-        unsafe { atomic_load(self.v.get() as *const uint, order) }
+    pub fn load(&self, order: Ordering) -> usize {
+        unsafe { atomic_load(self.v.get() as *const usize, order) }
     }
 
-    /// Stores a value into the uint.
+    /// Stores a value into the usize.
     ///
     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize = AtomicUsize::new(5);
     ///
-    /// some_uint.store(10, Ordering::Relaxed);
+    /// some_usize.store(10, Ordering::Relaxed);
     /// ```
     ///
     /// # Panics
     ///
     /// Panics if `order` is `Acquire` or `AcqRel`.
     #[inline]
-    pub fn store(&self, val: uint, order: Ordering) {
+    pub fn store(&self, val: usize, order: Ordering) {
         unsafe { atomic_store(self.v.get(), val, order); }
     }
 
-    /// Stores a value into the uint, returning the old value.
+    /// Stores a value into the usize, returning the old value.
     ///
     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize= AtomicUsize::new(5);
     ///
-    /// let value = some_uint.swap(10, Ordering::Relaxed);
+    /// let value = some_usize.swap(10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn swap(&self, val: uint, order: Ordering) -> uint {
+    pub fn swap(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_swap(self.v.get(), val, order) }
     }
 
-    /// Stores a value into the uint if the current value is the same as the expected value.
+    /// Stores a value into the usize if the current value is the same as the expected value.
     ///
     /// If the return value is equal to `old` then the value was updated.
     ///
@@ -668,91 +668,91 @@ impl AtomicUint {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize = AtomicUsize::new(5);
     ///
-    /// let value = some_uint.compare_and_swap(5, 10, Ordering::Relaxed);
+    /// let value = some_usize.compare_and_swap(5, 10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
+    pub fn compare_and_swap(&self, old: usize, new: usize, order: Ordering) -> usize {
         unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
     }
 
-    /// Add to the current uint, returning the previous value.
+    /// Add to the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0);
+    /// let foo = AtomicUsize::new(0);
     /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
     /// assert_eq!(10, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_add(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_add(self.v.get(), val, order) }
     }
 
-    /// Subtract from the current uint, returning the previous value.
+    /// Subtract from the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(10);
+    /// let foo = AtomicUsize::new(10);
     /// assert_eq!(10, foo.fetch_sub(10, Ordering::SeqCst));
     /// assert_eq!(0, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_sub(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_sub(self.v.get(), val, order) }
     }
 
-    /// Bitwise and with the current uint, returning the previous value.
+    /// Bitwise and with the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0b101101);
+    /// let foo = AtomicUsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_and(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_and(self.v.get(), val, order) }
     }
 
-    /// Bitwise or with the current uint, returning the previous value.
+    /// Bitwise or with the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0b101101);
+    /// let foo = AtomicUsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_or(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_or(self.v.get(), val, order) }
     }
 
-    /// Bitwise xor with the current uint, returning the previous value.
+    /// Bitwise xor with the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0b101101);
+    /// let foo = AtomicUsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_xor(self.v.get(), val, order) }
     }
 }
@@ -771,7 +771,7 @@ impl<T> AtomicPtr<T> {
     #[inline]
     #[stable]
     pub fn new(p: *mut T) -> AtomicPtr<T> {
-        AtomicPtr { p: UnsafeCell::new(p as uint) }
+        AtomicPtr { p: UnsafeCell::new(p as usize) }
     }
 
     /// Loads a value from the pointer.
@@ -823,7 +823,7 @@ impl<T> AtomicPtr<T> {
     #[inline]
     #[stable]
     pub fn store(&self, ptr: *mut T, order: Ordering) {
-        unsafe { atomic_store(self.p.get(), ptr as uint, order); }
+        unsafe { atomic_store(self.p.get(), ptr as usize, order); }
     }
 
     /// Stores a value into the pointer, returning the old value.
@@ -845,7 +845,7 @@ impl<T> AtomicPtr<T> {
     #[inline]
     #[stable]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
-        unsafe { atomic_swap(self.p.get(), ptr as uint, order) as *mut T }
+        unsafe { atomic_swap(self.p.get(), ptr as usize, order) as *mut T }
     }
 
     /// Stores a value into the pointer if the current value is the same as the expected value.
@@ -872,8 +872,8 @@ impl<T> AtomicPtr<T> {
     #[stable]
     pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
         unsafe {
-            atomic_compare_and_swap(self.p.get(), old as uint,
-                                    new as uint, order) as *mut T
+            atomic_compare_and_swap(self.p.get(), old as usize,
+                                    new as usize, order) as *mut T
         }
     }
 }
@@ -1035,3 +1035,134 @@ pub fn fence(order: Ordering) {
         }
     }
 }
+
+#[deprecated="renamed to AtomicIsize"]
+#[allow(missing_docs)]
+pub struct AtomicInt {
+    v: UnsafeCell<int>,
+}
+
+unsafe impl Sync for AtomicInt {}
+
+#[deprecated="renamed to AtomicUsize"]
+#[allow(missing_docs)]
+pub struct AtomicUint {
+    v: UnsafeCell<uint>,
+}
+
+unsafe impl Sync for AtomicUint {}
+
+#[deprecated="use ATOMIC_ISIZE_INIT instead"]
+#[allow(missing_docs, deprecated)]
+pub const ATOMIC_INT_INIT: AtomicInt =
+        AtomicInt { v: UnsafeCell { value: 0 } };
+#[deprecated="use ATOMIC_USIZE_INIT instead"]
+#[allow(missing_docs, deprecated)]
+pub const ATOMIC_UINT_INIT: AtomicUint =
+        AtomicUint { v: UnsafeCell { value: 0, } };
+
+#[allow(missing_docs, deprecated)]
+impl AtomicInt {
+    #[inline]
+    pub fn new(v: int) -> AtomicInt {
+        AtomicInt {v: UnsafeCell::new(v)}
+    }
+
+    #[inline]
+    pub fn load(&self, order: Ordering) -> int {
+        unsafe { atomic_load(self.v.get() as *const int, order) }
+    }
+
+    #[inline]
+    pub fn store(&self, val: int, order: Ordering) {
+        unsafe { atomic_store(self.v.get(), val, order); }
+    }
+
+    #[inline]
+    pub fn swap(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_swap(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
+        unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
+    }
+
+    #[inline]
+    pub fn fetch_add(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_add(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_sub(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_and(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_and(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_or(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_or(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_xor(self.v.get(), val, order) }
+    }
+}
+
+#[allow(missing_docs, deprecated)]
+impl AtomicUint {
+    #[inline]
+    pub fn new(v: uint) -> AtomicUint {
+        AtomicUint { v: UnsafeCell::new(v) }
+    }
+
+    #[inline]
+    pub fn load(&self, order: Ordering) -> uint {
+        unsafe { atomic_load(self.v.get() as *const uint, order) }
+    }
+
+    #[inline]
+    pub fn store(&self, val: uint, order: Ordering) {
+        unsafe { atomic_store(self.v.get(), val, order); }
+    }
+
+    #[inline]
+    pub fn swap(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_swap(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
+        unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
+    }
+
+    #[inline]
+    pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_add(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_sub(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_and(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_or(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_xor(self.v.get(), val, order) }
+    }
+}
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 6db01b7cb7a..963cb48db07 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -115,7 +115,6 @@
 //!     }
 //! #   fn calc_span_tree(&self) -> Vec<(uint, uint)> { vec![] }
 //! }
-//! # fn main() { }
 //! ```
 //!
 //! ## Mutating implementations of `clone`
@@ -509,12 +508,13 @@ impl<'b, T> DerefMut for RefMut<'b, T> {
 ///
 /// ```rust
 /// use std::cell::UnsafeCell;
-/// use std::marker;
+/// use std::marker::Sync;
 ///
 /// struct NotThreadSafe<T> {
 ///     value: UnsafeCell<T>,
-///     marker: marker::NoSync
 /// }
+///
+/// unsafe impl<T> Sync for NotThreadSafe<T> {}
 /// ```
 ///
 /// **NOTE:** `UnsafeCell<T>` fields are public to allow static initializers. It
diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs
index a21ec892dd7..ed3612bded0 100644
--- a/src/libcore/finally.rs
+++ b/src/libcore/finally.rs
@@ -23,16 +23,18 @@
 //!
 //! use std::finally::Finally;
 //!
-//! # fn main() {
 //! (|&mut:| {
 //!     // ...
 //! }).finally(|| {
 //!     // this code is always run
 //! })
-//! # }
 //! ```
 
-#![unstable]
+#![deprecated = "It is unclear if this module is more robust than implementing \
+                 Drop on a custom type, and this module is being removed with no \
+                 replacement. Use a custom Drop implementation to regain existing \
+                 functionality."]
+#![allow(deprecated)]
 
 use ops::{Drop, FnMut, FnOnce};
 
diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs
index 0ffcb014c28..f1b9ebe6d90 100644
--- a/src/libcore/fmt/float.rs
+++ b/src/libcore/fmt/float.rs
@@ -332,5 +332,5 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
         }
     }
 
-    f(unsafe { str::from_utf8_unchecked(&buf[0..end]) })
+    f(unsafe { str::from_utf8_unchecked(&buf[..end]) })
 }
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index a0ec9e5f151..535722f93bf 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -180,25 +180,6 @@ impl<'a> Arguments<'a> {
     /// unsafety, but will ignore invalid .
     #[doc(hidden)] #[inline]
     #[unstable = "implementation detail of the `format_args!` macro"]
-    #[cfg(stage0)] // SNAP 9e4e524
-    pub fn with_placeholders(pieces: &'a [&'a str],
-                             fmt: &'a [rt::Argument<'a>],
-                             args: &'a [Argument<'a>]) -> Arguments<'a> {
-        Arguments {
-            pieces: pieces,
-            fmt: Some(fmt),
-            args: args
-        }
-    }
-    /// This function is used to specify nonstandard formatting parameters.
-    /// The `pieces` array must be at least as long as `fmt` to construct
-    /// a valid Arguments structure. Also, any `Count` within `fmt` that is
-    /// `CountIsParam` or `CountIsNextParam` has to point to an argument
-    /// created with `argumentuint`. However, failing to do so doesn't cause
-    /// unsafety, but will ignore invalid .
-    #[doc(hidden)] #[inline]
-    #[unstable = "implementation detail of the `format_args!` macro"]
-    #[cfg(not(stage0))]
     pub fn with_placeholders(pieces: &'a [&'a str],
                              fmt: &'a [rt::Argument],
                              args: &'a [Argument<'a>]) -> Arguments<'a> {
@@ -226,10 +207,6 @@ pub struct Arguments<'a> {
     pieces: &'a [&'a str],
 
     // Placeholder specs, or `None` if all specs are default (as in "{}{}").
-    // SNAP 9e4e524
-    #[cfg(stage0)]
-    fmt: Option<&'a [rt::Argument<'a>]>,
-    #[cfg(not(stage0))]
     fmt: Option<&'a [rt::Argument]>,
 
     // Dynamic arguments for interpolation, to be interleaved with string
@@ -449,7 +426,7 @@ impl<'a> Formatter<'a> {
             for c in sign.into_iter() {
                 let mut b = [0; 4];
                 let n = c.encode_utf8(&mut b).unwrap_or(0);
-                let b = unsafe { str::from_utf8_unchecked(&b[0..n]) };
+                let b = unsafe { str::from_utf8_unchecked(&b[..n]) };
                 try!(f.buf.write_str(b));
             }
             if prefixed { f.buf.write_str(prefix) }
@@ -692,7 +669,7 @@ impl String for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
         let mut utf8 = [0u8; 4];
         let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
-        let s: &str = unsafe { mem::transmute(&utf8[0..amt]) };
+        let s: &str = unsafe { mem::transmute(&utf8[..amt]) };
         String::fmt(s, f)
     }
 }
diff --git a/src/libcore/fmt/rt.rs b/src/libcore/fmt/rt.rs
index 2abf921eaf2..bea32219155 100644
--- a/src/libcore/fmt/rt.rs
+++ b/src/libcore/fmt/rt.rs
@@ -21,21 +21,12 @@ pub use self::Count::*;
 pub use self::Position::*;
 pub use self::Flag::*;
 
-// SNAP 9e4e524
 #[doc(hidden)]
 #[derive(Copy)]
-#[cfg(not(stage0))]
 pub struct Argument {
     pub position: Position,
     pub format: FormatSpec,
 }
-#[doc(hidden)]
-#[derive(Copy)]
-#[cfg(stage0)]
-pub struct Argument<'a> {
-    pub position: Position,
-    pub format: FormatSpec,
-}
 
 #[doc(hidden)]
 #[derive(Copy)]
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index a82ea009e13..37e4a105a30 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -58,7 +58,13 @@
 
 #![unstable = "module was recently redesigned"]
 
+use prelude::*;
+
+use borrow::{Cow, ToOwned};
 use default::Default;
+use intrinsics::TypeId;
+use mem;
+use num::Int;
 
 pub use self::sip::SipHasher;
 
@@ -70,19 +76,6 @@ mod sip;
 /// to compute the hash. Specific implementations of this trait may specialize
 /// for particular instances of `H` in order to be able to optimize the hashing
 /// behavior.
-#[cfg(stage0)]
-pub trait Hash<H> {
-    /// Feeds this value into the state given, updating the hasher as necessary.
-    fn hash(&self, state: &mut H);
-}
-
-/// A hashable type.
-///
-/// The `H` type parameter is an abstract hash state that is used by the `Hash`
-/// to compute the hash. Specific implementations of this trait may specialize
-/// for particular instances of `H` in order to be able to optimize the hashing
-/// behavior.
-#[cfg(not(stage0))]
 pub trait Hash<H: Hasher> {
     /// Feeds this value into the state given, updating the hasher as necessary.
     fn hash(&self, state: &mut H);
@@ -121,314 +114,147 @@ pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
 
 //////////////////////////////////////////////////////////////////////////////
 
-#[cfg(stage0)]
-mod impls {
-    use prelude::*;
-
-    use borrow::{Cow, ToOwned};
-    use intrinsics::TypeId;
-    use mem;
-    use super::{Hash, Writer};
-    use num::Int;
-
-    macro_rules! impl_hash {
-        ($ty:ident, $uty:ident) => {
-            impl<S: Writer> Hash<S> for $ty {
-                #[inline]
-                fn hash(&self, state: &mut S) {
-                    let a: [u8; ::$ty::BYTES] = unsafe {
-                        mem::transmute((*self as $uty).to_le() as $ty)
-                    };
-                    state.write(a.as_slice())
-                }
-            }
-        }
-    }
-
-    impl_hash! { u8, u8 }
-    impl_hash! { u16, u16 }
-    impl_hash! { u32, u32 }
-    impl_hash! { u64, u64 }
-    impl_hash! { uint, uint }
-    impl_hash! { i8, u8 }
-    impl_hash! { i16, u16 }
-    impl_hash! { i32, u32 }
-    impl_hash! { i64, u64 }
-    impl_hash! { int, uint }
-
-    impl<S: Writer> Hash<S> for bool {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (*self as u8).hash(state);
-        }
-    }
-
-    impl<S: Writer> Hash<S> for char {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (*self as u32).hash(state);
-        }
-    }
-
-    impl<S: Writer> Hash<S> for str {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            state.write(self.as_bytes());
-            0xffu8.hash(state)
-        }
-    }
-
-    macro_rules! impl_hash_tuple {
-        () => (
-            impl<S> Hash<S> for () {
-                #[inline]
-                fn hash(&self, _state: &mut S) {}
-            }
-        );
-
-        ( $($name:ident)+) => (
-            impl<S, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
-                #[inline]
-                #[allow(non_snake_case)]
-                fn hash(&self, state: &mut S) {
-                    match *self {
-                        ($(ref $name,)*) => {
-                            $(
-                                $name.hash(state);
-                            )*
-                        }
-                    }
-                }
-            }
-        );
-    }
-
-    impl_hash_tuple! {}
-    impl_hash_tuple! { A }
-    impl_hash_tuple! { A B }
-    impl_hash_tuple! { A B C }
-    impl_hash_tuple! { A B C D }
-    impl_hash_tuple! { A B C D E }
-    impl_hash_tuple! { A B C D E F }
-    impl_hash_tuple! { A B C D E F G }
-    impl_hash_tuple! { A B C D E F G H }
-    impl_hash_tuple! { A B C D E F G H I }
-    impl_hash_tuple! { A B C D E F G H I J }
-    impl_hash_tuple! { A B C D E F G H I J K }
-    impl_hash_tuple! { A B C D E F G H I J K L }
-
-    impl<S: Writer, T: Hash<S>> Hash<S> for [T] {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            self.len().hash(state);
-            for elt in self.iter() {
-                elt.hash(state);
+macro_rules! impl_hash {
+    ($ty:ident, $uty:ident) => {
+        impl<S: Writer + Hasher> Hash<S> for $ty {
+            #[inline]
+            fn hash(&self, state: &mut S) {
+                let a: [u8; ::$ty::BYTES] = unsafe {
+                    mem::transmute((*self as $uty).to_le() as $ty)
+                };
+                state.write(a.as_slice())
             }
         }
     }
-
-
-    impl<'a, S, T: ?Sized + Hash<S>> Hash<S> for &'a T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (**self).hash(state);
-        }
-    }
-
-    impl<'a, S, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (**self).hash(state);
-        }
-    }
-
-    impl<S: Writer, T> Hash<S> for *const T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            // NB: raw-pointer Hash does _not_ dereference
-            // to the target; it just gives you the pointer-bytes.
-            (*self as uint).hash(state);
-        }
-    }
-
-    impl<S: Writer, T> Hash<S> for *mut T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            // NB: raw-pointer Hash does _not_ dereference
-            // to the target; it just gives you the pointer-bytes.
-            (*self as uint).hash(state);
-        }
-    }
-
-    impl<S: Writer> Hash<S> for TypeId {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            self.hash().hash(state)
-        }
-    }
-
-    impl<'a, T, B: ?Sized, S> Hash<S> for Cow<'a, T, B>
-        where B: Hash<S> + ToOwned<T>
-    {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            Hash::hash(&**self, state)
-        }
-    }
 }
 
-#[cfg(not(stage0))]
-mod impls {
-    use prelude::*;
-
-    use borrow::{Cow, ToOwned};
-    use intrinsics::TypeId;
-    use mem;
-    use super::{Hash, Writer, Hasher};
-    use num::Int;
-
-    macro_rules! impl_hash {
-        ($ty:ident, $uty:ident) => {
-            impl<S: Writer + Hasher> Hash<S> for $ty {
-                #[inline]
-                fn hash(&self, state: &mut S) {
-                    let a: [u8; ::$ty::BYTES] = unsafe {
-                        mem::transmute((*self as $uty).to_le() as $ty)
-                    };
-                    state.write(a.as_slice())
-                }
-            }
-        }
+impl_hash! { u8, u8 }
+impl_hash! { u16, u16 }
+impl_hash! { u32, u32 }
+impl_hash! { u64, u64 }
+impl_hash! { uint, uint }
+impl_hash! { i8, u8 }
+impl_hash! { i16, u16 }
+impl_hash! { i32, u32 }
+impl_hash! { i64, u64 }
+impl_hash! { int, uint }
+
+impl<S: Writer + Hasher> Hash<S> for bool {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        (*self as u8).hash(state);
     }
+}
 
-    impl_hash! { u8, u8 }
-    impl_hash! { u16, u16 }
-    impl_hash! { u32, u32 }
-    impl_hash! { u64, u64 }
-    impl_hash! { uint, uint }
-    impl_hash! { i8, u8 }
-    impl_hash! { i16, u16 }
-    impl_hash! { i32, u32 }
-    impl_hash! { i64, u64 }
-    impl_hash! { int, uint }
-
-    impl<S: Writer + Hasher> Hash<S> for bool {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (*self as u8).hash(state);
-        }
+impl<S: Writer + Hasher> Hash<S> for char {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        (*self as u32).hash(state);
     }
+}
 
-    impl<S: Writer + Hasher> Hash<S> for char {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (*self as u32).hash(state);
-        }
+impl<S: Writer + Hasher> Hash<S> for str {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        state.write(self.as_bytes());
+        0xffu8.hash(state)
     }
+}
 
-    impl<S: Writer + Hasher> Hash<S> for str {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            state.write(self.as_bytes());
-            0xffu8.hash(state)
+macro_rules! impl_hash_tuple {
+    () => (
+        impl<S: Hasher> Hash<S> for () {
+            #[inline]
+            fn hash(&self, _state: &mut S) {}
         }
-    }
-
-    macro_rules! impl_hash_tuple {
-        () => (
-            impl<S: Hasher> Hash<S> for () {
-                #[inline]
-                fn hash(&self, _state: &mut S) {}
-            }
-        );
-
-        ( $($name:ident)+) => (
-            impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
-                #[inline]
-                #[allow(non_snake_case)]
-                fn hash(&self, state: &mut S) {
-                    match *self {
-                        ($(ref $name,)*) => {
-                            $(
-                                $name.hash(state);
-                            )*
-                        }
+    );
+
+    ( $($name:ident)+) => (
+        impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
+            #[inline]
+            #[allow(non_snake_case)]
+            fn hash(&self, state: &mut S) {
+                match *self {
+                    ($(ref $name,)*) => {
+                        $(
+                            $name.hash(state);
+                        )*
                     }
                 }
             }
-        );
-    }
-
-    impl_hash_tuple! {}
-    impl_hash_tuple! { A }
-    impl_hash_tuple! { A B }
-    impl_hash_tuple! { A B C }
-    impl_hash_tuple! { A B C D }
-    impl_hash_tuple! { A B C D E }
-    impl_hash_tuple! { A B C D E F }
-    impl_hash_tuple! { A B C D E F G }
-    impl_hash_tuple! { A B C D E F G H }
-    impl_hash_tuple! { A B C D E F G H I }
-    impl_hash_tuple! { A B C D E F G H I J }
-    impl_hash_tuple! { A B C D E F G H I J K }
-    impl_hash_tuple! { A B C D E F G H I J K L }
+        }
+    );
+}
 
-    impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            self.len().hash(state);
-            for elt in self.iter() {
-                elt.hash(state);
-            }
+impl_hash_tuple! {}
+impl_hash_tuple! { A }
+impl_hash_tuple! { A B }
+impl_hash_tuple! { A B C }
+impl_hash_tuple! { A B C D }
+impl_hash_tuple! { A B C D E }
+impl_hash_tuple! { A B C D E F }
+impl_hash_tuple! { A B C D E F G }
+impl_hash_tuple! { A B C D E F G H }
+impl_hash_tuple! { A B C D E F G H I }
+impl_hash_tuple! { A B C D E F G H I J }
+impl_hash_tuple! { A B C D E F G H I J K }
+impl_hash_tuple! { A B C D E F G H I J K L }
+
+impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        self.len().hash(state);
+        for elt in self.iter() {
+            elt.hash(state);
         }
     }
+}
 
 
-    impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (**self).hash(state);
-        }
+impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        (**self).hash(state);
     }
+}
 
-    impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (**self).hash(state);
-        }
+impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        (**self).hash(state);
     }
+}
 
-    impl<S: Writer + Hasher, T> Hash<S> for *const T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            // NB: raw-pointer Hash does _not_ dereference
-            // to the target; it just gives you the pointer-bytes.
-            (*self as uint).hash(state);
-        }
+impl<S: Writer + Hasher, T> Hash<S> for *const T {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        // NB: raw-pointer Hash does _not_ dereference
+        // to the target; it just gives you the pointer-bytes.
+        (*self as uint).hash(state);
     }
+}
 
-    impl<S: Writer + Hasher, T> Hash<S> for *mut T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            // NB: raw-pointer Hash does _not_ dereference
-            // to the target; it just gives you the pointer-bytes.
-            (*self as uint).hash(state);
-        }
+impl<S: Writer + Hasher, T> Hash<S> for *mut T {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        // NB: raw-pointer Hash does _not_ dereference
+        // to the target; it just gives you the pointer-bytes.
+        (*self as uint).hash(state);
     }
+}
 
-    impl<S: Writer + Hasher> Hash<S> for TypeId {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            self.hash().hash(state)
-        }
+impl<S: Writer + Hasher> Hash<S> for TypeId {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        self.hash().hash(state)
     }
+}
 
-    impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
-        where B: Hash<S> + ToOwned<T>
-    {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            Hash::hash(&**self, state)
-        }
+impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
+    where B: Hash<S> + ToOwned<T>
+{
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        Hash::hash(&**self, state)
     }
 }
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 5924d515dda..40db0def626 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -42,7 +42,6 @@
 #![unstable]
 #![allow(missing_docs)]
 
-#[cfg(not(stage0))]
 use marker::Sized;
 
 pub type GlueFn = extern "Rust" fn(*const i8);
@@ -198,17 +197,17 @@ extern "rust-intrinsic" {
     pub fn pref_align_of<T>() -> uint;
 
     /// Get a static pointer to a type descriptor.
+    #[cfg(not(stage0))]
+    pub fn get_tydesc<T: ?Sized>() -> *const TyDesc;
+
+    #[cfg(stage0)]
     pub fn get_tydesc<T>() -> *const TyDesc;
 
     /// Gets an identifier which is globally unique to the specified type. This
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
-    #[cfg(not(stage0))]
     pub fn type_id<T: ?Sized + 'static>() -> TypeId;
 
-    #[cfg(stage0)]
-    pub fn type_id<T: 'static>() -> TypeId;
-
     /// Create a value initialized to zero.
     ///
     /// `init` is unsafe because it returns a zeroed-out datum,
@@ -558,15 +557,9 @@ pub struct TypeId {
 
 impl TypeId {
     /// Returns the `TypeId` of the type this generic function has been instantiated with
-    #[cfg(not(stage0))]
     pub fn of<T: ?Sized + 'static>() -> TypeId {
         unsafe { type_id::<T>() }
     }
 
-    #[cfg(stage0)]
-    pub fn of<T: 'static>() -> TypeId {
-        unsafe { type_id::<T>() }
-    }
-
     pub fn hash(&self) -> u64 { self.t }
 }
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 849080e8a82..0005db36c27 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -101,6 +101,8 @@ pub trait Iterator {
 
 /// Conversion from an `Iterator`
 #[stable]
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
+                          built from an iterator over elements of type `{A}`"]
 pub trait FromIterator<A> {
     /// Build a container with elements from an external iterator.
     fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
@@ -2751,9 +2753,9 @@ macro_rules! step_impl_no_between {
 }
 
 step_impl!(uint u8 u16 u32 int i8 i16 i32);
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 step_impl!(u64 i64);
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 step_impl_no_between!(u64 i64);
 
 
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 28f8cf588be..0b150d1ecf9 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -58,11 +58,11 @@
 
 #![no_std]
 #![allow(unknown_features, raw_pointer_derive)]
-#![cfg_attr(stage0, allow(unused_attributes))]
 #![allow(unknown_features)] #![feature(intrinsics, lang_items)]
 #![feature(simd, unsafe_destructor, slicing_syntax)]
 #![feature(unboxed_closures)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![feature(on_unimplemented)]
 #![deny(missing_docs)]
 
 #[macro_use]
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 3d3b9f8cf65..1c37126e8e9 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -39,13 +39,16 @@ macro_rules! panic {
 /// // the panic message for these assertions is the stringified value of the
 /// // expression given.
 /// assert!(true);
-/// # fn some_computation() -> bool { true }
+///
+/// fn some_computation() -> bool { true } // a very simple function
+///
 /// assert!(some_computation());
 ///
 /// // assert with a custom message
-/// # let x = true;
+/// let x = true;
 /// assert!(x, "x wasn't true!");
-/// # let a = 3i; let b = 27i;
+///
+/// let a = 3i; let b = 27i;
 /// assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
@@ -108,13 +111,15 @@ macro_rules! assert_eq {
 /// // the panic message for these assertions is the stringified value of the
 /// // expression given.
 /// debug_assert!(true);
-/// # fn some_expensive_computation() -> bool { true }
+///
+/// fn some_expensive_computation() -> bool { true } // a very simple function
 /// debug_assert!(some_expensive_computation());
 ///
 /// // assert with a custom message
-/// # let x = true;
+/// let x = true;
 /// debug_assert!(x, "x wasn't true!");
-/// # let a = 3i; let b = 27i;
+///
+/// let a = 3; let b = 27;
 /// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
 /// ```
 #[macro_export]
diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs
index d400cb47cbf..99ba9666cd2 100644
--- a/src/libcore/marker.rs
+++ b/src/libcore/marker.rs
@@ -42,6 +42,104 @@ pub trait Sized {
 }
 
 /// Types that can be copied by simply copying bits (i.e. `memcpy`).
+///
+/// By default, variable bindings have 'move semantics.' In other
+/// words:
+///
+/// ```
+/// #[derive(Show)]
+/// struct Foo;
+///
+/// let x = Foo;
+///
+/// let y = x;
+///
+/// // `x` has moved into `y`, and so cannot be used
+///
+/// // println!("{:?}", x); // error: use of moved value
+/// ```
+///
+/// However, if a type implements `Copy`, it instead has 'copy semantics':
+///
+/// ```
+/// // we can just derive a `Copy` implementation
+/// #[derive(Show, Copy)]
+/// struct Foo;
+///
+/// let x = Foo;
+///
+/// let y = x;
+///
+/// // `y` is a copy of `x`
+///
+/// println!("{:?}", x); // A-OK!
+/// ```
+///
+/// It's important to note that in these two examples, the only difference is if you are allowed to
+/// access `x` after the assignment: a move is also a bitwise copy under the hood.
+///
+/// ## When can my type be `Copy`?
+///
+/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
+/// `struct` can be `Copy`:
+///
+/// ```
+/// struct Point {
+///    x: i32,
+///    y: i32,
+/// }
+/// ```
+///
+/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`.
+///
+/// ```
+/// # struct Point;
+/// struct PointList {
+///     points: Vec<Point>,
+/// }
+/// ```
+///
+/// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we
+/// attempt to derive a `Copy` implementation, we'll get an error.
+///
+/// ```text
+/// error: the trait `Copy` may not be implemented for this type; field `points` does not implement
+/// `Copy`
+/// ```
+///
+/// ## How can I implement `Copy`?
+///
+/// There are two ways to implement `Copy` on your type:
+///
+/// ```
+/// #[derive(Copy)]
+/// struct MyStruct;
+/// ```
+///
+/// and
+///
+/// ```
+/// struct MyStruct;
+/// impl Copy for MyStruct {}
+/// ```
+///
+/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
+/// bound on type parameters, which isn't always desired.
+///
+/// ## When can my type _not_ be `Copy`?
+///
+/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
+/// mutable reference, and copying `String` would result in two attempts to free the same buffer.
+///
+/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
+/// managing some resource besides its own `size_of::<T>()` bytes.
+///
+/// ## When should my type be `Copy`?
+///
+/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
+/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
+/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
+/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
 #[stable]
 #[lang="copy"]
 pub trait Copy {
@@ -210,8 +308,7 @@ impl<T: ?Sized> Clone for ContravariantType<T> {
 /// "interior" mutability:
 ///
 /// ```
-/// pub struct Cell<T> { value: T }
-/// # fn main() {}
+/// struct Cell<T> { value: T }
 /// ```
 ///
 /// The type system would infer that `value` is only read here and
@@ -286,6 +383,7 @@ pub struct InvariantLifetime<'a>;
 #[unstable = "likely to change with new variance strategy"]
 #[lang="no_send_bound"]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct NoSend;
 
 /// A type which is considered "not POD", meaning that it is not
@@ -303,6 +401,7 @@ pub struct NoCopy;
 #[unstable = "likely to change with new variance strategy"]
 #[lang="no_sync_bound"]
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct NoSync;
 
 /// A type which is considered managed by the GC. This is typically
diff --git a/src/libcore/num/int.rs b/src/libcore/num/int.rs
index 065763a0d8e..83011db35ce 100644
--- a/src/libcore/num/int.rs
+++ b/src/libcore/num/int.rs
@@ -16,8 +16,5 @@
 
 #![deprecated = "replaced by isize"]
 
-#[cfg(stage0)] #[cfg(target_word_size = "32")] int_module! { int, 32 }
-#[cfg(stage0)] #[cfg(target_word_size = "64")] int_module! { int, 64 }
-
-#[cfg(not(stage0))] #[cfg(target_pointer_width = "32")] int_module! { int, 32 }
-#[cfg(not(stage0))] #[cfg(target_pointer_width = "64")] int_module! { int, 64 }
+#[cfg(target_pointer_width = "32")] int_module! { int, 32 }
+#[cfg(target_pointer_width = "64")] int_module! { int, 64 }
diff --git a/src/libcore/num/isize.rs b/src/libcore/num/isize.rs
index c1cf3c62131..e4711c92c59 100644
--- a/src/libcore/num/isize.rs
+++ b/src/libcore/num/isize.rs
@@ -17,9 +17,7 @@
 #![stable]
 #![doc(primitive = "isize")]
 
-#[cfg(any(all(stage0, target_word_size = "32"),
-          all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 int_module! { isize, 32 }
-#[cfg(any(all(stage0, target_word_size = "64"),
-          all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 int_module! { isize, 64 }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 57415f4331d..599a5515e3b 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -496,7 +496,7 @@ uint_impl! { u64 = u64, 64,
     intrinsics::u64_sub_with_overflow,
     intrinsics::u64_mul_with_overflow }
 
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 uint_impl! { uint = u32, 32,
     intrinsics::ctpop32,
     intrinsics::ctlz32,
@@ -506,7 +506,7 @@ uint_impl! { uint = u32, 32,
     intrinsics::u32_sub_with_overflow,
     intrinsics::u32_mul_with_overflow }
 
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 uint_impl! { uint = u64, 64,
     intrinsics::ctpop64,
     intrinsics::ctlz64,
@@ -601,13 +601,13 @@ int_impl! { i64 = i64, u64, 64,
     intrinsics::i64_sub_with_overflow,
     intrinsics::i64_mul_with_overflow }
 
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 int_impl! { int = i32, u32, 32,
     intrinsics::i32_add_with_overflow,
     intrinsics::i32_sub_with_overflow,
     intrinsics::i32_mul_with_overflow }
 
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 int_impl! { int = i64, u64, 64,
     intrinsics::i64_add_with_overflow,
     intrinsics::i64_sub_with_overflow,
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index ab956587d82..db7177e26fa 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -706,20 +706,36 @@ pub trait Shl<RHS> {
 }
 
 macro_rules! shl_impl {
-    ($($t:ty)*) => ($(
+    ($t:ty, $f:ty) => (
         #[stable]
-        impl Shl<uint> for $t {
+        impl Shl<$f> for $t {
             type Output = $t;
 
             #[inline]
-            fn shl(self, other: uint) -> $t {
+            fn shl(self, other: $f) -> $t {
                 self << other
             }
         }
+    )
+}
+
+macro_rules! shl_impl_all {
+    ($($t:ty)*) => ($(
+        shl_impl! { $t, u8 }
+        shl_impl! { $t, u16 }
+        shl_impl! { $t, u32 }
+        shl_impl! { $t, u64 }
+        shl_impl! { $t, usize }
+
+        shl_impl! { $t, i8 }
+        shl_impl! { $t, i16 }
+        shl_impl! { $t, i32 }
+        shl_impl! { $t, i64 }
+        shl_impl! { $t, isize }
     )*)
 }
 
-shl_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 
 /// The `Shr` trait is used to specify the functionality of `>>`.
 ///
@@ -761,45 +777,62 @@ pub trait Shr<RHS> {
 }
 
 macro_rules! shr_impl {
-    ($($t:ty)*) => ($(
-        impl Shr<uint> for $t {
+    ($t:ty, $f:ty) => (
+        impl Shr<$f> for $t {
             type Output = $t;
 
             #[inline]
-            fn shr(self, other: uint) -> $t { self >> other }
+            fn shr(self, other: $f) -> $t {
+                self >> other
+            }
         }
+    )
+}
+
+macro_rules! shr_impl_all {
+    ($($t:ty)*) => ($(
+        shr_impl! { $t, u8 }
+        shr_impl! { $t, u16 }
+        shr_impl! { $t, u32 }
+        shr_impl! { $t, u64 }
+        shr_impl! { $t, usize }
+
+        shr_impl! { $t, i8 }
+        shr_impl! { $t, i16 }
+        shr_impl! { $t, i32 }
+        shr_impl! { $t, i64 }
+        shr_impl! { $t, isize }
     )*)
 }
 
-shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 
 /// The `Index` trait is used to specify the functionality of indexing operations
 /// like `arr[idx]` when used in an immutable context.
 ///
 /// # Example
 ///
-/// A trivial implementation of `Index`. When `Foo[Foo]` happens, it ends up
+/// A trivial implementation of `Index`. When `Foo[Bar]` happens, it ends up
 /// calling `index`, and therefore, `main` prints `Indexing!`.
 ///
 /// ```
-/// #![feature(associated_types)]
-///
 /// use std::ops::Index;
 ///
 /// #[derive(Copy)]
 /// struct Foo;
+/// struct Bar;
 ///
-/// impl Index<Foo> for Foo {
+/// impl Index<Bar> for Foo {
 ///     type Output = Foo;
 ///
-///     fn index<'a>(&'a self, _index: &Foo) -> &'a Foo {
+///     fn index<'a>(&'a self, _index: &Bar) -> &'a Foo {
 ///         println!("Indexing!");
 ///         self
 ///     }
 /// }
 ///
 /// fn main() {
-///     Foo[Foo];
+///     Foo[Bar];
 /// }
 /// ```
 #[lang="index"]
@@ -815,28 +848,27 @@ pub trait Index<Index: ?Sized> {
 ///
 /// # Example
 ///
-/// A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
+/// A trivial implementation of `IndexMut`. When `Foo[Bar]` happens, it ends up
 /// calling `index_mut`, and therefore, `main` prints `Indexing!`.
 ///
 /// ```
-/// #![feature(associated_types)]
-///
 /// use std::ops::IndexMut;
 ///
 /// #[derive(Copy)]
 /// struct Foo;
+/// struct Bar;
 ///
-/// impl IndexMut<Foo> for Foo {
+/// impl IndexMut<Bar> for Foo {
 ///     type Output = Foo;
 ///
-///     fn index_mut<'a>(&'a mut self, _index: &Foo) -> &'a mut Foo {
+///     fn index_mut<'a>(&'a mut self, _index: &Bar) -> &'a mut Foo {
 ///         println!("Indexing!");
 ///         self
 ///     }
 /// }
 ///
 /// fn main() {
-///     &mut Foo[Foo];
+///     &mut Foo[Bar];
 /// }
 /// ```
 #[lang="index_mut"]
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 41eecb4649d..af7fc875389 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -66,7 +66,6 @@
 //! not (`None`).
 //!
 //! ```
-//! # use std::boxed::Box;
 //! let optional: Option<Box<int>> = None;
 //! check_optional(&optional);
 //!
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index c3bb9c91557..da3f180d7e1 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -21,11 +21,7 @@
 //! # Example
 //!
 //! ```ignore
-//! # fn main() {
-//! #![feature(globs)]
-//!
 //! use core::prelude::*;
-//! # }
 //! ```
 
 // Reexported core operators
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index ab1e69f0060..baf998d0828 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -46,7 +46,6 @@
 //! though unsafely, transformed from one type to the other.
 //!
 //! ```
-//! # use std::boxed::Box;
 //! use std::mem;
 //!
 //! unsafe {
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index f7421203336..1ab810f937d 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -119,7 +119,7 @@
 //! drop(file);
 //! ```
 //!
-//! If you *do* write that in Rust, the compiler will by give you a
+//! If you *do* write that in Rust, the compiler will give you a
 //! warning (by default, controlled by the `unused_must_use` lint).
 //!
 //! You might instead, if you don't want to handle the error, simply
@@ -178,13 +178,11 @@
 //! fn write_info(info: &Info) -> Result<(), IoError> {
 //!     let mut file = File::open_mode(&Path::new("my_best_friends.txt"), Open, Write);
 //!     // Early return on error
-//!     match file.write_line(format!("name: {}", info.name).as_slice()) {
-//!         Ok(_) => (),
-//!         Err(e) => return Err(e)
+//!     if let Err(e) = file.write_line(format!("name: {}", info.name).as_slice()) {
+//!         return Err(e)
 //!     }
-//!     match file.write_line(format!("age: {}", info.age).as_slice()) {
-//!         Ok(_) => (),
-//!         Err(e) => return Err(e)
+//!     if let Err(e) = file.write_line(format!("age: {}", info.age).as_slice()) {
+//!         return Err(e)
 //!     }
 //!     return file.write_line(format!("rating: {}", info.rating).as_slice());
 //! }
@@ -219,11 +217,9 @@
 //! makes it clear:
 //!
 //! ```
-//! # #![feature(macro_rules)]
 //! macro_rules! try {
 //!     ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
 //! }
-//! # fn main() { }
 //! ```
 //!
 //! `try!` is imported by the prelude, and is available everywhere.
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 7e47c5257a3..22da168911d 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -159,7 +159,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     fn split_at(&self, mid: uint) -> (&[T], &[T]) {
-        (&self[0..mid], &self[mid..])
+        (&self[..mid], &self[mid..])
     }
 
     #[inline]
@@ -240,7 +240,7 @@ impl<T> SliceExt for [T] {
 
     #[inline]
     fn init(&self) -> &[T] {
-        &self[0..(self.len() - 1)]
+        &self[..(self.len() - 1)]
     }
 
     #[inline]
@@ -443,7 +443,7 @@ impl<T> SliceExt for [T] {
     #[inline]
     fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
         let n = needle.len();
-        self.len() >= n && needle == &self[0..n]
+        self.len() >= n && needle == &self[..n]
     }
 
     #[inline]
@@ -972,7 +972,7 @@ impl<'a, T, P> Iterator for Split<'a, T, P> where P: FnMut(&T) -> bool {
         match self.v.iter().position(|x| (self.pred)(x)) {
             None => self.finish(),
             Some(idx) => {
-                let ret = Some(&self.v[0..idx]);
+                let ret = Some(&self.v[..idx]);
                 self.v = &self.v[(idx + 1)..];
                 ret
             }
@@ -999,7 +999,7 @@ impl<'a, T, P> DoubleEndedIterator for Split<'a, T, P> where P: FnMut(&T) -> boo
             None => self.finish(),
             Some(idx) => {
                 let ret = Some(&self.v[(idx + 1)..]);
-                self.v = &self.v[0..idx];
+                self.v = &self.v[..idx];
                 ret
             }
         }
@@ -1195,7 +1195,7 @@ impl<'a, T> Iterator for Windows<'a, T> {
         if self.size > self.v.len() {
             None
         } else {
-            let ret = Some(&self.v[0..self.size]);
+            let ret = Some(&self.v[..self.size]);
             self.v = &self.v[1..];
             ret
         }
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 94ee9b7dcf6..d9cf6dc086d 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -701,10 +701,10 @@ impl TwoWaySearcher {
         //
         // What's going on is we have some critical factorization (u, v) of the
         // needle, and we want to determine whether u is a suffix of
-        // &v[0..period]. If it is, we use "Algorithm CP1". Otherwise we use
+        // &v[..period]. If it is, we use "Algorithm CP1". Otherwise we use
         // "Algorithm CP2", which is optimized for when the period of the needle
         // is large.
-        if &needle[0..crit_pos] == &needle[period.. period + crit_pos] {
+        if &needle[..crit_pos] == &needle[period.. period + crit_pos] {
             TwoWaySearcher {
                 crit_pos: crit_pos,
                 period: period,
@@ -1412,7 +1412,7 @@ impl StrExt for str {
     #[inline]
     fn starts_with(&self, needle: &str) -> bool {
         let n = needle.len();
-        self.len() >= n && needle.as_bytes() == &self.as_bytes()[0..n]
+        self.len() >= n && needle.as_bytes() == &self.as_bytes()[..n]
     }
 
     #[inline]
diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs
index 4aca830cb94..5baeae236b3 100644
--- a/src/libcore/tuple.rs
+++ b/src/libcore/tuple.rs
@@ -35,9 +35,6 @@
 
 #![stable]
 
-#[unstable = "this is just a documentation module and should not be part \
-              of the public api"]
-
 use clone::Clone;
 use cmp::*;
 use cmp::Ordering::*;
diff --git a/src/libcoretest/atomic.rs b/src/libcoretest/atomic.rs
index f8e943ec9f6..8e3c7f4595a 100644
--- a/src/libcoretest/atomic.rs
+++ b/src/libcoretest/atomic.rs
@@ -30,49 +30,49 @@ fn bool_and() {
 
 #[test]
 fn uint_and() {
-    let x = AtomicUint::new(0xf731);
+    let x = AtomicUsize::new(0xf731);
     assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
 }
 
 #[test]
 fn uint_or() {
-    let x = AtomicUint::new(0xf731);
+    let x = AtomicUsize::new(0xf731);
     assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
 }
 
 #[test]
 fn uint_xor() {
-    let x = AtomicUint::new(0xf731);
+    let x = AtomicUsize::new(0xf731);
     assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
 }
 
 #[test]
 fn int_and() {
-    let x = AtomicInt::new(0xf731);
+    let x = AtomicIsize::new(0xf731);
     assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
 }
 
 #[test]
 fn int_or() {
-    let x = AtomicInt::new(0xf731);
+    let x = AtomicIsize::new(0xf731);
     assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
 }
 
 #[test]
 fn int_xor() {
-    let x = AtomicInt::new(0xf731);
+    let x = AtomicIsize::new(0xf731);
     assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
 }
 
 static S_BOOL : AtomicBool = ATOMIC_BOOL_INIT;
-static S_INT  : AtomicInt  = ATOMIC_INT_INIT;
-static S_UINT : AtomicUint = ATOMIC_UINT_INIT;
+static S_INT  : AtomicIsize  = ATOMIC_ISIZE_INIT;
+static S_UINT : AtomicUsize = ATOMIC_USIZE_INIT;
 
 #[test]
 fn static_init() {
diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs
index 7b6b4f84808..2e29b1c41c4 100644
--- a/src/libcoretest/char.rs
+++ b/src/libcoretest/char.rs
@@ -167,7 +167,7 @@ fn test_encode_utf8() {
     fn check(input: char, expect: &[u8]) {
         let mut buf = [0u8; 4];
         let n = input.encode_utf8(buf.as_mut_slice()).unwrap_or(0);
-        assert_eq!(&buf[0..n], expect);
+        assert_eq!(&buf[..n], expect);
     }
 
     check('x', &[0x78]);
@@ -181,7 +181,7 @@ fn test_encode_utf16() {
     fn check(input: char, expect: &[u16]) {
         let mut buf = [0u16; 2];
         let n = input.encode_utf16(buf.as_mut_slice()).unwrap_or(0);
-        assert_eq!(&buf[0..n], expect);
+        assert_eq!(&buf[..n], expect);
     }
 
     check('x', &[0x0078]);
diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs
index 61266a92649..26819bf9209 100644
--- a/src/libcoretest/iter.rs
+++ b/src/libcoretest/iter.rs
@@ -288,7 +288,7 @@ fn test_iterator_len() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     assert_eq!(v[..4].iter().count(), 4);
     assert_eq!(v[..10].iter().count(), 10);
-    assert_eq!(v[0..0].iter().count(), 0);
+    assert_eq!(v[..0].iter().count(), 0);
 }
 
 #[test]
@@ -296,31 +296,31 @@ fn test_iterator_sum() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     assert_eq!(v[..4].iter().map(|&x| x).sum(), 6);
     assert_eq!(v.iter().map(|&x| x).sum(), 55);
-    assert_eq!(v[0..0].iter().map(|&x| x).sum(), 0);
+    assert_eq!(v[..0].iter().map(|&x| x).sum(), 0);
 }
 
 #[test]
 fn test_iterator_product() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-    assert_eq!(v[0..4].iter().map(|&x| x).product(), 0);
+    assert_eq!(v[..4].iter().map(|&x| x).product(), 0);
     assert_eq!(v[1..5].iter().map(|&x| x).product(), 24);
-    assert_eq!(v[0..0].iter().map(|&x| x).product(), 1);
+    assert_eq!(v[..0].iter().map(|&x| x).product(), 1);
 }
 
 #[test]
 fn test_iterator_max() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-    assert_eq!(v[0..4].iter().map(|&x| x).max(), Some(3));
+    assert_eq!(v[..4].iter().map(|&x| x).max(), Some(3));
     assert_eq!(v.iter().map(|&x| x).max(), Some(10));
-    assert_eq!(v[0..0].iter().map(|&x| x).max(), None);
+    assert_eq!(v[..0].iter().map(|&x| x).max(), None);
 }
 
 #[test]
 fn test_iterator_min() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-    assert_eq!(v[0..4].iter().map(|&x| x).min(), Some(0));
+    assert_eq!(v[..4].iter().map(|&x| x).min(), Some(0));
     assert_eq!(v.iter().map(|&x| x).min(), Some(0));
-    assert_eq!(v[0..0].iter().map(|&x| x).min(), None);
+    assert_eq!(v[..0].iter().map(|&x| x).min(), None);
 }
 
 #[test]
@@ -373,7 +373,7 @@ fn test_all() {
     assert!(v.iter().all(|&x| x < 10));
     assert!(!v.iter().all(|&x| x % 2 == 0));
     assert!(!v.iter().all(|&x| x > 100));
-    assert!(v[0..0].iter().all(|_| panic!()));
+    assert!(v[..0].iter().all(|_| panic!()));
 }
 
 #[test]
@@ -382,7 +382,7 @@ fn test_any() {
     assert!(v.iter().any(|&x| x < 10));
     assert!(v.iter().any(|&x| x % 2 == 0));
     assert!(!v.iter().any(|&x| x > 100));
-    assert!(!v[0..0].iter().any(|_| panic!()));
+    assert!(!v[..0].iter().any(|_| panic!()));
 }
 
 #[test]
diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs
index 0d371dbe153..0c7b72612fa 100644
--- a/src/libcoretest/lib.rs
+++ b/src/libcoretest/lib.rs
@@ -12,6 +12,7 @@
 #![feature(unboxed_closures)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate core;
 extern crate test;
diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs
index 96b50e8bccb..3dc209e6fcb 100644
--- a/src/libcoretest/mem.rs
+++ b/src/libcoretest/mem.rs
@@ -19,18 +19,14 @@ fn size_of_basic() {
 }
 
 #[test]
-#[cfg(any(target_arch = "x86",
-          target_arch = "arm",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(target_pointer_width = "32")]
 fn size_of_32() {
     assert_eq!(size_of::<uint>(), 4u);
     assert_eq!(size_of::<*const uint>(), 4u);
 }
 
 #[test]
-#[cfg(any(target_arch = "x86_64",
-          target_arch = "aarch64"))]
+#[cfg(target_pointer_width = "64")]
 fn size_of_64() {
     assert_eq!(size_of::<uint>(), 8u);
     assert_eq!(size_of::<*const uint>(), 8u);
@@ -52,18 +48,14 @@ fn align_of_basic() {
 }
 
 #[test]
-#[cfg(any(target_arch = "x86",
-          target_arch = "arm",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(target_pointer_width = "32")]
 fn align_of_32() {
     assert_eq!(align_of::<uint>(), 4u);
     assert_eq!(align_of::<*const uint>(), 4u);
 }
 
 #[test]
-#[cfg(any(target_arch = "x86_64",
-          target_arch = "aarch64"))]
+#[cfg(target_pointer_width = "64")]
 fn align_of_64() {
     assert_eq!(align_of::<uint>(), 8u);
     assert_eq!(align_of::<*const uint>(), 8u);
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs
index fb6c98515f7..f0a2ab3d1d6 100644
--- a/src/libflate/lib.rs
+++ b/src/libflate/lib.rs
@@ -18,6 +18,7 @@
 #![unstable]
 #![staged_api]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 70ad8d28d27..0ff15327441 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -26,6 +26,7 @@
 
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 pub use self::Piece::*;
 pub use self::Position::*;
@@ -286,7 +287,7 @@ impl<'a> Parser<'a> {
             flags: 0,
             precision: CountImplied,
             width: CountImplied,
-            ty: &self.input[0..0],
+            ty: &self.input[..0],
         };
         if !self.consume(':') { return spec }
 
@@ -395,7 +396,7 @@ impl<'a> Parser<'a> {
                 self.cur.next();
                 pos
             }
-            Some(..) | None => { return &self.input[0..0]; }
+            Some(..) | None => { return &self.input[..0]; }
         };
         let mut end;
         loop {
diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index 470ef6e7e57..c2114d4c6df 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -88,6 +88,7 @@
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 #![deny(missing_docs)]
 
 #[cfg(test)] #[macro_use] extern crate log;
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index b48fe2e4278..2d7d88f0f35 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -274,6 +274,7 @@
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 use self::LabelText::*;
 
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index c866deafee4..0ad18e25329 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -13,6 +13,7 @@
 #![cfg_attr(not(feature = "cargo-build"), unstable)]
 #![cfg_attr(not(feature = "cargo-build"), staged_api)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 #![no_std]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
@@ -497,7 +498,8 @@ pub mod types {
         #[cfg(any(target_arch = "x86",
                   target_arch = "arm",
                   target_arch = "mips",
-                  target_arch = "mipsel"))]
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod arch {
             pub mod c95 {
                 pub type c_char = i8;
@@ -528,7 +530,8 @@ pub mod types {
             }
             #[cfg(any(target_arch = "x86",
                       target_arch = "mips",
-                      target_arch = "mipsel"))]
+                      target_arch = "mipsel",
+                      target_arch = "powerpc"))]
             pub mod posix88 {
                 pub type off_t = i32;
                 pub type dev_t = u64;
@@ -642,7 +645,9 @@ pub mod types {
                     pub __size: [u32; 9]
                 }
             }
-            #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+            #[cfg(any(target_arch = "mips",
+                      target_arch = "mipsel",
+                      target_arch = "powerpc"))]
             pub mod posix01 {
                 use types::os::arch::c95::{c_long, c_ulong, time_t};
                 use types::os::arch::posix88::{gid_t, ino_t};
@@ -2697,7 +2702,9 @@ pub mod consts {
             pub const EHWPOISON: c_int = 133;
         }
 
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod posix88 {
             use types::os::arch::c95::c_int;
             use types::common::c95::c_void;
@@ -2982,7 +2989,8 @@ pub mod consts {
             #[cfg(all(target_os = "linux",
                       any(target_arch = "mips",
                           target_arch = "mipsel",
-                          target_arch = "aarch64")))]
+                          target_arch = "aarch64",
+                          target_arch = "powerpc")))]
             pub const PTHREAD_STACK_MIN: size_t = 131072;
 
             pub const CLOCK_REALTIME: c_int = 0;
@@ -3040,7 +3048,9 @@ pub mod consts {
             pub const SHUT_WR: c_int = 1;
             pub const SHUT_RDWR: c_int = 2;
         }
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
@@ -3115,7 +3125,9 @@ pub mod consts {
             pub const MAP_NONBLOCK : c_int = 0x010000;
             pub const MAP_STACK : c_int = 0x020000;
         }
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod extra {
             use types::os::arch::c95::c_int;
 
@@ -4157,6 +4169,27 @@ pub mod funcs {
                 pub fn malloc(size: size_t) -> *mut c_void;
                 pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
                 pub fn free(p: *mut c_void);
+
+                /// Exits the running program in a possibly dangerous manner.
+                ///
+                /// # Unsafety
+                ///
+                /// While this forces your program to exit, it does so in a way that has
+                /// consequences. This will skip all unwinding code, which means that anything
+                /// relying on unwinding for cleanup (such as flushing and closing a buffer to a
+                /// file) may act in an unexpected way.
+                ///
+                /// # Examples
+                ///
+                /// ```no_run
+                /// extern crate libc;
+                ///
+                /// fn main() {
+                ///     unsafe {
+                ///         libc::exit(1);
+                ///     }
+                /// }
+                /// ```
                 pub fn exit(status: c_int) -> !;
                 pub fn _exit(status: c_int) -> !;
                 pub fn atexit(cb: extern fn()) -> c_int;
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index a166dc369cb..dbd88434127 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -169,6 +169,7 @@
 #![feature(slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 #![deny(missing_docs)]
 
 extern crate regex;
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 4d605253ab0..853eb41d011 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -23,6 +23,7 @@
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 #![no_std]
 #![unstable]
 #![staged_api]
@@ -270,8 +271,7 @@ pub trait Rng : Sized {
     /// let choices = [1i, 2, 4, 8, 16, 32];
     /// let mut rng = thread_rng();
     /// println!("{:?}", rng.choose(&choices));
-    /// # // uncomment when slicing syntax is stable
-    /// //assert_eq!(rng.choose(&choices[0..0]), None);
+    /// assert_eq!(rng.choose(&choices[..0]), None);
     /// ```
     fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
         if values.is_empty() {
diff --git a/src/librbml/io.rs b/src/librbml/io.rs
index bdc00d7db97..f39860c8695 100644
--- a/src/librbml/io.rs
+++ b/src/librbml/io.rs
@@ -95,7 +95,7 @@ impl Writer for SeekableMemWriter {
             // there (left), and what will be appended on the end (right)
             let cap = self.buf.len() - self.pos;
             let (left, right) = if cap <= buf.len() {
-                (&buf[0..cap], &buf[cap..])
+                (&buf[..cap], &buf[cap..])
             } else {
                 let result: (_, &[_]) = (buf, &[]);
                 result
diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs
index 6a7062a419e..f28600e5e69 100644
--- a/src/librbml/lib.rs
+++ b/src/librbml/lib.rs
@@ -27,6 +27,7 @@
 #![allow(unknown_features)]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate serialize;
 #[macro_use] extern crate log;
diff --git a/src/libregex/lib.rs b/src/libregex/lib.rs
index 45f42336ceb..002b74cf1ef 100644
--- a/src/libregex/lib.rs
+++ b/src/libregex/lib.rs
@@ -24,6 +24,7 @@
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![allow(unknown_features)]
+#![allow(unstable)]
 #![feature(slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
diff --git a/src/librustc/README.txt b/src/librustc/README.txt
index e79ee7fa647..697dddca74f 100644
--- a/src/librustc/README.txt
+++ b/src/librustc/README.txt
@@ -68,7 +68,7 @@ util     - ubiquitous types and helper functions
 lib      - bindings to LLVM
 
 The entry-point for the compiler is main() in the librustc_trans
-crate. But the 
+crate.
 
 The 3 central data structures:
 ------------------------------
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index fb7c5296d02..62869064551 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -29,12 +29,15 @@
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![feature(rustc_diagnostic_macros)]
+#![allow(unstable)]
 
 extern crate arena;
 extern crate flate;
+extern crate fmt_macros;
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
+extern crate regex;
 extern crate rustc_llvm;
 extern crate rustc_back;
 extern crate serialize;
@@ -42,6 +45,7 @@ extern crate rbml;
 extern crate collections;
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
+#[macro_use] #[no_link] extern crate rustc_bitflags;
 
 extern crate "serialize" as rustc_serialize; // used by deriving
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 620b8f277dd..59808b302f4 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -666,6 +666,7 @@ impl LintPass for UnusedAttributes {
             "must_use",
             "stable",
             "unstable",
+            "rustc_on_unimplemented",
 
             // FIXME: #19470 this shouldn't be needed forever
             "old_orphan_check",
@@ -773,9 +774,8 @@ impl LintPass for UnusedResults {
                         warned |= check_must_use(cx, &it.attrs[], s.span);
                     }
                 } else {
-                    csearch::get_item_attrs(&cx.sess().cstore, did, |attrs| {
-                        warned |= check_must_use(cx, &attrs[], s.span);
-                    });
+                    let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
+                    warned |= check_must_use(cx, &attrs[], s.span);
                 }
             }
             _ => {}
@@ -1731,7 +1731,7 @@ impl LintPass for Stability {
         let mut span = e.span;
 
         let id = match e.node {
-            ast::ExprPath(..) | ast::ExprStruct(..) => {
+            ast::ExprPath(..) | ast::ExprQPath(..) | ast::ExprStruct(..) => {
                 match cx.tcx.def_map.borrow().get(&e.id) {
                     Some(&def) => def.def_id(),
                     None => return
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index a8326cc060a..5de683f8a4f 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -58,8 +58,8 @@ fn dump_crates(cstore: &CStore) {
         debug!("  hash: {}", data.hash());
         opt_source.map(|cs| {
             let CrateSource { dylib, rlib, cnum: _ } = cs;
-            dylib.map(|dl| debug!("  dylib: {}", dl.display()));
-            rlib.map(|rl|  debug!("   rlib: {}", rl.display()));
+            dylib.map(|dl| debug!("  dylib: {}", dl.0.display()));
+            rlib.map(|rl|  debug!("   rlib: {}", rl.0.display()));
         });
     })
 }
@@ -305,8 +305,8 @@ impl<'a> CrateReader<'a> {
         }
     }
 
-    fn existing_match(&self, name: &str,
-                      hash: Option<&Svh>) -> Option<ast::CrateNum> {
+    fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
+                      -> Option<ast::CrateNum> {
         let mut ret = None;
         self.sess.cstore.iter_crate_data(|cnum, data| {
             if data.name != name { return }
@@ -317,27 +317,37 @@ impl<'a> CrateReader<'a> {
                 None => {}
             }
 
-            // When the hash is None we're dealing with a top-level dependency in
-            // which case we may have a specification on the command line for this
-            // library. Even though an upstream library may have loaded something of
-            // the same name, we have to make sure it was loaded from the exact same
-            // location as well.
+            // When the hash is None we're dealing with a top-level dependency
+            // in which case we may have a specification on the command line for
+            // this library. Even though an upstream library may have loaded
+            // something of the same name, we have to make sure it was loaded
+            // from the exact same location as well.
             //
             // We're also sure to compare *paths*, not actual byte slices. The
             // `source` stores paths which are normalized which may be different
             // from the strings on the command line.
             let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
-            match self.sess.opts.externs.get(name) {
-                Some(locs) => {
-                    let found = locs.iter().any(|l| {
-                        let l = fs::realpath(&Path::new(&l[])).ok();
-                        l == source.dylib || l == source.rlib
-                    });
-                    if found {
-                        ret = Some(cnum);
-                    }
+            if let Some(locs) = self.sess.opts.externs.get(name) {
+                let found = locs.iter().any(|l| {
+                    let l = fs::realpath(&Path::new(&l[])).ok();
+                    source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
+                    source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
+                });
+                if found {
+                    ret = Some(cnum);
                 }
-                None => ret = Some(cnum),
+            }
+
+            // Alright, so we've gotten this far which means that `data` has the
+            // right name, we don't have a hash, and we don't have a --extern
+            // pointing for ourselves. We're still not quite yet done because we
+            // have to make sure that this crate was found in the crate lookup
+            // path (this is a top-level dependency) as we don't want to
+            // implicitly load anything inside the dependency lookup path.
+            let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
+                                  .unwrap().1;
+            if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
+                ret = Some(cnum);
             }
         });
         return ret;
@@ -359,8 +369,8 @@ impl<'a> CrateReader<'a> {
         let crate_paths = if root.is_none() {
             Some(CratePaths {
                 ident: ident.to_string(),
-                dylib: lib.dylib.clone(),
-                rlib:  lib.rlib.clone(),
+                dylib: lib.dylib.clone().map(|p| p.0),
+                rlib:  lib.rlib.clone().map(|p| p.0),
             })
         } else {
             None
@@ -400,7 +410,7 @@ impl<'a> CrateReader<'a> {
                      kind: PathKind)
                          -> (ast::CrateNum, Rc<cstore::crate_metadata>,
                              cstore::CrateSource) {
-        match self.existing_match(name, hash) {
+        match self.existing_match(name, hash, kind) {
             None => {
                 let mut load_ctxt = loader::Context {
                     sess: self.sess,
@@ -483,8 +493,8 @@ impl<'a> CrateReader<'a> {
         let library = match load_ctxt.maybe_load_library_crate() {
             Some(l) => l,
             None if is_cross => {
-                // Try loading from target crates. This will abort later if we try to
-                // load a plugin registrar function,
+                // Try loading from target crates. This will abort later if we
+                // try to load a plugin registrar function,
                 target_only = true;
                 should_link = info.should_link;
 
@@ -497,7 +507,9 @@ impl<'a> CrateReader<'a> {
         };
 
         let dylib = library.dylib.clone();
-        let register = should_link && self.existing_match(info.name.as_slice(), None).is_none();
+        let register = should_link && self.existing_match(info.name.as_slice(),
+                                                          None,
+                                                          PathKind::Crate).is_none();
         let metadata = if register {
             // Register crate now to avoid double-reading metadata
             let (_, cmd, _) = self.register_crate(&None, &info.ident[],
@@ -511,7 +523,7 @@ impl<'a> CrateReader<'a> {
         PluginMetadata {
             sess: self.sess,
             metadata: metadata,
-            dylib: dylib,
+            dylib: dylib.map(|p| p.0),
             info: info,
             vi_span: span,
             target_only: target_only,
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index cfff7c9935b..e34fb37e1c5 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -203,13 +203,11 @@ pub fn get_methods_if_impl(cstore: &cstore::CStore,
     decoder::get_methods_if_impl(cstore.intr.clone(), &*cdata, def.node)
 }
 
-pub fn get_item_attrs<F>(cstore: &cstore::CStore,
-                         def_id: ast::DefId,
-                         f: F) where
-    F: FnOnce(Vec<ast::Attribute>),
-{
+pub fn get_item_attrs(cstore: &cstore::CStore,
+                      def_id: ast::DefId)
+                      -> Vec<ast::Attribute> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_item_attrs(&*cdata, def_id.node, f)
+    decoder::get_item_attrs(&*cdata, def_id.node)
 }
 
 pub fn get_struct_fields(cstore: &cstore::CStore,
@@ -264,6 +262,15 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
     }
 }
 
+pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
+                               def: ast::DefId)
+                               -> Option<ast::ImplPolarity>
+{
+    let cstore = &tcx.sess.cstore;
+    let cdata = cstore.get_crate_data(def.krate);
+    decoder::get_impl_polarity(&*cdata, def.node)
+}
+
 // Given a def_id for an impl, return the trait it implements,
 // if there is one.
 pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index ec0b80c3a53..49e03376a8c 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -20,6 +20,7 @@ pub use self::NativeLibraryKind::*;
 use back::svh::Svh;
 use metadata::decoder;
 use metadata::loader;
+use session::search_paths::PathKind;
 use util::nodemap::{FnvHashMap, NodeMap};
 
 use std::cell::RefCell;
@@ -65,8 +66,8 @@ pub enum NativeLibraryKind {
 // must be non-None.
 #[derive(PartialEq, Clone)]
 pub struct CrateSource {
-    pub dylib: Option<Path>,
-    pub rlib: Option<Path>,
+    pub dylib: Option<(Path, PathKind)>,
+    pub rlib: Option<(Path, PathKind)>,
     pub cnum: ast::CrateNum,
 }
 
@@ -178,10 +179,10 @@ impl CStore {
         let mut libs = self.used_crate_sources.borrow()
             .iter()
             .map(|src| (src.cnum, match prefer {
-                RequireDynamic => src.dylib.clone(),
-                RequireStatic => src.rlib.clone(),
+                RequireDynamic => src.dylib.clone().map(|p| p.0),
+                RequireStatic => src.rlib.clone().map(|p| p.0),
             }))
-            .collect::<Vec<(ast::CrateNum, Option<Path>)>>();
+            .collect::<Vec<_>>();
         libs.sort_by(|&(a, _), &(b, _)| {
             ordering.position_elem(&a).cmp(&ordering.position_elem(&b))
         });
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 5ac8f908bf1..6bf1798d246 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -371,6 +371,15 @@ fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety {
     }
 }
 
+fn parse_polarity(item_doc: rbml::Doc) -> ast::ImplPolarity {
+    let polarity_doc = reader::get_doc(item_doc, tag_polarity);
+    if reader::doc_as_u8(polarity_doc) != 0 {
+        ast::ImplPolarity::Negative
+    } else {
+        ast::ImplPolarity::Positive
+    }
+}
+
 fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
     let names_doc = reader::get_doc(item_doc, tag_associated_type_names);
     let mut names = Vec::new();
@@ -436,6 +445,20 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
     }
 }
 
+pub fn get_impl_polarity<'tcx>(cdata: Cmd,
+                               id: ast::NodeId)
+                               -> Option<ast::ImplPolarity>
+{
+    let item_doc = lookup_item(id, cdata.data());
+    let fam = item_family(item_doc);
+    match fam {
+        Family::Impl => {
+            Some(parse_polarity(item_doc))
+        }
+        _ => None
+    }
+}
+
 pub fn get_impl_trait<'tcx>(cdata: Cmd,
                             id: ast::NodeId,
                             tcx: &ty::ctxt<'tcx>)
@@ -1025,18 +1048,16 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
     ret
 }
 
-pub fn get_item_attrs<F>(cdata: Cmd,
-                         orig_node_id: ast::NodeId,
-                         f: F) where
-    F: FnOnce(Vec<ast::Attribute>),
-{
+pub fn get_item_attrs(cdata: Cmd,
+                      orig_node_id: ast::NodeId)
+                      -> Vec<ast::Attribute> {
     // The attributes for a tuple struct are attached to the definition, not the ctor;
     // we assume that someone passing in a tuple struct ctor is actually wanting to
     // look at the definition
     let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id);
     let node_id = node_id.map(|x| x.node).unwrap_or(orig_node_id);
     let item = lookup_item(node_id, cdata.data());
-    f(get_attributes(item));
+    get_attributes(item)
 }
 
 pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attribute>> {
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index e8160487e16..ddee1f79d6a 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -39,13 +39,13 @@ pub struct FileSearch<'a> {
 
 impl<'a> FileSearch<'a> {
     pub fn for_each_lib_search_path<F>(&self, mut f: F) where
-        F: FnMut(&Path) -> FileMatch,
+        F: FnMut(&Path, PathKind) -> FileMatch,
     {
         let mut visited_dirs = HashSet::new();
         let mut found = false;
 
-        for path in self.search_paths.iter(self.kind) {
-            match f(path) {
+        for (path, kind) in self.search_paths.iter(self.kind) {
+            match f(path, kind) {
                 FileMatches => found = true,
                 FileDoesntMatch => ()
             }
@@ -54,9 +54,9 @@ impl<'a> FileSearch<'a> {
 
         debug!("filesearch: searching lib path");
         let tlib_path = make_target_lib_path(self.sysroot,
-                                    self.triple);
+                                             self.triple);
         if !visited_dirs.contains(tlib_path.as_vec()) {
-            match f(&tlib_path) {
+            match f(&tlib_path, PathKind::All) {
                 FileMatches => found = true,
                 FileDoesntMatch => ()
             }
@@ -76,7 +76,7 @@ impl<'a> FileSearch<'a> {
                     visited_dirs.insert(tlib_path.as_vec().to_vec());
                     // Don't keep searching the RUST_PATH if one match turns up --
                     // if we did, we'd get a "multiple matching crates" error
-                    match f(&tlib_path) {
+                    match f(&tlib_path, PathKind::All) {
                        FileMatches => {
                            break;
                        }
@@ -91,8 +91,10 @@ impl<'a> FileSearch<'a> {
         make_target_lib_path(self.sysroot, self.triple)
     }
 
-    pub fn search<F>(&self, mut pick: F) where F: FnMut(&Path) -> FileMatch {
-        self.for_each_lib_search_path(|lib_search_path| {
+    pub fn search<F>(&self, mut pick: F)
+        where F: FnMut(&Path, PathKind) -> FileMatch
+    {
+        self.for_each_lib_search_path(|lib_search_path, kind| {
             debug!("searching {}", lib_search_path.display());
             match fs::readdir(lib_search_path) {
                 Ok(files) => {
@@ -108,7 +110,7 @@ impl<'a> FileSearch<'a> {
                     let files2 = files.iter().filter(|p| !is_rlib(p));
                     for path in files1.chain(files2) {
                         debug!("testing {}", path.display());
-                        let maybe_picked = pick(path);
+                        let maybe_picked = pick(path, kind);
                         match maybe_picked {
                             FileMatches => {
                                 debug!("picked {}", path.display());
@@ -142,7 +144,7 @@ impl<'a> FileSearch<'a> {
     // Returns a list of directories where target-specific dylibs might be located.
     pub fn get_dylib_search_paths(&self) -> Vec<Path> {
         let mut paths = Vec::new();
-        self.for_each_lib_search_path(|lib_search_path| {
+        self.for_each_lib_search_path(|lib_search_path, _| {
             paths.push(lib_search_path.clone());
             FileDoesntMatch
         });
@@ -272,12 +274,12 @@ fn find_libdir(sysroot: &Path) -> String {
         }
     }
 
-    #[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+    #[cfg(target_pointer_width = "64")]
     fn primary_libdir_name() -> String {
         "lib64".to_string()
     }
 
-    #[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+    #[cfg(target_pointer_width = "32")]
     fn primary_libdir_name() -> String {
         "lib32".to_string()
     }
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index f749721cca8..70b6ddf23fd 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -215,6 +215,7 @@
 use back::archive::{METADATA_FILENAME};
 use back::svh::Svh;
 use session::Session;
+use session::search_paths::PathKind;
 use llvm;
 use llvm::{False, ObjectFile, mk_section_iter};
 use llvm::archive_ro::ArchiveRO;
@@ -229,7 +230,7 @@ use rustc_back::target::Target;
 
 use std::ffi::CString;
 use std::cmp;
-use std::collections::{HashMap, HashSet};
+use std::collections::HashMap;
 use std::io::fs::PathExtensions;
 use std::io;
 use std::ptr;
@@ -260,8 +261,8 @@ pub struct Context<'a> {
 }
 
 pub struct Library {
-    pub dylib: Option<Path>,
-    pub rlib: Option<Path>,
+    pub dylib: Option<(Path, PathKind)>,
+    pub rlib: Option<(Path, PathKind)>,
     pub metadata: MetadataBlob,
 }
 
@@ -384,7 +385,7 @@ impl<'a> Context<'a> {
         // of the crate id (path/name/id).
         //
         // The goal of this step is to look at as little metadata as possible.
-        self.filesearch.search(|path| {
+        self.filesearch.search(|path, kind| {
             let file = match path.filename_str() {
                 None => return FileDoesntMatch,
                 Some(file) => file,
@@ -404,12 +405,12 @@ impl<'a> Context<'a> {
 
             let hash_str = hash.to_string();
             let slot = candidates.entry(hash_str).get().unwrap_or_else(
-                |vacant_entry| vacant_entry.insert((HashSet::new(), HashSet::new())));
+                |vacant_entry| vacant_entry.insert((HashMap::new(), HashMap::new())));
             let (ref mut rlibs, ref mut dylibs) = *slot;
             if rlib {
-                rlibs.insert(fs::realpath(path).unwrap());
+                rlibs.insert(fs::realpath(path).unwrap(), kind);
             } else {
-                dylibs.insert(fs::realpath(path).unwrap());
+                dylibs.insert(fs::realpath(path).unwrap(), kind);
             }
 
             FileMatches
@@ -453,16 +454,16 @@ impl<'a> Context<'a> {
                 self.sess.note("candidates:");
                 for lib in libraries.iter() {
                     match lib.dylib {
-                        Some(ref p) => {
+                        Some((ref p, _)) => {
                             self.sess.note(&format!("path: {}",
                                                    p.display())[]);
                         }
                         None => {}
                     }
                     match lib.rlib {
-                        Some(ref p) => {
+                        Some((ref p, _)) => {
                             self.sess.note(&format!("path: {}",
-                                                   p.display())[]);
+                                                    p.display())[]);
                         }
                         None => {}
                     }
@@ -483,9 +484,9 @@ impl<'a> Context<'a> {
     // read the metadata from it if `*slot` is `None`. If the metadata couldn't
     // be read, it is assumed that the file isn't a valid rust library (no
     // errors are emitted).
-    fn extract_one(&mut self, m: HashSet<Path>, flavor: &str,
-                   slot: &mut Option<MetadataBlob>) -> Option<Path> {
-        let mut ret = None::<Path>;
+    fn extract_one(&mut self, m: HashMap<Path, PathKind>, flavor: &str,
+                   slot: &mut Option<MetadataBlob>) -> Option<(Path, PathKind)> {
+        let mut ret = None::<(Path, PathKind)>;
         let mut error = 0u;
 
         if slot.is_some() {
@@ -500,7 +501,7 @@ impl<'a> Context<'a> {
             }
         }
 
-        for lib in m.into_iter() {
+        for (lib, kind) in m.into_iter() {
             info!("{} reading metadata from: {}", flavor, lib.display());
             let metadata = match get_metadata_section(self.target.options.is_like_osx,
                                                       &lib) {
@@ -525,7 +526,7 @@ impl<'a> Context<'a> {
                                            self.crate_name)[]);
                 self.sess.span_note(self.span,
                                     &format!(r"candidate #1: {}",
-                                            ret.as_ref().unwrap()
+                                            ret.as_ref().unwrap().0
                                                .display())[]);
                 error = 1;
                 ret = None;
@@ -538,7 +539,7 @@ impl<'a> Context<'a> {
                 continue
             }
             *slot = Some(metadata);
-            ret = Some(lib);
+            ret = Some((lib, kind));
         }
         return if error > 0 {None} else {ret}
     }
@@ -606,8 +607,8 @@ impl<'a> Context<'a> {
         // rlibs/dylibs.
         let sess = self.sess;
         let dylibname = self.dylibname();
-        let mut rlibs = HashSet::new();
-        let mut dylibs = HashSet::new();
+        let mut rlibs = HashMap::new();
+        let mut dylibs = HashMap::new();
         {
             let mut locs = locs.iter().map(|l| Path::new(&l[])).filter(|loc| {
                 if !loc.exists() {
@@ -637,13 +638,15 @@ impl<'a> Context<'a> {
                 false
             });
 
-            // Now that we have an iterator of good candidates, make sure there's at
-            // most one rlib and at most one dylib.
+            // Now that we have an iterator of good candidates, make sure
+            // there's at most one rlib and at most one dylib.
             for loc in locs {
                 if loc.filename_str().unwrap().ends_with(".rlib") {
-                    rlibs.insert(fs::realpath(&loc).unwrap());
+                    rlibs.insert(fs::realpath(&loc).unwrap(),
+                                 PathKind::ExternFlag);
                 } else {
-                    dylibs.insert(fs::realpath(&loc).unwrap());
+                    dylibs.insert(fs::realpath(&loc).unwrap(),
+                                  PathKind::ExternFlag);
                 }
             }
         };
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index b601ea59486..07b520e5865 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -495,7 +495,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             ast::ExprMac(..) |
             ast::ExprClosure(..) |
             ast::ExprLit(..) |
-            ast::ExprPath(..) => {
+            ast::ExprPath(..) |
+            ast::ExprQPath(..) => {
                 self.straightline(expr, pred, None::<ast::Expr>.iter())
             }
         }
diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs
index f4db2b6e61d..3d8348e8f5a 100644
--- a/src/librustc/middle/cfg/graphviz.rs
+++ b/src/librustc/middle/cfg/graphviz.rs
@@ -28,6 +28,8 @@ pub struct LabelledCFG<'a, 'ast: 'a> {
     pub ast_map: &'a ast_map::Map<'ast>,
     pub cfg: &'a cfg::CFG,
     pub name: String,
+    /// `labelled_edges` controls whether we emit labels on the edges
+    pub labelled_edges: bool,
 }
 
 fn replace_newline_with_backslash_l(s: String) -> String {
@@ -75,6 +77,9 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
 
     fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> {
         let mut label = String::new();
+        if !self.labelled_edges {
+            return dot::LabelText::EscStr(label.into_cow());
+        }
         let mut put_one = false;
         for (i, &node_id) in e.data.exiting_scopes.iter().enumerate() {
             if put_one {
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 621d7274b3f..202020a9033 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -111,7 +111,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
                            expression");
             }
         }
-        ast::ExprPath(_) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             match v.tcx.def_map.borrow()[e.id] {
                 DefStatic(..) | DefConst(..) |
                 DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 43f39a67f5c..a1a90395b3b 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -926,7 +926,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         }
     };
     head.map(|mut head| {
-        head.push_all(&r[0..col]);
+        head.push_all(&r[..col]);
         head.push_all(&r[(col + 1)..]);
         head
     })
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 154272d2deb..026aa3c5ccf 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -228,7 +228,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
                           "{} are not allowed to have custom pointers",
                           self.msg());
             }
-            ast::ExprPath(..) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 match ty::resolve_expr(self.tcx, e) {
                     def::DefStatic(..) if self.mode == InConstant => {
                         let msg = "constants cannot refer to other statics, \
diff --git a/src/librustc/middle/check_static_recursion.rs b/src/librustc/middle/check_static_recursion.rs
index e2a0738def1..86a58dae45a 100644
--- a/src/librustc/middle/check_static_recursion.rs
+++ b/src/librustc/middle/check_static_recursion.rs
@@ -93,7 +93,7 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
 
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprPath(..) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 match self.def_map.borrow().get(&e.id) {
                     Some(&DefStatic(def_id, _)) |
                     Some(&DefConst(def_id)) if
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 52352e920ce..c998d178c22 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -244,7 +244,7 @@ impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> {
 
             // FIXME: (#3728) we can probably do something CCI-ish
             // surrounding nonlocal constants. But we don't yet.
-            ast::ExprPath(_) => self.lookup_constness(e),
+            ast::ExprPath(_) | ast::ExprQPath(_) => self.lookup_constness(e),
 
             ast::ExprRepeat(..) => general_const,
 
@@ -356,6 +356,13 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
             }
         }
 
+        ast::ExprQPath(_) => {
+            match lookup_const(tcx, expr) {
+                Some(actual) => return const_expr_to_pat(tcx, actual),
+                _ => unreachable!()
+            }
+        }
+
         _ => ast::PatLit(P(expr.clone()))
     };
     P(ast::Pat { id: expr.id, node: pat, span: expr.span })
@@ -542,7 +549,7 @@ pub fn eval_const_expr_partial(tcx: &ty::ctxt, e: &Expr) -> Result<const_val, St
                 ty::ty_float(ast::TyF64) => (f64, const_float, f64)
             }))
       }
-      ast::ExprPath(_) => {
+      ast::ExprPath(_) | ast::ExprQPath(_) => {
           match lookup_const(tcx, e) {
               Some(actual_e) => eval_const_expr_partial(tcx, &*actual_e),
               None => Err("non-constant path in constant expr".to_string())
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index f7eea6e5cb7..abb8f35f662 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -175,7 +175,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
             ast::ExprInlineAsm(..) => {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
-            ast::ExprPath(..) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index e5eb439d42c..a5f2dc398e9 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -424,7 +424,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                 self.walk_expr(&**subexpr)
             }
 
-            ast::ExprPath(..) => { }
+            ast::ExprPath(_) | ast::ExprQPath(_) => { }
 
             ast::ExprUnary(ast::UnDeref, ref base) => {      // *base
                 if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index ab1c41f6968..8fd44f144e1 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -613,6 +613,39 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         self.commit_unconditionally(move || self.try(move |_| f()))
     }
 
+    /// Execute `f` and commit only the region bindings if successful.
+    /// The function f must be very careful not to leak any non-region
+    /// variables that get created.
+    pub fn commit_regions_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
+        F: FnOnce() -> Result<T, E>
+    {
+        debug!("commit_regions_if_ok()");
+        let CombinedSnapshot { type_snapshot,
+                               int_snapshot,
+                               float_snapshot,
+                               region_vars_snapshot } = self.start_snapshot();
+
+        let r = self.try(move |_| f());
+
+        // Roll back any non-region bindings - they should be resolved
+        // inside `f`, with, e.g. `resolve_type_vars_if_possible`.
+        self.type_variables
+            .borrow_mut()
+            .rollback_to(type_snapshot);
+        self.int_unification_table
+            .borrow_mut()
+            .rollback_to(int_snapshot);
+        self.float_unification_table
+            .borrow_mut()
+            .rollback_to(float_snapshot);
+
+        // Commit region vars that may escape through resolved types.
+        self.region_vars
+            .commit(region_vars_snapshot);
+
+        r
+    }
+
     /// Execute `f`, unroll bindings on panic
     pub fn try<T, E, F>(&self, f: F) -> Result<T, E> where
         F: FnOnce(&CombinedSnapshot) -> Result<T, E>
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 1b1dca00422..6b9e5b2ceea 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -447,7 +447,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
 fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
-      ast::ExprPath(_) => {
+      ast::ExprPath(_) | ast::ExprQPath(_) => {
         let def = ir.tcx.def_map.borrow()[expr.id].clone();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if let DefLocal(..) = def {
@@ -960,7 +960,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         match expr.node {
           // Interesting cases with control flow or which gen/kill
 
-          ast::ExprPath(_) => {
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
               self.access_path(expr, succ, ACC_READ | ACC_USE)
           }
 
@@ -1289,7 +1289,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         // just ignore such cases and treat them as reads.
 
         match expr.node {
-            ast::ExprPath(_) => succ,
+            ast::ExprPath(_) | ast::ExprQPath(_) => succ,
             ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
             ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
             _ => self.propagate_through_expr(expr, succ)
@@ -1300,7 +1300,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
                     -> LiveNode {
         match expr.node {
-          ast::ExprPath(_) => self.access_path(expr, succ, acc),
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
+              self.access_path(expr, succ, acc)
+          }
 
           // We do not track other lvalues, so just propagate through
           // to their subcomponents.  Also, it may happen that
@@ -1492,7 +1494,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
       ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
       ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
-      ast::ExprRange(..) => {
+      ast::ExprRange(..) | ast::ExprQPath(..) => {
         visit::walk_expr(this, expr);
       }
       ast::ExprIfLet(..) => {
@@ -1583,7 +1585,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
-            ast::ExprPath(_) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 51ec7528432..90fe6b49911 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -520,7 +520,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             }
           }
 
-          ast::ExprPath(_) => {
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
             let def = (*self.tcx().def_map.borrow())[expr.id];
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index aa37c2fe348..74797dfd77a 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -11,28 +11,14 @@
 //! A pass that checks to make sure private fields and methods aren't used
 //! outside their scopes. This pass will also generate a set of exported items
 //! which are available for use externally when compiled as a library.
+
 pub use self::PrivateDep::*;
 pub use self::ImportUse::*;
 pub use self::LastPrivate::*;
-use self::PrivacyResult::*;
-use self::FieldName::*;
-
-use std::mem::replace;
 
-use metadata::csearch;
-use middle::def;
-use middle::ty::{self, Ty};
-use middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam, MethodTypeParam};
-use middle::ty::{MethodStatic, MethodStaticUnboxedClosure, MethodObject, MethodTraitObject};
 use util::nodemap::{DefIdSet, NodeMap, NodeSet};
 
-use syntax::{ast, ast_map};
-use syntax::ast_util::{is_local, local_def, PostExpansionMethod};
-use syntax::codemap::Span;
-use syntax::parse::token;
-use syntax::visit::{self, Visitor};
-
-type Context<'a, 'tcx> = (&'a MethodMap<'tcx>, &'a def::ExportMap);
+use syntax::ast;
 
 /// A set of AST nodes exported by the crate.
 pub type ExportedItems = NodeSet;
@@ -84,1547 +70,3 @@ impl LastPrivate {
         }
     }
 }
-
-/// Result of a checking operation - None => no errors were found. Some => an
-/// error and contains the span and message for reporting that error and
-/// optionally the same for a note about the error.
-type CheckResult = Option<(Span, String, Option<(Span, String)>)>;
-
-////////////////////////////////////////////////////////////////////////////////
-/// The parent visitor, used to determine what's the parent of what (node-wise)
-////////////////////////////////////////////////////////////////////////////////
-
-struct ParentVisitor {
-    parents: NodeMap<ast::NodeId>,
-    curparent: ast::NodeId,
-}
-
-impl<'v> Visitor<'v> for ParentVisitor {
-    fn visit_item(&mut self, item: &ast::Item) {
-        self.parents.insert(item.id, self.curparent);
-
-        let prev = self.curparent;
-        match item.node {
-            ast::ItemMod(..) => { self.curparent = item.id; }
-            // Enum variants are parented to the enum definition itself because
-            // they inherit privacy
-            ast::ItemEnum(ref def, _) => {
-                for variant in def.variants.iter() {
-                    // The parent is considered the enclosing enum because the
-                    // enum will dictate the privacy visibility of this variant
-                    // instead.
-                    self.parents.insert(variant.node.id, item.id);
-                }
-            }
-
-            // Trait methods are always considered "public", but if the trait is
-            // private then we need some private item in the chain from the
-            // method to the root. In this case, if the trait is private, then
-            // parent all the methods to the trait to indicate that they're
-            // private.
-            ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
-                for m in methods.iter() {
-                    match *m {
-                        ast::ProvidedMethod(ref m) => {
-                            self.parents.insert(m.id, item.id);
-                        }
-                        ast::RequiredMethod(ref m) => {
-                            self.parents.insert(m.id, item.id);
-                        }
-                        ast::TypeTraitItem(_) => {}
-                    };
-                }
-            }
-
-            _ => {}
-        }
-        visit::walk_item(self, item);
-        self.curparent = prev;
-    }
-
-    fn visit_foreign_item(&mut self, a: &ast::ForeignItem) {
-        self.parents.insert(a.id, self.curparent);
-        visit::walk_foreign_item(self, a);
-    }
-
-    fn visit_fn(&mut self, a: visit::FnKind<'v>, b: &'v ast::FnDecl,
-                c: &'v ast::Block, d: Span, id: ast::NodeId) {
-        // We already took care of some trait methods above, otherwise things
-        // like impl methods and pub trait methods are parented to the
-        // containing module, not the containing trait.
-        if !self.parents.contains_key(&id) {
-            self.parents.insert(id, self.curparent);
-        }
-        visit::walk_fn(self, a, b, c, d);
-    }
-
-    fn visit_struct_def(&mut self, s: &ast::StructDef, _: ast::Ident,
-                        _: &'v ast::Generics, n: ast::NodeId) {
-        // Struct constructors are parented to their struct definitions because
-        // they essentially are the struct definitions.
-        match s.ctor_id {
-            Some(id) => { self.parents.insert(id, n); }
-            None => {}
-        }
-
-        // While we have the id of the struct definition, go ahead and parent
-        // all the fields.
-        for field in s.fields.iter() {
-            self.parents.insert(field.node.id, self.curparent);
-        }
-        visit::walk_struct_def(self, s)
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// The embargo visitor, used to determine the exports of the ast
-////////////////////////////////////////////////////////////////////////////////
-
-struct EmbargoVisitor<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    export_map: &'a def::ExportMap,
-
-    // This flag is an indicator of whether the previous item in the
-    // hierarchical chain was exported or not. This is the indicator of whether
-    // children should be exported as well. Note that this can flip from false
-    // to true if a reexported module is entered (or an action similar).
-    prev_exported: bool,
-
-    // This is a list of all exported items in the AST. An exported item is any
-    // function/method/item which is usable by external crates. This essentially
-    // means that the result is "public all the way down", but the "path down"
-    // may jump across private boundaries through reexport statements.
-    exported_items: ExportedItems,
-
-    // This sets contains all the destination nodes which are publicly
-    // re-exported. This is *not* a set of all reexported nodes, only a set of
-    // all nodes which are reexported *and* reachable from external crates. This
-    // means that the destination of the reexport is exported, and hence the
-    // destination must also be exported.
-    reexports: NodeSet,
-
-    // These two fields are closely related to one another in that they are only
-    // used for generation of the 'PublicItems' set, not for privacy checking at
-    // all
-    public_items: PublicItems,
-    prev_public: bool,
-}
-
-impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
-    // There are checks inside of privacy which depend on knowing whether a
-    // trait should be exported or not. The two current consumers of this are:
-    //
-    //  1. Should default methods of a trait be exported?
-    //  2. Should the methods of an implementation of a trait be exported?
-    //
-    // The answer to both of these questions partly rely on whether the trait
-    // itself is exported or not. If the trait is somehow exported, then the
-    // answers to both questions must be yes. Right now this question involves
-    // more analysis than is currently done in rustc, so we conservatively
-    // answer "yes" so that all traits need to be exported.
-    fn exported_trait(&self, _id: ast::NodeId) -> bool {
-        true
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        let orig_all_pub = self.prev_public;
-        self.prev_public = orig_all_pub && item.vis == ast::Public;
-        if self.prev_public {
-            self.public_items.insert(item.id);
-        }
-
-        let orig_all_exported = self.prev_exported;
-        match item.node {
-            // impls/extern blocks do not break the "public chain" because they
-            // cannot have visibility qualifiers on them anyway
-            ast::ItemImpl(..) | ast::ItemForeignMod(..) => {}
-
-            // Traits are a little special in that even if they themselves are
-            // not public they may still be exported.
-            ast::ItemTrait(..) => {
-                self.prev_exported = self.exported_trait(item.id);
-            }
-
-            // Private by default, hence we only retain the "public chain" if
-            // `pub` is explicitly listed.
-            _ => {
-                self.prev_exported =
-                    (orig_all_exported && item.vis == ast::Public) ||
-                     self.reexports.contains(&item.id);
-            }
-        }
-
-        let public_first = self.prev_exported &&
-                           self.exported_items.insert(item.id);
-
-        match item.node {
-            // Enum variants inherit from their parent, so if the enum is
-            // public all variants are public unless they're explicitly priv
-            ast::ItemEnum(ref def, _) if public_first => {
-                for variant in def.variants.iter() {
-                    self.exported_items.insert(variant.node.id);
-                }
-            }
-
-            // Implementations are a little tricky to determine what's exported
-            // out of them. Here's a few cases which are currently defined:
-            //
-            // * Impls for private types do not need to export their methods
-            //   (either public or private methods)
-            //
-            // * Impls for public types only have public methods exported
-            //
-            // * Public trait impls for public types must have all methods
-            //   exported.
-            //
-            // * Private trait impls for public types can be ignored
-            //
-            // * Public trait impls for private types have their methods
-            //   exported. I'm not entirely certain that this is the correct
-            //   thing to do, but I have seen use cases of where this will cause
-            //   undefined symbols at linkage time if this case is not handled.
-            //
-            // * Private trait impls for private types can be completely ignored
-            ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
-                let public_ty = match ty.node {
-                    ast::TyPath(_, id) => {
-                        match self.tcx.def_map.borrow()[id].clone() {
-                            def::DefPrimTy(..) => true,
-                            def => {
-                                let did = def.def_id();
-                                !is_local(did) ||
-                                 self.exported_items.contains(&did.node)
-                            }
-                        }
-                    }
-                    _ => true,
-                };
-                let tr = ty::impl_trait_ref(self.tcx, local_def(item.id));
-                let public_trait = tr.clone().map_or(false, |tr| {
-                    !is_local(tr.def_id) ||
-                     self.exported_items.contains(&tr.def_id.node)
-                });
-
-                if public_ty || public_trait {
-                    for impl_item in impl_items.iter() {
-                        match *impl_item {
-                            ast::MethodImplItem(ref method) => {
-                                let meth_public =
-                                    match method.pe_explicit_self().node {
-                                        ast::SelfStatic => public_ty,
-                                        _ => true,
-                                    } && method.pe_vis() == ast::Public;
-                                if meth_public || tr.is_some() {
-                                    self.exported_items.insert(method.id);
-                                }
-                            }
-                            ast::TypeImplItem(_) => {}
-                        }
-                    }
-                }
-            }
-
-            // Default methods on traits are all public so long as the trait
-            // is public
-            ast::ItemTrait(_, _, _, ref methods) if public_first => {
-                for method in methods.iter() {
-                    match *method {
-                        ast::ProvidedMethod(ref m) => {
-                            debug!("provided {}", m.id);
-                            self.exported_items.insert(m.id);
-                        }
-                        ast::RequiredMethod(ref m) => {
-                            debug!("required {}", m.id);
-                            self.exported_items.insert(m.id);
-                        }
-                        ast::TypeTraitItem(ref t) => {
-                            debug!("typedef {}", t.ty_param.id);
-                            self.exported_items.insert(t.ty_param.id);
-                        }
-                    }
-                }
-            }
-
-            // Struct constructors are public if the struct is all public.
-            ast::ItemStruct(ref def, _) if public_first => {
-                match def.ctor_id {
-                    Some(id) => { self.exported_items.insert(id); }
-                    None => {}
-                }
-            }
-
-            ast::ItemTy(ref ty, _) if public_first => {
-                if let ast::TyPath(_, id) = ty.node {
-                    match self.tcx.def_map.borrow()[id].clone() {
-                        def::DefPrimTy(..) | def::DefTyParam(..) => {},
-                        def => {
-                            let did = def.def_id();
-                            if is_local(did) {
-                                self.exported_items.insert(did.node);
-                            }
-                        }
-                    }
-                }
-            }
-
-            _ => {}
-        }
-
-        visit::walk_item(self, item);
-
-        self.prev_exported = orig_all_exported;
-        self.prev_public = orig_all_pub;
-    }
-
-    fn visit_foreign_item(&mut self, a: &ast::ForeignItem) {
-        if (self.prev_exported && a.vis == ast::Public) || self.reexports.contains(&a.id) {
-            self.exported_items.insert(a.id);
-        }
-    }
-
-    fn visit_mod(&mut self, m: &ast::Mod, _sp: Span, id: ast::NodeId) {
-        // This code is here instead of in visit_item so that the
-        // crate module gets processed as well.
-        if self.prev_exported {
-            assert!(self.export_map.contains_key(&id), "wut {}", id);
-            for export in self.export_map[id].iter() {
-                if is_local(export.def_id) {
-                    self.reexports.insert(export.def_id.node);
-                }
-            }
-        }
-        visit::walk_mod(self, m)
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// The privacy visitor, where privacy checks take place (violations reported)
-////////////////////////////////////////////////////////////////////////////////
-
-struct PrivacyVisitor<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    curitem: ast::NodeId,
-    in_foreign: bool,
-    parents: NodeMap<ast::NodeId>,
-    external_exports: ExternalExports,
-    last_private_map: LastPrivateMap,
-}
-
-enum PrivacyResult {
-    Allowable,
-    ExternallyDenied,
-    DisallowedBy(ast::NodeId),
-}
-
-enum FieldName {
-    UnnamedField(uint), // index
-    // FIXME #6993: change type (and name) from Ident to Name
-    NamedField(ast::Ident),
-}
-
-impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
-    // used when debugging
-    fn nodestr(&self, id: ast::NodeId) -> String {
-        self.tcx.map.node_to_string(id).to_string()
-    }
-
-    // Determines whether the given definition is public from the point of view
-    // of the current item.
-    fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
-        if !is_local(did) {
-            if self.external_exports.contains(&did) {
-                debug!("privacy - {:?} was externally exported", did);
-                return Allowable;
-            }
-            debug!("privacy - is {:?} a public method", did);
-
-            return match self.tcx.impl_or_trait_items.borrow().get(&did) {
-                Some(&ty::MethodTraitItem(ref meth)) => {
-                    debug!("privacy - well at least it's a method: {:?}",
-                           *meth);
-                    match meth.container {
-                        ty::TraitContainer(id) => {
-                            debug!("privacy - recursing on trait {:?}", id);
-                            self.def_privacy(id)
-                        }
-                        ty::ImplContainer(id) => {
-                            match ty::impl_trait_ref(self.tcx, id) {
-                                Some(t) => {
-                                    debug!("privacy - impl of trait {:?}", id);
-                                    self.def_privacy(t.def_id)
-                                }
-                                None => {
-                                    debug!("privacy - found a method {:?}",
-                                            meth.vis);
-                                    if meth.vis == ast::Public {
-                                        Allowable
-                                    } else {
-                                        ExternallyDenied
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-                Some(&ty::TypeTraitItem(ref typedef)) => {
-                    match typedef.container {
-                        ty::TraitContainer(id) => {
-                            debug!("privacy - recursing on trait {:?}", id);
-                            self.def_privacy(id)
-                        }
-                        ty::ImplContainer(id) => {
-                            match ty::impl_trait_ref(self.tcx, id) {
-                                Some(t) => {
-                                    debug!("privacy - impl of trait {:?}", id);
-                                    self.def_privacy(t.def_id)
-                                }
-                                None => {
-                                    debug!("privacy - found a typedef {:?}",
-                                            typedef.vis);
-                                    if typedef.vis == ast::Public {
-                                        Allowable
-                                    } else {
-                                        ExternallyDenied
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-                None => {
-                    debug!("privacy - nope, not even a method");
-                    ExternallyDenied
-                }
-            };
-        }
-
-        debug!("privacy - local {} not public all the way down",
-               self.tcx.map.node_to_string(did.node));
-        // return quickly for things in the same module
-        if self.parents.get(&did.node) == self.parents.get(&self.curitem) {
-            debug!("privacy - same parent, we're done here");
-            return Allowable;
-        }
-
-        // We now know that there is at least one private member between the
-        // destination and the root.
-        let mut closest_private_id = did.node;
-        loop {
-            debug!("privacy - examining {}", self.nodestr(closest_private_id));
-            let vis = match self.tcx.map.find(closest_private_id) {
-                // If this item is a method, then we know for sure that it's an
-                // actual method and not a static method. The reason for this is
-                // that these cases are only hit in the ExprMethodCall
-                // expression, and ExprCall will have its path checked later
-                // (the path of the trait/impl) if it's a static method.
-                //
-                // With this information, then we can completely ignore all
-                // trait methods. The privacy violation would be if the trait
-                // couldn't get imported, not if the method couldn't be used
-                // (all trait methods are public).
-                //
-                // However, if this is an impl method, then we dictate this
-                // decision solely based on the privacy of the method
-                // invocation.
-                // FIXME(#10573) is this the right behavior? Why not consider
-                //               where the method was defined?
-                Some(ast_map::NodeImplItem(ii)) => {
-                    match *ii {
-                        ast::MethodImplItem(ref m) => {
-                            let imp = self.tcx.map
-                                          .get_parent_did(closest_private_id);
-                            match ty::impl_trait_ref(self.tcx, imp) {
-                                Some(..) => return Allowable,
-                                _ if m.pe_vis() == ast::Public => {
-                                    return Allowable
-                                }
-                                _ => m.pe_vis()
-                            }
-                        }
-                        ast::TypeImplItem(_) => return Allowable,
-                    }
-                }
-                Some(ast_map::NodeTraitItem(_)) => {
-                    return Allowable;
-                }
-
-                // This is not a method call, extract the visibility as one
-                // would normally look at it
-                Some(ast_map::NodeItem(it)) => it.vis,
-                Some(ast_map::NodeForeignItem(_)) => {
-                    self.tcx.map.get_foreign_vis(closest_private_id)
-                }
-                Some(ast_map::NodeVariant(..)) => {
-                    ast::Public // need to move up a level (to the enum)
-                }
-                _ => ast::Public,
-            };
-            if vis != ast::Public { break }
-            // if we've reached the root, then everything was allowable and this
-            // access is public.
-            if closest_private_id == ast::CRATE_NODE_ID { return Allowable }
-            closest_private_id = self.parents[closest_private_id];
-
-            // If we reached the top, then we were public all the way down and
-            // we can allow this access.
-            if closest_private_id == ast::DUMMY_NODE_ID { return Allowable }
-        }
-        debug!("privacy - closest priv {}", self.nodestr(closest_private_id));
-        if self.private_accessible(closest_private_id) {
-            Allowable
-        } else {
-            DisallowedBy(closest_private_id)
-        }
-    }
-
-    /// For a local private node in the AST, this function will determine
-    /// whether the node is accessible by the current module that iteration is
-    /// inside.
-    fn private_accessible(&self, id: ast::NodeId) -> bool {
-        let parent = self.parents[id];
-        debug!("privacy - accessible parent {}", self.nodestr(parent));
-
-        // After finding `did`'s closest private member, we roll ourselves back
-        // to see if this private member's parent is anywhere in our ancestry.
-        // By the privacy rules, we can access all of our ancestor's private
-        // members, so that's why we test the parent, and not the did itself.
-        let mut cur = self.curitem;
-        loop {
-            debug!("privacy - questioning {}, {}", self.nodestr(cur), cur);
-            match cur {
-                // If the relevant parent is in our history, then we're allowed
-                // to look inside any of our ancestor's immediate private items,
-                // so this access is valid.
-                x if x == parent => return true,
-
-                // If we've reached the root, then we couldn't access this item
-                // in the first place
-                ast::DUMMY_NODE_ID => return false,
-
-                // Keep going up
-                _ => {}
-            }
-
-            cur = self.parents[cur];
-        }
-    }
-
-    fn report_error(&self, result: CheckResult) -> bool {
-        match result {
-            None => true,
-            Some((span, msg, note)) => {
-                self.tcx.sess.span_err(span, &msg[]);
-                match note {
-                    Some((span, msg)) => {
-                        self.tcx.sess.span_note(span, &msg[])
-                    }
-                    None => {},
-                }
-                false
-            },
-        }
-    }
-
-    /// Guarantee that a particular definition is public. Returns a CheckResult
-    /// which contains any errors found. These can be reported using `report_error`.
-    /// If the result is `None`, no errors were found.
-    fn ensure_public(&self, span: Span, to_check: ast::DefId,
-                     source_did: Option<ast::DefId>, msg: &str) -> CheckResult {
-        let id = match self.def_privacy(to_check) {
-            ExternallyDenied => {
-                return Some((span, format!("{} is private", msg), None))
-            }
-            Allowable => return None,
-            DisallowedBy(id) => id,
-        };
-
-        // If we're disallowed by a particular id, then we attempt to give a
-        // nice error message to say why it was disallowed. It was either
-        // because the item itself is private or because its parent is private
-        // and its parent isn't in our ancestry.
-        let (err_span, err_msg) = if id == source_did.unwrap_or(to_check).node {
-            return Some((span, format!("{} is private", msg), None));
-        } else {
-            (span, format!("{} is inaccessible", msg))
-        };
-        let item = match self.tcx.map.find(id) {
-            Some(ast_map::NodeItem(item)) => {
-                match item.node {
-                    // If an impl disallowed this item, then this is resolve's
-                    // way of saying that a struct/enum's static method was
-                    // invoked, and the struct/enum itself is private. Crawl
-                    // back up the chains to find the relevant struct/enum that
-                    // was private.
-                    ast::ItemImpl(_, _, _, _, ref ty, _) => {
-                        let id = match ty.node {
-                            ast::TyPath(_, id) => id,
-                            _ => return Some((err_span, err_msg, None)),
-                        };
-                        let def = self.tcx.def_map.borrow()[id].clone();
-                        let did = def.def_id();
-                        assert!(is_local(did));
-                        match self.tcx.map.get(did.node) {
-                            ast_map::NodeItem(item) => item,
-                            _ => self.tcx.sess.span_bug(item.span,
-                                                        "path is not an item")
-                        }
-                    }
-                    _ => item
-                }
-            }
-            Some(..) | None => return Some((err_span, err_msg, None)),
-        };
-        let desc = match item.node {
-            ast::ItemMod(..) => "module",
-            ast::ItemTrait(..) => "trait",
-            ast::ItemStruct(..) => "struct",
-            ast::ItemEnum(..) => "enum",
-            _ => return Some((err_span, err_msg, None))
-        };
-        let msg = format!("{} `{}` is private", desc,
-                          token::get_ident(item.ident));
-        Some((err_span, err_msg, Some((span, msg))))
-    }
-
-    // Checks that a field is in scope.
-    fn check_field(&mut self,
-                   span: Span,
-                   id: ast::DefId,
-                   name: FieldName) {
-        let fields = ty::lookup_struct_fields(self.tcx, id);
-        let field = match name {
-            NamedField(ident) => {
-                debug!("privacy - check named field {} in struct {:?}", ident.name, id);
-                fields.iter().find(|f| f.name == ident.name).unwrap()
-            }
-            UnnamedField(idx) => &fields[idx]
-        };
-        if field.vis == ast::Public ||
-            (is_local(field.id) && self.private_accessible(field.id.node)) {
-            return
-        }
-
-        let struct_type = ty::lookup_item_type(self.tcx, id).ty;
-        let struct_desc = match struct_type.sty {
-            ty::ty_struct(_, _) =>
-                format!("struct `{}`", ty::item_path_str(self.tcx, id)),
-            // struct variant fields have inherited visibility
-            ty::ty_enum(..) => return,
-            _ => self.tcx.sess.span_bug(span, "can't find struct for field")
-        };
-        let msg = match name {
-            NamedField(name) => format!("field `{}` of {} is private",
-                                        token::get_ident(name), struct_desc),
-            UnnamedField(idx) => format!("field #{} of {} is private",
-                                         idx + 1, struct_desc),
-        };
-        self.tcx.sess.span_err(span, &msg[]);
-    }
-
-    // Given the ID of a method, checks to ensure it's in scope.
-    fn check_static_method(&mut self,
-                           span: Span,
-                           method_id: ast::DefId,
-                           name: ast::Ident) {
-        // If the method is a default method, we need to use the def_id of
-        // the default implementation.
-        let method_id = match ty::impl_or_trait_item(self.tcx, method_id) {
-            ty::MethodTraitItem(method_type) => {
-                method_type.provided_source.unwrap_or(method_id)
-            }
-            ty::TypeTraitItem(_) => method_id,
-        };
-
-        let string = token::get_ident(name);
-        self.report_error(self.ensure_public(span,
-                                             method_id,
-                                             None,
-                                             &format!("method `{}`",
-                                                     string)[]));
-    }
-
-    // Checks that a path is in scope.
-    fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
-        debug!("privacy - path {}", self.nodestr(path_id));
-        let orig_def = self.tcx.def_map.borrow()[path_id].clone();
-        let ck = |&: tyname: &str| {
-            let ck_public = |&: def: ast::DefId| {
-                let name = token::get_ident(path.segments.last().unwrap().identifier);
-                let origdid = orig_def.def_id();
-                self.ensure_public(span,
-                                   def,
-                                   Some(origdid),
-                                   &format!("{} `{}`", tyname, name)[])
-            };
-
-            match self.last_private_map[path_id] {
-                LastMod(AllPublic) => {},
-                LastMod(DependsOn(def)) => {
-                    self.report_error(ck_public(def));
-                },
-                LastImport { value_priv,
-                             value_used: check_value,
-                             type_priv,
-                             type_used: check_type } => {
-                    // This dance with found_error is because we don't want to report
-                    // a privacy error twice for the same directive.
-                    let found_error = match (type_priv, check_type) {
-                        (Some(DependsOn(def)), Used) => {
-                            !self.report_error(ck_public(def))
-                        },
-                        _ => false,
-                    };
-                    if !found_error {
-                        match (value_priv, check_value) {
-                            (Some(DependsOn(def)), Used) => {
-                                self.report_error(ck_public(def));
-                            },
-                            _ => {},
-                        }
-                    }
-                    // If an import is not used in either namespace, we still
-                    // want to check that it could be legal. Therefore we check
-                    // in both namespaces and only report an error if both would
-                    // be illegal. We only report one error, even if it is
-                    // illegal to import from both namespaces.
-                    match (value_priv, check_value, type_priv, check_type) {
-                        (Some(p), Unused, None, _) |
-                        (None, _, Some(p), Unused) => {
-                            let p = match p {
-                                AllPublic => None,
-                                DependsOn(def) => ck_public(def),
-                            };
-                            if p.is_some() {
-                                self.report_error(p);
-                            }
-                        },
-                        (Some(v), Unused, Some(t), Unused) => {
-                            let v = match v {
-                                AllPublic => None,
-                                DependsOn(def) => ck_public(def),
-                            };
-                            let t = match t {
-                                AllPublic => None,
-                                DependsOn(def) => ck_public(def),
-                            };
-                            if let (Some(_), Some(t)) = (v, t) {
-                                self.report_error(Some(t));
-                            }
-                        },
-                        _ => {},
-                    }
-                },
-            }
-        };
-        // FIXME(#12334) Imports can refer to definitions in both the type and
-        // value namespaces. The privacy information is aware of this, but the
-        // def map is not. Therefore the names we work out below will not always
-        // be accurate and we can get slightly wonky error messages (but type
-        // checking is always correct).
-        match self.tcx.def_map.borrow()[path_id].clone() {
-            def::DefStaticMethod(..) => ck("static method"),
-            def::DefFn(..) => ck("function"),
-            def::DefStatic(..) => ck("static"),
-            def::DefConst(..) => ck("const"),
-            def::DefVariant(..) => ck("variant"),
-            def::DefTy(_, false) => ck("type"),
-            def::DefTy(_, true) => ck("enum"),
-            def::DefTrait(..) => ck("trait"),
-            def::DefStruct(..) => ck("struct"),
-            def::DefMethod(_, Some(..), _) => ck("trait method"),
-            def::DefMethod(..) => ck("method"),
-            def::DefMod(..) => ck("module"),
-            _ => {}
-        }
-    }
-
-    // Checks that a method is in scope.
-    fn check_method(&mut self, span: Span, origin: &MethodOrigin,
-                    ident: ast::Ident) {
-        match *origin {
-            MethodStatic(method_id) => {
-                self.check_static_method(span, method_id, ident)
-            }
-            MethodStaticUnboxedClosure(_) => {}
-            // Trait methods are always all public. The only controlling factor
-            // is whether the trait itself is accessible or not.
-            MethodTypeParam(MethodParam { ref trait_ref, .. }) |
-            MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
-                self.report_error(self.ensure_public(span, trait_ref.def_id,
-                                                     None, "source trait"));
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        let orig_curitem = replace(&mut self.curitem, item.id);
-        visit::walk_item(self, item);
-        self.curitem = orig_curitem;
-    }
-
-    fn visit_expr(&mut self, expr: &ast::Expr) {
-        match expr.node {
-            ast::ExprField(ref base, ident) => {
-                if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
-                    self.check_field(expr.span, id, NamedField(ident.node));
-                }
-            }
-            ast::ExprTupField(ref base, idx) => {
-                if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
-                    self.check_field(expr.span, id, UnnamedField(idx.node));
-                }
-            }
-            ast::ExprMethodCall(ident, _, _) => {
-                let method_call = MethodCall::expr(expr.id);
-                match self.tcx.method_map.borrow().get(&method_call) {
-                    None => {
-                        self.tcx.sess.span_bug(expr.span,
-                                                "method call not in \
-                                                method map");
-                    }
-                    Some(method) => {
-                        debug!("(privacy checking) checking impl method");
-                        self.check_method(expr.span, &method.origin, ident.node);
-                    }
-                }
-            }
-            ast::ExprStruct(_, ref fields, _) => {
-                match ty::expr_ty(self.tcx, expr).sty {
-                    ty::ty_struct(id, _) => {
-                        for field in (*fields).iter() {
-                            self.check_field(expr.span, id,
-                                             NamedField(field.ident.node));
-                        }
-                    }
-                    ty::ty_enum(_, _) => {
-                        match self.tcx.def_map.borrow()[expr.id].clone() {
-                            def::DefVariant(_, variant_id, _) => {
-                                for field in fields.iter() {
-                                    self.check_field(expr.span, variant_id,
-                                                     NamedField(field.ident.node));
-                                }
-                            }
-                            _ => self.tcx.sess.span_bug(expr.span,
-                                                        "resolve didn't \
-                                                         map enum struct \
-                                                         constructor to a \
-                                                         variant def"),
-                        }
-                    }
-                    _ => self.tcx.sess.span_bug(expr.span, "struct expr \
-                                                            didn't have \
-                                                            struct type?!"),
-                }
-            }
-            ast::ExprPath(..) => {
-                let guard = |&: did: ast::DefId| {
-                    let fields = ty::lookup_struct_fields(self.tcx, did);
-                    let any_priv = fields.iter().any(|f| {
-                        f.vis != ast::Public && (
-                            !is_local(f.id) ||
-                            !self.private_accessible(f.id.node))
-                    });
-                    if any_priv {
-                        self.tcx.sess.span_err(expr.span,
-                            "cannot invoke tuple struct constructor \
-                             with private fields");
-                    }
-                };
-                match self.tcx.def_map.borrow().get(&expr.id) {
-                    Some(&def::DefStruct(did)) => {
-                        guard(if is_local(did) {
-                            local_def(self.tcx.map.get_parent(did.node))
-                        } else {
-                            // "tuple structs" with zero fields (such as
-                            // `pub struct Foo;`) don't have a ctor_id, hence
-                            // the unwrap_or to the same struct id.
-                            let maybe_did =
-                                csearch::get_tuple_struct_definition_if_ctor(
-                                    &self.tcx.sess.cstore, did);
-                            maybe_did.unwrap_or(did)
-                        })
-                    }
-                    _ => {}
-                }
-            }
-            _ => {}
-        }
-
-        visit::walk_expr(self, expr);
-    }
-
-    fn visit_view_item(&mut self, a: &ast::ViewItem) {
-        match a.node {
-            ast::ViewItemExternCrate(..) => {}
-            ast::ViewItemUse(ref vpath) => {
-                match vpath.node {
-                    ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
-                    ast::ViewPathList(ref prefix, ref list, _) => {
-                        for pid in list.iter() {
-                            match pid.node {
-                                ast::PathListIdent { id, name } => {
-                                    debug!("privacy - ident item {}", id);
-                                    let seg = ast::PathSegment {
-                                        identifier: name,
-                                        parameters: ast::PathParameters::none(),
-                                    };
-                                    let segs = vec![seg];
-                                    let path = ast::Path {
-                                        global: false,
-                                        span: pid.span,
-                                        segments: segs,
-                                    };
-                                    self.check_path(pid.span, id, &path);
-                                }
-                                ast::PathListMod { id } => {
-                                    debug!("privacy - mod item {}", id);
-                                    self.check_path(pid.span, id, prefix);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        visit::walk_view_item(self, a);
-    }
-
-    fn visit_pat(&mut self, pattern: &ast::Pat) {
-        // Foreign functions do not have their patterns mapped in the def_map,
-        // and there's nothing really relevant there anyway, so don't bother
-        // checking privacy. If you can name the type then you can pass it to an
-        // external C function anyway.
-        if self.in_foreign { return }
-
-        match pattern.node {
-            ast::PatStruct(_, ref fields, _) => {
-                match ty::pat_ty(self.tcx, pattern).sty {
-                    ty::ty_struct(id, _) => {
-                        for field in fields.iter() {
-                            self.check_field(pattern.span, id,
-                                             NamedField(field.node.ident));
-                        }
-                    }
-                    ty::ty_enum(_, _) => {
-                        match self.tcx.def_map.borrow().get(&pattern.id) {
-                            Some(&def::DefVariant(_, variant_id, _)) => {
-                                for field in fields.iter() {
-                                    self.check_field(pattern.span, variant_id,
-                                                     NamedField(field.node.ident));
-                                }
-                            }
-                            _ => self.tcx.sess.span_bug(pattern.span,
-                                                        "resolve didn't \
-                                                         map enum struct \
-                                                         pattern to a \
-                                                         variant def"),
-                        }
-                    }
-                    _ => self.tcx.sess.span_bug(pattern.span,
-                                                "struct pattern didn't have \
-                                                 struct type?!"),
-                }
-            }
-
-            // Patterns which bind no fields are allowable (the path is check
-            // elsewhere).
-            ast::PatEnum(_, Some(ref fields)) => {
-                match ty::pat_ty(self.tcx, pattern).sty {
-                    ty::ty_struct(id, _) => {
-                        for (i, field) in fields.iter().enumerate() {
-                            if let ast::PatWild(..) = field.node {
-                                continue
-                            }
-                            self.check_field(field.span, id, UnnamedField(i));
-                        }
-                    }
-                    ty::ty_enum(..) => {
-                        // enum fields have no privacy at this time
-                    }
-                    _ => {}
-                }
-
-            }
-            _ => {}
-        }
-
-        visit::walk_pat(self, pattern);
-    }
-
-    fn visit_foreign_item(&mut self, fi: &ast::ForeignItem) {
-        self.in_foreign = true;
-        visit::walk_foreign_item(self, fi);
-        self.in_foreign = false;
-    }
-
-    fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
-        self.check_path(path.span, id, path);
-        visit::walk_path(self, path);
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-/// The privacy sanity check visitor, ensures unnecessary visibility isn't here
-////////////////////////////////////////////////////////////////////////////////
-
-struct SanePrivacyVisitor<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    in_fn: bool,
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        if self.in_fn {
-            self.check_all_inherited(item);
-        } else {
-            self.check_sane_privacy(item);
-        }
-
-        let in_fn = self.in_fn;
-        let orig_in_fn = replace(&mut self.in_fn, match item.node {
-            ast::ItemMod(..) => false, // modules turn privacy back on
-            _ => in_fn,           // otherwise we inherit
-        });
-        visit::walk_item(self, item);
-        self.in_fn = orig_in_fn;
-    }
-
-    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, _: ast::NodeId) {
-        // This catches both functions and methods
-        let orig_in_fn = replace(&mut self.in_fn, true);
-        visit::walk_fn(self, fk, fd, b, s);
-        self.in_fn = orig_in_fn;
-    }
-
-    fn visit_view_item(&mut self, i: &ast::ViewItem) {
-        match i.vis {
-            ast::Inherited => {}
-            ast::Public => {
-                if self.in_fn {
-                    self.tcx.sess.span_err(i.span, "unnecessary `pub`, imports \
-                                                    in functions are never \
-                                                    reachable");
-                } else if let ast::ViewItemExternCrate(..) = i.node {
-                    self.tcx.sess.span_err(i.span, "`pub` visibility \
-                                                    is not allowed");
-                }
-            }
-        }
-        visit::walk_view_item(self, i);
-    }
-}
-
-impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
-    /// Validates all of the visibility qualifiers placed on the item given. This
-    /// ensures that there are no extraneous qualifiers that don't actually do
-    /// anything. In theory these qualifiers wouldn't parse, but that may happen
-    /// later on down the road...
-    fn check_sane_privacy(&self, item: &ast::Item) {
-        let tcx = self.tcx;
-        let check_inherited = |&: sp: Span, vis: ast::Visibility, note: &str| {
-            if vis != ast::Inherited {
-                tcx.sess.span_err(sp, "unnecessary visibility qualifier");
-                if note.len() > 0 {
-                    tcx.sess.span_note(sp, note);
-                }
-            }
-        };
-        match item.node {
-            // implementations of traits don't need visibility qualifiers because
-            // that's controlled by having the trait in scope.
-            ast::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
-                check_inherited(item.span, item.vis,
-                                "visibility qualifiers have no effect on trait \
-                                 impls");
-                for impl_item in impl_items.iter() {
-                    match *impl_item {
-                        ast::MethodImplItem(ref m) => {
-                            check_inherited(m.span, m.pe_vis(), "");
-                        }
-                        ast::TypeImplItem(_) => {}
-                    }
-                }
-            }
-
-            ast::ItemImpl(..) => {
-                check_inherited(item.span, item.vis,
-                                "place qualifiers on individual methods instead");
-            }
-            ast::ItemForeignMod(..) => {
-                check_inherited(item.span, item.vis,
-                                "place qualifiers on individual functions \
-                                 instead");
-            }
-
-            ast::ItemEnum(ref def, _) => {
-                for v in def.variants.iter() {
-                    match v.node.vis {
-                        ast::Public => {
-                            if item.vis == ast::Public {
-                                tcx.sess.span_err(v.span, "unnecessary `pub` \
-                                                           visibility");
-                            }
-                        }
-                        ast::Inherited => {}
-                    }
-                }
-            }
-
-            ast::ItemTrait(_, _, _, ref methods) => {
-                for m in methods.iter() {
-                    match *m {
-                        ast::ProvidedMethod(ref m) => {
-                            check_inherited(m.span, m.pe_vis(),
-                                            "unnecessary visibility");
-                        }
-                        ast::RequiredMethod(ref m) => {
-                            check_inherited(m.span, m.vis,
-                                            "unnecessary visibility");
-                        }
-                        ast::TypeTraitItem(_) => {}
-                    }
-                }
-            }
-
-            ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) |
-            ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
-            ast::ItemMac(..) => {}
-        }
-    }
-
-    /// When inside of something like a function or a method, visibility has no
-    /// control over anything so this forbids any mention of any visibility
-    fn check_all_inherited(&self, item: &ast::Item) {
-        let tcx = self.tcx;
-        fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
-            if vis != ast::Inherited {
-                tcx.sess.span_err(sp, "visibility has no effect inside functions");
-            }
-        }
-        let check_struct = |&: def: &ast::StructDef| {
-            for f in def.fields.iter() {
-               match f.node.kind {
-                    ast::NamedField(_, p) => check_inherited(tcx, f.span, p),
-                    ast::UnnamedField(..) => {}
-                }
-            }
-        };
-        check_inherited(tcx, item.span, item.vis);
-        match item.node {
-            ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
-                for impl_item in impl_items.iter() {
-                    match *impl_item {
-                        ast::MethodImplItem(ref m) => {
-                            check_inherited(tcx, m.span, m.pe_vis());
-                        }
-                        ast::TypeImplItem(_) => {}
-                    }
-                }
-            }
-            ast::ItemForeignMod(ref fm) => {
-                for i in fm.items.iter() {
-                    check_inherited(tcx, i.span, i.vis);
-                }
-            }
-            ast::ItemEnum(ref def, _) => {
-                for v in def.variants.iter() {
-                    check_inherited(tcx, v.span, v.node.vis);
-                }
-            }
-
-            ast::ItemStruct(ref def, _) => check_struct(&**def),
-
-            ast::ItemTrait(_, _, _, ref methods) => {
-                for m in methods.iter() {
-                    match *m {
-                        ast::RequiredMethod(..) => {}
-                        ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span,
-                                                                m.pe_vis()),
-                        ast::TypeTraitItem(_) => {}
-                    }
-                }
-            }
-
-            ast::ItemStatic(..) | ast::ItemConst(..) |
-            ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
-            ast::ItemMac(..) => {}
-        }
-    }
-}
-
-struct VisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    exported_items: &'a ExportedItems,
-    public_items: &'a PublicItems,
-    in_variant: bool,
-}
-
-struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    inner: &'a VisiblePrivateTypesVisitor<'b, 'tcx>,
-    /// whether the type refers to private types.
-    contains_private: bool,
-    /// whether we've recurred at all (i.e. if we're pointing at the
-    /// first type on which visit_ty was called).
-    at_outer_type: bool,
-    // whether that first type is a public path.
-    outer_type_is_public_path: bool,
-}
-
-impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
-    fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
-        let did = match self.tcx.def_map.borrow().get(&path_id).cloned() {
-            // `int` etc. (None doesn't seem to occur.)
-            None | Some(def::DefPrimTy(..)) => return false,
-            Some(def) => def.def_id()
-        };
-        // A path can only be private if:
-        // it's in this crate...
-        if !is_local(did) {
-            return false
-        }
-        // .. and it corresponds to a private type in the AST (this returns
-        // None for type parameters)
-        match self.tcx.map.find(did.node) {
-            Some(ast_map::NodeItem(ref item)) => item.vis != ast::Public,
-            Some(_) | None => false,
-        }
-    }
-
-    fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
-        // FIXME: this would preferably be using `exported_items`, but all
-        // traits are exported currently (see `EmbargoVisitor.exported_trait`)
-        self.public_items.contains(&trait_id)
-    }
-
-    fn check_ty_param_bound(&self,
-                            ty_param_bound: &ast::TyParamBound) {
-        if let ast::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
-            if !self.tcx.sess.features.borrow().visible_private_types &&
-                self.path_is_private_type(trait_ref.trait_ref.ref_id) {
-                    let span = trait_ref.trait_ref.path.span;
-                    self.tcx.sess.span_err(span,
-                                           "private trait in exported type \
-                                            parameter bound");
-            }
-        }
-    }
-}
-
-impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
-    fn visit_ty(&mut self, ty: &ast::Ty) {
-        if let ast::TyPath(_, path_id) = ty.node {
-            if self.inner.path_is_private_type(path_id) {
-                self.contains_private = true;
-                // found what we're looking for so let's stop
-                // working.
-                return
-            } else if self.at_outer_type {
-                self.outer_type_is_public_path = true;
-            }
-        }
-        self.at_outer_type = false;
-        visit::walk_ty(self, ty)
-    }
-
-    // don't want to recurse into [, .. expr]
-    fn visit_expr(&mut self, _: &ast::Expr) {}
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        match item.node {
-            // contents of a private mod can be reexported, so we need
-            // to check internals.
-            ast::ItemMod(_) => {}
-
-            // An `extern {}` doesn't introduce a new privacy
-            // namespace (the contents have their own privacies).
-            ast::ItemForeignMod(_) => {}
-
-            ast::ItemTrait(_, _, ref bounds, _) => {
-                if !self.trait_is_public(item.id) {
-                    return
-                }
-
-                for bound in bounds.iter() {
-                    self.check_ty_param_bound(bound)
-                }
-            }
-
-            // impls need some special handling to try to offer useful
-            // error messages without (too many) false positives
-            // (i.e. we could just return here to not check them at
-            // all, or some worse estimation of whether an impl is
-            // publicly visible.
-            ast::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
-                // `impl [... for] Private` is never visible.
-                let self_contains_private;
-                // impl [... for] Public<...>, but not `impl [... for]
-                // ~[Public]` or `(Public,)` etc.
-                let self_is_public_path;
-
-                // check the properties of the Self type:
-                {
-                    let mut visitor = CheckTypeForPrivatenessVisitor {
-                        inner: self,
-                        contains_private: false,
-                        at_outer_type: true,
-                        outer_type_is_public_path: false,
-                    };
-                    visitor.visit_ty(&**self_);
-                    self_contains_private = visitor.contains_private;
-                    self_is_public_path = visitor.outer_type_is_public_path;
-                }
-
-                // miscellaneous info about the impl
-
-                // `true` iff this is `impl Private for ...`.
-                let not_private_trait =
-                    trait_ref.as_ref().map_or(true, // no trait counts as public trait
-                                              |tr| {
-                        let did = ty::trait_ref_to_def_id(self.tcx, tr);
-
-                        !is_local(did) || self.trait_is_public(did.node)
-                    });
-
-                // `true` iff this is a trait impl or at least one method is public.
-                //
-                // `impl Public { $( fn ...() {} )* }` is not visible.
-                //
-                // This is required over just using the methods' privacy
-                // directly because we might have `impl<T: Foo<Private>> ...`,
-                // and we shouldn't warn about the generics if all the methods
-                // are private (because `T` won't be visible externally).
-                let trait_or_some_public_method =
-                    trait_ref.is_some() ||
-                    impl_items.iter()
-                              .any(|impl_item| {
-                                  match *impl_item {
-                                      ast::MethodImplItem(ref m) => {
-                                          self.exported_items.contains(&m.id)
-                                      }
-                                      ast::TypeImplItem(_) => false,
-                                  }
-                              });
-
-                if !self_contains_private &&
-                        not_private_trait &&
-                        trait_or_some_public_method {
-
-                    visit::walk_generics(self, g);
-
-                    match *trait_ref {
-                        None => {
-                            for impl_item in impl_items.iter() {
-                                match *impl_item {
-                                    ast::MethodImplItem(ref method) => {
-                                        visit::walk_method_helper(self, &**method)
-                                    }
-                                    ast::TypeImplItem(_) => {}
-                                }
-                            }
-                        }
-                        Some(ref tr) => {
-                            // Any private types in a trait impl fall into two
-                            // categories.
-                            // 1. mentioned in the trait definition
-                            // 2. mentioned in the type params/generics
-                            //
-                            // Those in 1. can only occur if the trait is in
-                            // this crate and will've been warned about on the
-                            // trait definition (there's no need to warn twice
-                            // so we don't check the methods).
-                            //
-                            // Those in 2. are warned via walk_generics and this
-                            // call here.
-                            self.visit_trait_ref(tr)
-                        }
-                    }
-                } else if trait_ref.is_none() && self_is_public_path {
-                    // impl Public<Private> { ... }. Any public static
-                    // methods will be visible as `Public::foo`.
-                    let mut found_pub_static = false;
-                    for impl_item in impl_items.iter() {
-                        match *impl_item {
-                            ast::MethodImplItem(ref method) => {
-                                if method.pe_explicit_self().node ==
-                                        ast::SelfStatic &&
-                                        self.exported_items
-                                            .contains(&method.id) {
-                                    found_pub_static = true;
-                                    visit::walk_method_helper(self, &**method);
-                                }
-                            }
-                            ast::TypeImplItem(_) => {}
-                        }
-                    }
-                    if found_pub_static {
-                        visit::walk_generics(self, g)
-                    }
-                }
-                return
-            }
-
-            // `type ... = ...;` can contain private types, because
-            // we're introducing a new name.
-            ast::ItemTy(..) => return,
-
-            // not at all public, so we don't care
-            _ if !self.exported_items.contains(&item.id) => return,
-
-            _ => {}
-        }
-
-        // we've carefully constructed it so that if we're here, then
-        // any `visit_ty`'s will be called on things that are in
-        // public signatures, i.e. things that we're interested in for
-        // this visitor.
-        visit::walk_item(self, item);
-    }
-
-    fn visit_generics(&mut self, generics: &ast::Generics) {
-        for ty_param in generics.ty_params.iter() {
-            for bound in ty_param.bounds.iter() {
-                self.check_ty_param_bound(bound)
-            }
-        }
-        for predicate in generics.where_clause.predicates.iter() {
-            match predicate {
-                &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
-                    for bound in bound_pred.bounds.iter() {
-                        self.check_ty_param_bound(bound)
-                    }
-                }
-                &ast::WherePredicate::RegionPredicate(_) => {}
-                &ast::WherePredicate::EqPredicate(ref eq_pred) => {
-                    self.visit_ty(&*eq_pred.ty);
-                }
-            }
-        }
-    }
-
-    fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
-        if self.exported_items.contains(&item.id) {
-            visit::walk_foreign_item(self, item)
-        }
-    }
-
-    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
-                b: &'v ast::Block, s: Span, id: ast::NodeId) {
-        // needs special handling for methods.
-        if self.exported_items.contains(&id) {
-            visit::walk_fn(self, fk, fd, b, s);
-        }
-    }
-
-    fn visit_ty(&mut self, t: &ast::Ty) {
-        if let ast::TyPath(ref p, path_id) = t.node {
-            if !self.tcx.sess.features.borrow().visible_private_types &&
-                self.path_is_private_type(path_id) {
-                self.tcx.sess.span_err(p.span,
-                                       "private type in exported type signature");
-            }
-        }
-        visit::walk_ty(self, t)
-    }
-
-    fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) {
-        if self.exported_items.contains(&v.node.id) {
-            self.in_variant = true;
-            visit::walk_variant(self, v, g);
-            self.in_variant = false;
-        }
-    }
-
-    fn visit_struct_field(&mut self, s: &ast::StructField) {
-        match s.node.kind {
-            ast::NamedField(_, vis) if vis == ast::Public || self.in_variant => {
-                visit::walk_struct_field(self, s);
-            }
-            _ => {}
-        }
-    }
-
-
-    // we don't need to introspect into these at all: an
-    // expression/block context can't possibly contain exported
-    // things, and neither do view_items. (Making them no-ops stops us
-    // from traversing the whole AST without having to be super
-    // careful about our `walk_...` calls above.)
-    fn visit_view_item(&mut self, _: &ast::ViewItem) {}
-    fn visit_block(&mut self, _: &ast::Block) {}
-    fn visit_expr(&mut self, _: &ast::Expr) {}
-}
-
-pub fn check_crate(tcx: &ty::ctxt,
-                   export_map: &def::ExportMap,
-                   external_exports: ExternalExports,
-                   last_private_map: LastPrivateMap)
-                   -> (ExportedItems, PublicItems) {
-    let krate = tcx.map.krate();
-
-    // Figure out who everyone's parent is
-    let mut visitor = ParentVisitor {
-        parents: NodeMap::new(),
-        curparent: ast::DUMMY_NODE_ID,
-    };
-    visit::walk_crate(&mut visitor, krate);
-
-    // Use the parent map to check the privacy of everything
-    let mut visitor = PrivacyVisitor {
-        curitem: ast::DUMMY_NODE_ID,
-        in_foreign: false,
-        tcx: tcx,
-        parents: visitor.parents,
-        external_exports: external_exports,
-        last_private_map: last_private_map,
-    };
-    visit::walk_crate(&mut visitor, krate);
-
-    // Sanity check to make sure that all privacy usage and controls are
-    // reasonable.
-    let mut visitor = SanePrivacyVisitor {
-        in_fn: false,
-        tcx: tcx,
-    };
-    visit::walk_crate(&mut visitor, krate);
-
-    tcx.sess.abort_if_errors();
-
-    // Build up a set of all exported items in the AST. This is a set of all
-    // items which are reachable from external crates based on visibility.
-    let mut visitor = EmbargoVisitor {
-        tcx: tcx,
-        exported_items: NodeSet::new(),
-        public_items: NodeSet::new(),
-        reexports: NodeSet::new(),
-        export_map: export_map,
-        prev_exported: true,
-        prev_public: true,
-    };
-    loop {
-        let before = visitor.exported_items.len();
-        visit::walk_crate(&mut visitor, krate);
-        if before == visitor.exported_items.len() {
-            break
-        }
-    }
-
-    let EmbargoVisitor { exported_items, public_items, .. } = visitor;
-
-    {
-        let mut visitor = VisiblePrivateTypesVisitor {
-            tcx: tcx,
-            exported_items: &exported_items,
-            public_items: &public_items,
-            in_variant: false,
-        };
-        visit::walk_crate(&mut visitor, krate);
-    }
-    return (exported_items, public_items);
-}
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 906607ddc5b..b7e6da8c5f6 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -104,7 +104,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &ast::Expr) {
 
         match expr.node {
-            ast::ExprPath(_) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 let def = match self.tcx.def_map.borrow().get(&expr.id) {
                     Some(&def) => def,
                     None => {
diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs
index a6a6703353c..017641bd3b7 100644
--- a/src/librustc/middle/recursion_limit.rs
+++ b/src/librustc/middle/recursion_limit.rs
@@ -12,7 +12,7 @@
 //
 // There are various parts of the compiler that must impose arbitrary limits
 // on how deeply they recurse to prevent stack overflow. Users can override
-// this via an attribute on the crate like `#![recursion_limit(22)]`. This pass
+// this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
 // just peeks and looks for that attribute.
 
 use session::Session;
@@ -34,6 +34,6 @@ pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
         }
 
         sess.span_err(attr.span, "malformed recursion limit attribute, \
-                                  expected #![recursion_limit(\"N\")]");
+                                  expected #![recursion_limit=\"N\"]");
     }
 }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 5d33a7efd3b..8dcbc74f0eb 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -22,6 +22,8 @@ use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
 use util::common::can_reach;
 
 use std::cell::RefCell;
+// NOTE(stage0) remove import after a snapshot
+#[cfg(stage0)]
 use std::hash::{Hash};
 use syntax::codemap::Span;
 use syntax::{ast, visit};
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 9ac6b8a86b6..9ad2dd499cc 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -19,7 +19,7 @@ use util::ppaux::Repr;
 
 use std::fmt;
 use std::slice::Iter;
-use std::vec::Vec;
+use std::vec::{Vec, IntoIter};
 use syntax::codemap::{Span, DUMMY_SP};
 
 ///////////////////////////////////////////////////////////////////////////
@@ -397,6 +397,10 @@ impl<T> VecPerParamSpace<T> {
         self.content.iter()
     }
 
+    pub fn into_iter(self) -> IntoIter<T> {
+        self.content.into_iter()
+    }
+
     pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> {
         EnumeratedItems::new(self)
     }
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index 02c913a9e81..6d0e60ec495 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -18,9 +18,12 @@ use super::{
     SelectionError,
 };
 
+use fmt_macros::{Parser, Piece, Position};
 use middle::infer::InferCtxt;
-use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef};
-use syntax::codemap::Span;
+use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef, TraitRef};
+use std::collections::HashMap;
+use syntax::codemap::{DUMMY_SP, Span};
+use syntax::attr::{AttributeMethods, AttrMetaMethods};
 use util::ppaux::{Repr, UserString};
 
 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
@@ -62,6 +65,83 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
+fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+                                     trait_ref: &TraitRef<'tcx>,
+                                     span: Span) -> Option<String> {
+    let def_id = trait_ref.def_id;
+    let mut report = None;
+    for item in ty::get_attrs(infcx.tcx, def_id).iter() {
+        if item.check_name("rustc_on_unimplemented") {
+            let err_sp = if item.meta().span == DUMMY_SP {
+                span
+            } else {
+                item.meta().span
+            };
+            let def = ty::lookup_trait_def(infcx.tcx, def_id);
+            let trait_str = def.trait_ref.user_string(infcx.tcx);
+            if let Some(ref istring) = item.value_str() {
+                let mut generic_map = def.generics.types.iter_enumerated()
+                                         .map(|(param, i, gen)| {
+                                               (gen.name.as_str().to_string(),
+                                                trait_ref.substs.types.get(param, i)
+                                                         .user_string(infcx.tcx))
+                                              }).collect::<HashMap<String, String>>();
+                generic_map.insert("Self".to_string(),
+                                   trait_ref.self_ty().user_string(infcx.tcx));
+                let parser = Parser::new(istring.get());
+                let mut errored = false;
+                let err: String = parser.filter_map(|p| {
+                    match p {
+                        Piece::String(s) => Some(s),
+                        Piece::NextArgument(a) => match a.position {
+                            Position::ArgumentNamed(s) => match generic_map.get(s) {
+                                Some(val) => Some(val.as_slice()),
+                                None => {
+                                    infcx.tcx.sess
+                                         .span_err(err_sp,
+                                                   format!("the #[rustc_on_unimplemented] \
+                                                            attribute on \
+                                                            trait definition for {} refers to \
+                                                            non-existent type parameter {}",
+                                                           trait_str, s)
+                                                   .as_slice());
+                                    errored = true;
+                                    None
+                                }
+                            },
+                            _ => {
+                                infcx.tcx.sess
+                                     .span_err(err_sp,
+                                               format!("the #[rustc_on_unimplemented] \
+                                                        attribute on \
+                                                        trait definition for {} must have named \
+                                                        format arguments, \
+                                                        eg `#[rustc_on_unimplemented = \
+                                                        \"foo {{T}}\"]`",
+                                                       trait_str).as_slice());
+                                errored = true;
+                                None
+                            }
+                        }
+                    }
+                }).collect();
+                // Report only if the format string checks out
+                if !errored {
+                    report = Some(err);
+                }
+            } else {
+                infcx.tcx.sess.span_err(err_sp,
+                                        format!("the #[rustc_on_unimplemented] attribute on \
+                                                 trait definition for {} must have a value, \
+                                                 eg `#[rustc_on_unimplemented = \"foo\"]`",
+                                                 trait_str).as_slice());
+            }
+            break;
+        }
+    }
+    report
+}
+
 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                         obligation: &PredicateObligation<'tcx>,
                                         error: &SelectionError<'tcx>)
@@ -81,58 +161,80 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 
             note_obligation_cause(infcx, obligation);
         }
-        SelectionError::Unimplemented => {
-            match obligation.predicate {
-                ty::Predicate::Trait(ref trait_predicate) => {
-                    let trait_predicate =
-                        infcx.resolve_type_vars_if_possible(trait_predicate);
-                    if !trait_predicate.references_error() {
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        infcx.tcx.sess.span_err(
-                            obligation.cause.span,
-                            format!(
-                                "the trait `{}` is not implemented for the type `{}`",
-                                trait_ref.user_string(infcx.tcx),
-                                trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
-                    }
-                }
 
-                ty::Predicate::Equate(ref predicate) => {
-                    let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                    let err = infcx.equality_predicate(obligation.cause.span,
-                                                             &predicate).unwrap_err();
+        SelectionError::Unimplemented => {
+            match &obligation.cause.code {
+                &ObligationCauseCode::CompareImplMethodObligation => {
                     infcx.tcx.sess.span_err(
                         obligation.cause.span,
                         format!(
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate.user_string(infcx.tcx),
-                            ty::type_err_to_str(infcx.tcx, &err)).as_slice());
+                            "the requirement `{}` appears on the impl \
+                            method but not on the corresponding trait method",
+                            obligation.predicate.user_string(infcx.tcx)).as_slice());
                 }
+                _ => {
+                    match obligation.predicate {
+                        ty::Predicate::Trait(ref trait_predicate) => {
+                            let trait_predicate =
+                                infcx.resolve_type_vars_if_possible(trait_predicate);
 
-                ty::Predicate::RegionOutlives(ref predicate) => {
-                    let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                    let err = infcx.region_outlives_predicate(obligation.cause.span,
-                                                              &predicate).unwrap_err();
-                    infcx.tcx.sess.span_err(
-                        obligation.cause.span,
-                        format!(
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate.user_string(infcx.tcx),
-                            ty::type_err_to_str(infcx.tcx, &err)).as_slice());
-                }
+                            if !trait_predicate.references_error() {
+                                let trait_ref = trait_predicate.to_poly_trait_ref();
+                                infcx.tcx.sess.span_err(
+                                    obligation.cause.span,
+                                    format!(
+                                        "the trait `{}` is not implemented for the type `{}`",
+                                        trait_ref.user_string(infcx.tcx),
+                                        trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
+                                // Check if it has a custom "#[rustc_on_unimplemented]"
+                                // error message, report with that message if it does
+                                let custom_note = report_on_unimplemented(infcx, &*trait_ref.0,
+                                                                          obligation.cause.span);
+                                if let Some(s) = custom_note {
+                                    infcx.tcx.sess.span_note(obligation.cause.span,
+                                                             s.as_slice());
+                                }
+                            }
+                        }
 
-                ty::Predicate::Projection(..) |
-                ty::Predicate::TypeOutlives(..) => {
-                    let predicate =
-                        infcx.resolve_type_vars_if_possible(&obligation.predicate);
-                    infcx.tcx.sess.span_err(
-                        obligation.cause.span,
-                        format!(
-                            "the requirement `{}` is not satisfied",
-                            predicate.user_string(infcx.tcx)).as_slice());
+                        ty::Predicate::Equate(ref predicate) => {
+                            let predicate = infcx.resolve_type_vars_if_possible(predicate);
+                            let err = infcx.equality_predicate(obligation.cause.span,
+                                                               &predicate).unwrap_err();
+                            infcx.tcx.sess.span_err(
+                                obligation.cause.span,
+                                format!(
+                                    "the requirement `{}` is not satisfied (`{}`)",
+                                    predicate.user_string(infcx.tcx),
+                                    ty::type_err_to_str(infcx.tcx, &err)).as_slice());
+                        }
+
+                        ty::Predicate::RegionOutlives(ref predicate) => {
+                            let predicate = infcx.resolve_type_vars_if_possible(predicate);
+                            let err = infcx.region_outlives_predicate(obligation.cause.span,
+                                                                      &predicate).unwrap_err();
+                            infcx.tcx.sess.span_err(
+                                obligation.cause.span,
+                                format!(
+                                    "the requirement `{}` is not satisfied (`{}`)",
+                                    predicate.user_string(infcx.tcx),
+                                    ty::type_err_to_str(infcx.tcx, &err)).as_slice());
+                        }
+
+                        ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                                let predicate =
+                                    infcx.resolve_type_vars_if_possible(&obligation.predicate);
+                                infcx.tcx.sess.span_err(
+                                    obligation.cause.span,
+                                    format!(
+                                        "the requirement `{}` is not satisfied",
+                                        predicate.user_string(infcx.tcx)).as_slice());
+                        }
+                    }
                 }
             }
         }
+
         OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
             let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
             let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
@@ -141,12 +243,12 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                     obligation.cause.span,
                     format!(
                         "type mismatch: the type `{}` implements the trait `{}`, \
-                         but the trait `{}` is required ({})",
+                        but the trait `{}` is required ({})",
                         expected_trait_ref.self_ty().user_string(infcx.tcx),
                         expected_trait_ref.user_string(infcx.tcx),
                         actual_trait_ref.user_string(infcx.tcx),
                         ty::type_err_to_str(infcx.tcx, e)).as_slice());
-                note_obligation_cause(infcx, obligation);
+                    note_obligation_cause(infcx, obligation);
             }
         }
     }
@@ -242,7 +344,7 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 }
 
 fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                        _predicate: &ty::Predicate<'tcx>,
+                                        predicate: &ty::Predicate<'tcx>,
                                         cause_span: Span,
                                         cause_code: &ObligationCauseCode<'tcx>)
 {
@@ -329,6 +431,12 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             let parent_predicate = parent_trait_ref.as_predicate();
             note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
         }
+        ObligationCauseCode::CompareImplMethodObligation => {
+            span_note!(tcx.sess, cause_span,
+                      "the requirement `{}` appears on the impl method\
+                      but not on the corresponding trait method",
+                      predicate.user_string(infcx.tcx));
+        }
     }
 }
 
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index 3ef6694ce31..425765edf87 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -121,9 +121,12 @@ pub enum ObligationCauseCode<'tcx> {
     // static items must have `Sync` type
     SharedStatic,
 
+
     BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
 
     ImplDerivedObligation(DerivedObligationCause<'tcx>),
+
+    CompareImplMethodObligation,
 }
 
 #[derive(Clone)]
@@ -218,8 +221,10 @@ pub enum Vtable<'tcx, N> {
     VtableImpl(VtableImplData<'tcx, N>),
 
     /// Successful resolution to an obligation provided by the caller
-    /// for some type parameter.
-    VtableParam,
+    /// for some type parameter. The `Vec<N>` represents the
+    /// obligations incurred from normalizing the where-clause (if
+    /// any).
+    VtableParam(Vec<N>),
 
     /// Virtual calls through an object
     VtableObject(VtableObjectData<'tcx>),
@@ -443,7 +448,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableImpl(ref i) => i.iter_nested(),
             VtableFnPointer(..) => (&[]).iter(),
             VtableUnboxedClosure(..) => (&[]).iter(),
-            VtableParam => (&[]).iter(),
+            VtableParam(ref n) => n.iter(),
             VtableObject(_) => (&[]).iter(),
             VtableBuiltin(ref i) => i.iter_nested(),
         }
@@ -454,7 +459,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
             VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
             VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
-            VtableParam => VtableParam,
+            VtableParam(ref n) => VtableParam(n.iter().map(op).collect()),
             VtableObject(ref p) => VtableObject(p.clone()),
             VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
         }
@@ -467,7 +472,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
             VtableFnPointer(sig) => VtableFnPointer(sig),
             VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
-            VtableParam => VtableParam,
+            VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
             VtableObject(p) => VtableObject(p),
             VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
         }
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index d6302976b9f..62649653a69 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -611,6 +611,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return Ok(None);
         }
 
+
         // If there are *NO* candidates, that there are no impls --
         // that we know of, anyway. Note that in the case where there
         // are unbound type variables within the obligation, it might
@@ -626,6 +627,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // Just one candidate left.
         let candidate = candidates.pop().unwrap();
+
+        match candidate {
+            ImplCandidate(def_id) => {
+                match ty::trait_impl_polarity(self.tcx(), def_id) {
+                    Some(ast::ImplPolarity::Negative) => return Err(Unimplemented),
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
         Ok(Some(candidate))
     }
 
@@ -714,7 +726,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 debug!("obligation self ty is {}",
                        obligation.predicate.0.self_ty().repr(self.tcx()));
 
-                try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
 
                 try!(self.assemble_builtin_bound_candidates(ty::BoundCopy,
                                                             stack,
@@ -722,10 +734,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
             Some(bound @ ty::BoundSend) |
             Some(bound @ ty::BoundSync) => {
-                try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
 
                 // No explicit impls were declared for this type, consider the fallback rules.
-                if candidates.vec.is_empty() {
+                if candidates.vec.is_empty() && !candidates.ambiguous {
                     try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
                 }
             }
@@ -741,13 +753,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
                 try!(self.assemble_unboxed_closure_candidates(obligation, &mut candidates));
                 try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
-                try!(self.assemble_candidates_from_impls(obligation, &mut candidates.vec));
+                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
                 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
             }
         }
 
         self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
-        try!(self.assemble_candidates_from_caller_bounds(obligation, &mut candidates));
+        try!(self.assemble_candidates_from_caller_bounds(stack, &mut candidates));
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
     }
@@ -884,13 +896,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// supplied to find out whether it is listed among them.
     ///
     /// Never affects inference environment.
-    fn assemble_candidates_from_caller_bounds(&mut self,
-                                              obligation: &TraitObligation<'tcx>,
-                                              candidates: &mut SelectionCandidateSet<'tcx>)
-                                              -> Result<(),SelectionError<'tcx>>
+    fn assemble_candidates_from_caller_bounds<'o>(&mut self,
+                                                  stack: &TraitObligationStack<'o, 'tcx>,
+                                                  candidates: &mut SelectionCandidateSet<'tcx>)
+                                                  -> Result<(),SelectionError<'tcx>>
     {
         debug!("assemble_candidates_from_caller_bounds({})",
-               obligation.repr(self.tcx()));
+               stack.obligation.repr(self.tcx()));
 
         let caller_trait_refs: Vec<_> =
             self.param_env().caller_bounds.predicates.iter()
@@ -903,8 +915,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let matching_bounds =
             all_bounds.filter(
-                |bound| self.infcx.probe(
-                    |_| self.match_poly_trait_ref(obligation, bound.clone())).is_ok());
+                |bound| self.evaluate_where_clause(stack, bound.clone()).may_apply());
 
         let param_candidates =
             matching_bounds.map(|bound| ParamCandidate(bound));
@@ -914,6 +925,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         Ok(())
     }
 
+    fn evaluate_where_clause<'o>(&mut self,
+                                 stack: &TraitObligationStack<'o, 'tcx>,
+                                 where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                                 -> EvaluationResult<'tcx>
+    {
+        self.infcx().probe(move |_| {
+            match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
+                Ok(obligations) => {
+                    self.evaluate_predicates_recursively(Some(stack), obligations.iter())
+                }
+                Err(()) => {
+                    EvaluatedToErr(Unimplemented)
+                }
+            }
+        })
+    }
+
     /// Check for the artificial impl that the compiler will create for an obligation like `X :
     /// FnMut<..>` where `X` is an unboxed closure type.
     ///
@@ -997,9 +1025,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Search for impls that might apply to `obligation`.
     fn assemble_candidates_from_impls(&mut self,
                                       obligation: &TraitObligation<'tcx>,
-                                      candidate_vec: &mut Vec<SelectionCandidate<'tcx>>)
+                                      candidates: &mut SelectionCandidateSet<'tcx>)
                                       -> Result<(), SelectionError<'tcx>>
     {
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+        debug!("assemble_candidates_from_impls(self_ty={})", self_ty.repr(self.tcx()));
+
         let all_impls = self.all_impls(obligation.predicate.def_id());
         for &impl_def_id in all_impls.iter() {
             self.infcx.probe(|snapshot| {
@@ -1008,7 +1039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 match self.match_impl(impl_def_id, obligation, snapshot,
                                       &skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
                     Ok(_) => {
-                        candidate_vec.push(ImplCandidate(impl_def_id));
+                        candidates.vec.push(ImplCandidate(impl_def_id));
                     }
                     Err(()) => { }
                 }
@@ -1140,6 +1171,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                                    candidate_j: &SelectionCandidate<'tcx>)
                                                    -> bool
     {
+        if candidate_i == candidate_j {
+            return true;
+        }
+
         match (candidate_i, candidate_j) {
             (&ImplCandidate(impl_def_id), &ParamCandidate(ref bound)) => {
                 debug!("Considering whether to drop param {} in favor of impl {}",
@@ -1166,6 +1201,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         .is_ok()
                 })
             }
+            (&BuiltinCandidate(_), &ParamCandidate(_)) => {
+                // If we have a where-clause like `Option<K> : Send`,
+                // then we wind up in a situation where there is a
+                // default rule (`Option<K>:Send if K:Send) and the
+                // where-clause that both seem applicable. Just take
+                // the where-clause in that case.
+                true
+            }
             (&ProjectionCandidate, &ParamCandidate(_)) => {
                 // FIXME(#20297) -- this gives where clauses precedent
                 // over projections. Really these are just two means
@@ -1179,8 +1222,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // the where clauses are in scope.
                 true
             }
+            (&ParamCandidate(ref bound1), &ParamCandidate(ref bound2)) => {
+                self.infcx.probe(|_| {
+                    let bound1 =
+                        project::normalize_with_depth(self,
+                                                      stack.obligation.cause.clone(),
+                                                      stack.obligation.recursion_depth+1,
+                                                      bound1);
+                    let bound2 =
+                        project::normalize_with_depth(self,
+                                                      stack.obligation.cause.clone(),
+                                                      stack.obligation.recursion_depth+1,
+                                                      bound2);
+                    let origin =
+                        infer::RelateOutputImplTypes(stack.obligation.cause.span);
+                    self.infcx
+                        .sub_poly_trait_refs(false, origin, bound1.value, bound2.value)
+                        .is_ok()
+                })
+            }
             _ => {
-                *candidate_i == *candidate_j
+                false
             }
         }
     }
@@ -1548,8 +1610,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             ParamCandidate(param) => {
-                self.confirm_param_candidate(obligation, param);
-                Ok(VtableParam)
+                let obligations = self.confirm_param_candidate(obligation, param);
+                Ok(VtableParam(obligations))
             }
 
             ImplCandidate(impl_def_id) => {
@@ -1576,7 +1638,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ProjectionCandidate => {
                 self.confirm_projection_candidate(obligation);
-                Ok(VtableParam)
+                Ok(VtableParam(Vec::new()))
             }
         }
     }
@@ -1597,6 +1659,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn confirm_param_candidate(&mut self,
                                obligation: &TraitObligation<'tcx>,
                                param: ty::PolyTraitRef<'tcx>)
+                               -> Vec<PredicateObligation<'tcx>>
     {
         debug!("confirm_param_candidate({},{})",
                obligation.repr(self.tcx()),
@@ -1606,11 +1669,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // where-clause trait-ref could be unified with the obligation
         // trait-ref. Repeat that unification now without any
         // transactional boundary; it should not fail.
-        match self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                           obligation.predicate.to_poly_trait_ref(),
-                                           param.clone()) {
-            Ok(()) => { }
-            Err(_) => {
+        match self.match_where_clause_trait_ref(obligation, param.clone()) {
+            Ok(obligations) => obligations,
+            Err(()) => {
                 self.tcx().sess.bug(
                     format!("Where clause `{}` was applicable to `{}` but now is not",
                             param.repr(self.tcx()),
@@ -2037,19 +2098,43 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             })
     }
 
+    /// Normalize `where_clause_trait_ref` and try to match it against
+    /// `obligation`.  If successful, return any predicates that
+    /// result from the normalization. Normalization is necessary
+    /// because where-clauses are stored in the parameter environment
+    /// unnormalized.
+    fn match_where_clause_trait_ref(&mut self,
+                                    obligation: &TraitObligation<'tcx>,
+                                    where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                                    -> Result<Vec<PredicateObligation<'tcx>>,()>
+    {
+        let where_clause_trait_ref =
+            project::normalize_with_depth(self,
+                                          obligation.cause.clone(),
+                                          obligation.recursion_depth+1,
+                                          &where_clause_trait_ref);
+
+        let () =
+            try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref.value.clone()));
+
+        Ok(where_clause_trait_ref.obligations)
+    }
+
+    /// Returns `Ok` if `poly_trait_ref` being true implies that the
+    /// obligation is satisfied.
     fn match_poly_trait_ref(&mut self,
                             obligation: &TraitObligation<'tcx>,
-                            where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                            poly_trait_ref: ty::PolyTraitRef<'tcx>)
                             -> Result<(),()>
     {
-        debug!("match_poly_trait_ref: obligation={} where_clause_trait_ref={}",
+        debug!("match_poly_trait_ref: obligation={} poly_trait_ref={}",
                obligation.repr(self.tcx()),
-               where_clause_trait_ref.repr(self.tcx()));
+               poly_trait_ref.repr(self.tcx()));
 
         let origin = infer::RelateOutputImplTypes(obligation.cause.span);
         match self.infcx.sub_poly_trait_refs(false,
                                              origin,
-                                             where_clause_trait_ref,
+                                             poly_trait_ref,
                                              obligation.predicate.to_poly_trait_ref()) {
             Ok(()) => Ok(()),
             Err(_) => Err(()),
@@ -2144,8 +2229,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     /// Returns set of all impls for a given trait.
     fn all_impls(&self, trait_def_id: ast::DefId) -> Vec<ast::DefId> {
-        ty::populate_implementations_for_trait_if_necessary(self.tcx(),
-                                                            trait_def_id);
+        ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_def_id);
+
         match self.tcx().trait_impls.borrow().get(&trait_def_id) {
             None => Vec::new(),
             Some(impls) => impls.borrow().clone()
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index 272447027af..fe8362223e3 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -380,8 +380,9 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
                 format!("VtableObject({})",
                         d.repr(tcx)),
 
-            super::VtableParam =>
-                format!("VtableParam"),
+            super::VtableParam(ref n) =>
+                format!("VtableParam({})",
+                        n.repr(tcx)),
 
             super::VtableBuiltin(ref d) =>
                 d.repr(tcx)
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index ef86e67de16..34e4993c54d 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -68,7 +68,7 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
 use util::nodemap::{FnvHashMap};
 
 use arena::TypedArena;
-use std::borrow::BorrowFrom;
+use std::borrow::{BorrowFrom, Cow};
 use std::cell::{Cell, RefCell};
 use std::cmp::{self, Ordering};
 use std::fmt::{self, Show};
@@ -76,6 +76,7 @@ use std::hash::{Hash, Writer, SipHasher, Hasher};
 use std::mem;
 use std::ops;
 use std::rc::Rc;
+use std::vec::CowVec;
 use collections::enum_set::{EnumSet, CLike};
 use std::collections::{HashMap, HashSet};
 use syntax::abi;
@@ -946,13 +947,6 @@ impl<'tcx> PartialEq for TyS<'tcx> {
 }
 impl<'tcx> Eq for TyS<'tcx> {}
 
-#[cfg(stage0)]
-impl<'tcx, S: Writer> Hash<S> for TyS<'tcx> {
-    fn hash(&self, s: &mut S) {
-        (self as *const _).hash(s)
-    }
-}
-#[cfg(not(stage0))]
 impl<'tcx, S: Writer + Hasher> Hash<S> for TyS<'tcx> {
     fn hash(&self, s: &mut S) {
         (self as *const _).hash(s)
@@ -2604,12 +2598,17 @@ impl FlagComputation {
 
             &ty_projection(ref data) => {
                 self.add_flags(HAS_PROJECTION);
-                self.add_substs(data.trait_ref.substs);
+                self.add_projection_ty(data);
             }
 
             &ty_trait(box TyTrait { ref principal, ref bounds }) => {
                 let mut computation = FlagComputation::new();
                 computation.add_substs(principal.0.substs);
+                for projection_bound in bounds.projection_bounds.iter() {
+                    let mut proj_computation = FlagComputation::new();
+                    proj_computation.add_projection_predicate(&projection_bound.0);
+                    computation.add_bound_computation(&proj_computation);
+                }
                 self.add_bound_computation(&computation);
 
                 self.add_bounds(bounds);
@@ -2673,6 +2672,15 @@ impl FlagComputation {
         }
     }
 
+    fn add_projection_predicate(&mut self, projection_predicate: &ProjectionPredicate) {
+        self.add_projection_ty(&projection_predicate.projection_ty);
+        self.add_ty(projection_predicate.ty);
+    }
+
+    fn add_projection_ty(&mut self, projection_ty: &ProjectionTy) {
+        self.add_substs(projection_ty.trait_ref.substs);
+    }
+
     fn add_substs(&mut self, substs: &Substs) {
         self.add_tys(substs.types.as_slice());
         match substs.regions {
@@ -4132,12 +4140,8 @@ pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
     }
 }
 
-pub fn try_node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Option<Ty<'tcx>> {
-    cx.node_types.borrow().get(&id).cloned()
-}
-
 pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
-    match try_node_id_to_type(cx, id) {
+    match node_id_to_type_opt(cx, id) {
        Some(ty) => ty,
        None => cx.sess.bug(
            &format!("node_id_to_type: no type for node `{}`",
@@ -4514,7 +4518,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
     }
 
     match expr.node {
-        ast::ExprPath(..) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             match resolve_expr(tcx, expr) {
                 def::DefVariant(tid, vid, _) => {
                     let variant_info = enum_variant_with_id(tcx, tid, vid);
@@ -4702,7 +4706,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
         }
         ty_tup(ref tys) if tys.is_empty() => ::util::ppaux::ty_to_string(cx, ty),
 
-        ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
+        ty_enum(id, _) => format!("enum `{}`", item_path_str(cx, id)),
         ty_uniq(_) => "box".to_string(),
         ty_vec(_, Some(n)) => format!("array of {} elements", n),
         ty_vec(_, None) => "slice".to_string(),
@@ -4714,7 +4718,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
             format!("trait {}", item_path_str(cx, inner.principal_def_id()))
         }
         ty_struct(id, _) => {
-            format!("struct {}", item_path_str(cx, id))
+            format!("struct `{}`", item_path_str(cx, id))
         }
         ty_unboxed_closure(..) => "closure".to_string(),
         ty_tup(_) => "tuple".to_string(),
@@ -5024,6 +5028,23 @@ pub fn trait_items<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId)
     }
 }
 
+pub fn trait_impl_polarity<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
+                            -> Option<ast::ImplPolarity> {
+     if id.krate == ast::LOCAL_CRATE {
+         match cx.map.find(id.node) {
+             Some(ast_map::NodeItem(item)) => {
+                 match item.node {
+                     ast::ItemImpl(_, polarity, _, _, _, _) => Some(polarity),
+                     _ => None
+                 }
+             }
+             _ => None
+         }
+     } else {
+         csearch::get_impl_polarity(cx, id)
+     }
+}
+
 pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                                 -> ImplOrTraitItem<'tcx> {
     lookup_locally_or_in_crate_store("impl_or_trait_items",
@@ -5555,40 +5576,20 @@ pub fn predicates<'tcx>(
     vec
 }
 
-/// Iterate over attributes of a definition.
-// (This should really be an iterator, but that would require csearch and
-// decoder to use iterators instead of higher-order functions.)
-pub fn each_attr<F>(tcx: &ctxt, did: DefId, mut f: F) -> bool where
-    F: FnMut(&ast::Attribute) -> bool,
-{
+/// Get the attributes of a definition.
+pub fn get_attrs<'tcx>(tcx: &'tcx ctxt, did: DefId)
+                       -> CowVec<'tcx, ast::Attribute> {
     if is_local(did) {
         let item = tcx.map.expect_item(did.node);
-        item.attrs.iter().all(|attr| f(attr))
+        Cow::Borrowed(&item.attrs[])
     } else {
-        info!("getting foreign attrs");
-        let mut cont = true;
-        csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| {
-            if cont {
-                cont = attrs.iter().all(|attr| f(attr));
-            }
-        });
-        info!("done");
-        cont
+        Cow::Owned(csearch::get_item_attrs(&tcx.sess.cstore, did))
     }
 }
 
 /// Determine whether an item is annotated with an attribute
 pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
-    let mut found = false;
-    each_attr(tcx, did, |item| {
-        if item.check_name(attr) {
-            found = true;
-            false
-        } else {
-            true
-        }
-    });
-    found
+    get_attrs(tcx, did).iter().any(|item| item.check_name(attr))
 }
 
 /// Determine whether an item is annotated with `#[repr(packed)]`
@@ -5605,13 +5606,9 @@ pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
 pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
     memoized(&tcx.repr_hint_cache, did, |did: DefId| {
         Rc::new(if did.krate == LOCAL_CRATE {
-            let mut acc = Vec::new();
-            ty::each_attr(tcx, did, |meta| {
-                acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(),
-                                                 meta).into_iter());
-                true
-            });
-            acc
+            get_attrs(tcx, did).iter().flat_map(|meta| {
+                attr::find_repr_attrs(tcx.sess.diagnostic(), meta).into_iter()
+            }).collect()
         } else {
             csearch::get_repr_attrs(&tcx.sess.cstore, did)
         })
@@ -5997,6 +5994,7 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
 pub fn record_trait_implementation(tcx: &ctxt,
                                    trait_def_id: DefId,
                                    impl_def_id: DefId) {
+
     match tcx.trait_impls.borrow().get(&trait_def_id) {
         Some(impls_for_trait) => {
             impls_for_trait.borrow_mut().push(impl_def_id);
@@ -6004,6 +6002,7 @@ pub fn record_trait_implementation(tcx: &ctxt,
         }
         None => {}
     }
+
     tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
 }
 
@@ -7364,3 +7363,15 @@ impl<'tcx> Repr<'tcx> for field<'tcx> {
                 self.mt.repr(tcx))
     }
 }
+
+impl<'a, 'tcx> Repr<'tcx> for ParameterEnvironment<'a, 'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("ParameterEnvironment(\
+            free_substs={}, \
+            implicit_region_bound={}, \
+            caller_bounds={})",
+            self.free_substs.repr(tcx),
+            self.implicit_region_bound.repr(tcx),
+            self.caller_bounds.repr(tcx))
+        }
+    }
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index b81a4ed2f58..37886b4a1e1 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -514,7 +514,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
             traits::VtableFnPointer(ref d) => {
                 traits::VtableFnPointer(d.fold_with(folder))
             }
-            traits::VtableParam => traits::VtableParam,
+            traits::VtableParam(ref n) => traits::VtableParam(n.fold_with(folder)),
             traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
             traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
         }
@@ -564,6 +564,18 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
     }
 }
 
+impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParameterEnvironment<'a, 'tcx> {
+        ty::ParameterEnvironment {
+            tcx: self.tcx,
+            free_substs: self.free_substs.fold_with(folder),
+            implicit_region_bound: self.implicit_region_bound.fold_with(folder),
+            caller_bounds: self.caller_bounds.fold_with(folder),
+            selection_cache: traits::SelectionCache::new(),
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // "super" routines: these are the default implementations for TypeFolder.
 //
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs
index feec97f02da..f6fb1c2d419 100644
--- a/src/librustc/plugin/registry.rs
+++ b/src/librustc/plugin/registry.rs
@@ -14,7 +14,7 @@ use lint::{LintPassObject, LintId, Lint};
 use session::Session;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
-use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
+use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
 use syntax::ext::base::{MacroExpanderFn};
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -82,7 +82,7 @@ impl<'a> Registry<'a> {
             IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
             Decorator(ext) => Decorator(ext),
             Modifier(ext) => Modifier(ext),
-
+            MultiModifier(ext) => MultiModifier(ext),
             MacroRulesTT => {
                 self.sess.err("plugin tried to register a new MacroRulesTT");
                 return;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 26d5a9daf89..8a7c7b38287 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -15,6 +15,8 @@ use metadata::filesearch;
 use session::search_paths::PathKind;
 use util::nodemap::NodeMap;
 
+use regex::Regex;
+
 use syntax::ast::NodeId;
 use syntax::codemap::Span;
 use syntax::diagnostic::{self, Emitter};
@@ -71,7 +73,58 @@ impl Session {
         self.diagnostic().handler().fatal(msg)
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
-        self.diagnostic().span_err(sp, msg)
+        // Conditions for enabling multi-line errors:
+        if !msg.contains("mismatched types") &&
+           !msg.contains("type mismatch resolving") &&
+           !msg.contains("if and else have incompatible types") &&
+           !msg.contains("if may be missing an else clause") &&
+           !msg.contains("match arms have incompatible types") &&
+           !msg.contains("structure constructor specifies a structure of type") {
+            return self.diagnostic().span_err(sp, msg);
+        }
+
+        let first  = Regex::new(r"[( ]expected").unwrap();
+        let second = Regex::new(r" found").unwrap();
+        let third  = Regex::new(
+                     r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
+
+        let mut new_msg = String::new();
+        let mut head = 0u;
+
+        // Insert `\n` before expected and found.
+        for (pos1, pos2) in first.find_iter(msg).zip(
+                            second.find_iter(msg)) {
+            new_msg = new_msg +
+            // A `(` may be preceded by a space and it should be trimmed
+                      msg[head..pos1.0].trim_right() + // prefix
+                      "\n" +                           // insert before first
+                      &msg[pos1.0..pos1.1] +           // insert what first matched
+                      &msg[pos1.1..pos2.0] +           // between matches
+                      "\n   " +                        // insert before second
+            //           123
+            // `expected` is 3 char longer than `found`. To align the types, `found` gets
+            // 3 spaces prepended.
+                      &msg[pos2.0..pos2.1];            // insert what second matched
+
+            head = pos2.1;
+        }
+
+        let mut tail = &msg[head..];
+        // Insert `\n` before any remaining messages which match.
+        for pos in third.find_iter(tail).take(1) {
+            // The end of the message may just be wrapped in `()` without `expected`/`found`.
+            // Push this also to a new line and add the final tail after.
+            new_msg = new_msg +
+            // `(` is usually preceded by a space and should be trimmed.
+                      tail[..pos.0].trim_right() + // prefix
+                      "\n" +                       // insert before paren
+                      &tail[pos.0..];              // append the tail
+
+            tail = "";
+        }
+
+        new_msg.push_str(tail);
+        self.diagnostic().span_err(sp, &new_msg[])
     }
     pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
         self.diagnostic().span_err_with_code(sp, msg, code)
@@ -121,6 +174,9 @@ impl Session {
     pub fn fileline_note(&self, sp: Span, msg: &str) {
         self.diagnostic().fileline_note(sp, msg)
     }
+    pub fn fileline_help(&self, sp: Span, msg: &str) {
+        self.diagnostic().fileline_help(sp, msg)
+    }
     pub fn note(&self, msg: &str) {
         self.diagnostic().handler().note(msg)
     }
diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs
index 9bff5435217..0cf04fe0a00 100644
--- a/src/librustc/session/search_paths.rs
+++ b/src/librustc/session/search_paths.rs
@@ -10,7 +10,7 @@
 
 use std::slice;
 
-#[derive(Clone)]
+#[derive(Clone, Show)]
 pub struct SearchPaths {
     paths: Vec<(PathKind, Path)>,
 }
@@ -20,11 +20,12 @@ pub struct Iter<'a> {
     iter: slice::Iter<'a, (PathKind, Path)>,
 }
 
-#[derive(Eq, PartialEq, Clone, Copy)]
+#[derive(Eq, PartialEq, Clone, Copy, Show)]
 pub enum PathKind {
     Native,
     Crate,
     Dependency,
+    ExternFlag,
     All,
 }
 
@@ -54,14 +55,16 @@ impl SearchPaths {
 }
 
 impl<'a> Iterator for Iter<'a> {
-    type Item = &'a Path;
+    type Item = (&'a Path, PathKind);
 
-    fn next(&mut self) -> Option<&'a Path> {
+    fn next(&mut self) -> Option<(&'a Path, PathKind)> {
         loop {
             match self.iter.next() {
                 Some(&(kind, ref p)) if self.kind == PathKind::All ||
                                         kind == PathKind::All ||
-                                        kind == self.kind => return Some(p),
+                                        kind == self.kind => {
+                    return Some((p, kind))
+                }
                 Some(..) => {}
                 None => return None,
             }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 559ec533baa..fb44d0cadfa 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -542,7 +542,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
         0
     };
 
-    for t in tps[0..(tps.len() - num_defaults)].iter() {
+    for t in tps[..(tps.len() - num_defaults)].iter() {
         strs.push(ty_to_string(cx, *t))
     }
 
@@ -1430,7 +1430,7 @@ impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
 impl<'tcx> Repr<'tcx> for ty::ProjectionTy<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         format!("<{} as {}>::{}",
-                self.trait_ref.self_ty().repr(tcx),
+                self.trait_ref.substs.self_ty().repr(tcx),
                 self.trait_ref.repr(tcx),
                 self.item_name.repr(tcx))
     }
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
index d29a47b65b0..d778b916b67 100644
--- a/src/librustc_back/lib.rs
+++ b/src/librustc_back/lib.rs
@@ -32,6 +32,7 @@
 #![allow(unknown_features)]
 #![feature(slicing_syntax, box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate syntax;
 extern crate serialize;
diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs
index ac5662f534c..e376ac50dcd 100644
--- a/src/librustc_back/sha2.rs
+++ b/src/librustc_back/sha2.rs
@@ -140,7 +140,7 @@ impl FixedBuffer for FixedBuffer64 {
             if input.len() >= buffer_remaining {
                     copy_memory(
                         self.buffer.slice_mut(self.buffer_idx, size),
-                        &input[0..buffer_remaining]);
+                        &input[..buffer_remaining]);
                 self.buffer_idx = 0;
                 func(&self.buffer);
                 i += buffer_remaining;
@@ -188,7 +188,7 @@ impl FixedBuffer for FixedBuffer64 {
     fn full_buffer<'s>(&'s mut self) -> &'s [u8] {
         assert!(self.buffer_idx == 64);
         self.buffer_idx = 0;
-        return &self.buffer[0..64];
+        return &self.buffer[..64];
     }
 
     fn position(&self) -> uint { self.buffer_idx }
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index 4e260da2e4d..789a87bbcda 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -252,6 +252,7 @@ mod svh_visitor {
         SawExprIndex,
         SawExprRange,
         SawExprPath,
+        SawExprQPath,
         SawExprAddrOf(ast::Mutability),
         SawExprRet,
         SawExprInlineAsm(&'a ast::InlineAsm),
@@ -285,6 +286,7 @@ mod svh_visitor {
             ExprIndex(..)            => SawExprIndex,
             ExprRange(..)            => SawExprRange,
             ExprPath(..)             => SawExprPath,
+            ExprQPath(..)            => SawExprQPath,
             ExprAddrOf(m, _)         => SawExprAddrOf(m),
             ExprBreak(id)            => SawExprBreak(id.map(content)),
             ExprAgain(id)            => SawExprAgain(id.map(content)),
diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs
index f9dcb4fb812..ac133cabc3b 100644
--- a/src/librustc_back/target/apple_ios_base.rs
+++ b/src/librustc_back/target/apple_ios_base.rs
@@ -14,6 +14,7 @@ use target::TargetOptions;
 use self::Arch::*;
 
 #[allow(non_camel_case_types)]
+#[derive(Copy)]
 pub enum Arch {
     Armv7,
     Armv7s,
@@ -70,8 +71,16 @@ fn pre_link_args(arch: Arch) -> Vec<String> {
          "-Wl,-syslibroot".to_string(), get_sdk_root(sdk_name)]
 }
 
+fn target_cpu(arch: Arch) -> String {
+    match arch {
+        X86_64 => "x86-64",
+        _ => "generic",
+    }.to_string()
+}
+
 pub fn opts(arch: Arch) -> TargetOptions {
     TargetOptions {
+        cpu: target_cpu(arch),
         dynamic_linking: false,
         executables: true,
         // Although there is an experimental implementation of LLVM which
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 57e2744ae9b..f8eabb4375f 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -72,6 +72,7 @@ mod i686_unknown_dragonfly;
 mod i686_unknown_linux_gnu;
 mod mips_unknown_linux_gnu;
 mod mipsel_unknown_linux_gnu;
+mod powerpc_unknown_linux_gnu;
 mod x86_64_apple_darwin;
 mod x86_64_apple_ios;
 mod x86_64_pc_windows_gnu;
@@ -95,7 +96,7 @@ pub struct Target {
     /// OS name to use for conditional compilation.
     pub target_os: String,
     /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
-    /// "aarch64", and "mips". "mips" includes "mipsel".
+    /// "aarch64", "mips", and "powerpc". "mips" includes "mipsel".
     pub arch: String,
     /// Optional settings with defaults.
     pub options: TargetOptions,
@@ -339,6 +340,7 @@ impl Target {
             i686_unknown_linux_gnu,
             mips_unknown_linux_gnu,
             mipsel_unknown_linux_gnu,
+            powerpc_unknown_linux_gnu,
             arm_linux_androideabi,
             arm_unknown_linux_gnueabi,
             arm_unknown_linux_gnueabihf,
diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..5e0b7bcf3ef
--- /dev/null
+++ b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
@@ -0,0 +1,26 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::linux_base::opts();
+    base.pre_link_args.push("-m32".to_string());
+
+    Target {
+        data_layout: "E-S8-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
+        llvm_target: "powerpc-unknown-linux-gnu".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "32".to_string(),
+        arch: "powerpc".to_string(),
+        target_os: "linux".to_string(),
+        options: base,
+    }
+}
diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs
index 0ebd3bd3215..f2abfd4564c 100644
--- a/src/librustc_back/target/x86_64_apple_darwin.rs
+++ b/src/librustc_back/target/x86_64_apple_darwin.rs
@@ -12,6 +12,7 @@ use target::Target;
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts();
+    base.cpu = "x86-64".to_string();
     base.eliminate_frame_pointer = false;
     base.pre_link_args.push("-m64".to_string());
 
diff --git a/src/librustc_back/target/x86_64_pc_windows_gnu.rs b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
index 9e1294a8962..6b3054656fe 100644
--- a/src/librustc_back/target/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
@@ -12,6 +12,7 @@ use target::Target;
 
 pub fn target() -> Target {
     let mut base = super::windows_base::opts();
+    base.cpu = "x86-64".to_string();
     // On Win64 unwinding is handled by the OS, so we can link libgcc statically.
     base.pre_link_args.push("-static-libgcc".to_string());
     base.pre_link_args.push("-m64".to_string());
diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
index 6635306b0e1..676aaecc2fc 100644
--- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
@@ -12,6 +12,7 @@ use target::Target;
 
 pub fn target() -> Target {
     let mut base = super::dragonfly_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs
index 2aba2b8defb..3275cb07b5a 100644
--- a/src/librustc_back/target/x86_64_unknown_freebsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs
@@ -12,6 +12,7 @@ use target::Target;
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
index d7a6df3a8b0..49c4ad4aea9 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
@@ -12,6 +12,7 @@ use target::Target;
 
 pub fn target() -> Target {
     let mut base = super::linux_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
diff --git a/src/libstd/bitflags.rs b/src/librustc_bitflags/lib.rs
index 3a059766fef..c47a525552d 100644
--- a/src/libstd/bitflags.rs
+++ b/src/librustc_bitflags/lib.rs
@@ -8,10 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![crate_name = "rustc_bitflags"]
 #![unstable]
+#![staged_api]
+#![crate_type = "rlib"]
+#![no_std]
 
 //! A typesafe bitmask flag generator.
 
+#[cfg(test)] #[macro_use] extern crate std;
+
 /// The `bitflags!` macro generates a `struct` that holds a set of C-style
 /// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
 ///
@@ -21,6 +27,8 @@
 /// # Example
 ///
 /// ```{.rust}
+/// #[macro_use] extern crate rustc_bitflags;
+///
 /// bitflags! {
 ///     flags Flags: u32 {
 ///         const FLAG_A       = 0b00000001,
@@ -45,6 +53,8 @@
 /// The generated `struct`s can also be extended with type and trait implementations:
 ///
 /// ```{.rust}
+/// #[macro_use] extern crate rustc_bitflags;
+///
 /// use std::fmt;
 ///
 /// bitflags! {
@@ -273,8 +283,8 @@ macro_rules! bitflags {
 #[cfg(test)]
 #[allow(non_upper_case_globals)]
 mod tests {
-    use hash::{self, SipHasher};
-    use option::Option::{Some, None};
+    use std::hash::{self, SipHasher};
+    use std::option::Option::{Some, None};
 
     bitflags! {
         #[doc = "> The first principle is that you must not fool yourself — and"]
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index eedad75c89f..4dd9b3ad2ef 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -23,6 +23,7 @@
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![allow(non_camel_case_types)]
+#![allow(unstable)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index c2af4315b06..3fac5ba9674 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -24,9 +24,9 @@ use rustc_borrowck as borrowck;
 use rustc_resolve as resolve;
 use rustc_trans::back::link;
 use rustc_trans::back::write;
-use rustc_trans::save;
 use rustc_trans::trans;
 use rustc_typeck as typeck;
+use rustc_privacy;
 
 use serialize::json;
 
@@ -47,23 +47,43 @@ pub fn compile_input(sess: Session,
                      input: &Input,
                      outdir: &Option<Path>,
                      output: &Option<Path>,
-                     addl_plugins: Option<Vec<String>>) {
+                     addl_plugins: Option<Vec<String>>,
+                     control: CompileController) {
+    macro_rules! controller_entry_point{($point: ident, $make_state: expr) => ({
+        {
+            let state = $make_state;
+            (control.$point.callback)(state);
+        }
+        if control.$point.stop {
+            return;
+        }
+    })}
+
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
     let (outputs, trans, sess) = {
         let (outputs, expanded_crate, id) = {
             let krate = phase_1_parse_input(&sess, cfg, input);
-            if stop_after_phase_1(&sess) { return; }
+
+            controller_entry_point!(after_parse,
+                                    CompileState::state_after_parse(input,
+                                                                    &sess,
+                                                                    outdir,
+                                                                    &krate));
+
             let outputs = build_output_filenames(input,
                                                  outdir,
                                                  output,
                                                  &krate.attrs[],
                                                  &sess);
-            let id = link::find_crate_name(Some(&sess), &krate.attrs[],
+            let id = link::find_crate_name(Some(&sess),
+                                           &krate.attrs[],
                                            input);
             let expanded_crate
-                = match phase_2_configure_and_expand(&sess, krate, &id[],
+                = match phase_2_configure_and_expand(&sess,
+                                                     krate,
+                                                     &id[],
                                                      addl_plugins) {
                     None => return,
                     Some(k) => k
@@ -72,23 +92,44 @@ pub fn compile_input(sess: Session,
             (outputs, expanded_crate, id)
         };
 
+        controller_entry_point!(after_expand,
+                                CompileState::state_after_expand(input,
+                                                                 &sess,
+                                                                 outdir,
+                                                                 &expanded_crate,
+                                                                 &id[]));
+
         let mut forest = ast_map::Forest::new(expanded_crate);
         let ast_map = assign_node_ids_and_map(&sess, &mut forest);
 
         write_out_deps(&sess, input, &outputs, &id[]);
 
-        if stop_after_phase_2(&sess) { return; }
+        controller_entry_point!(after_write_deps,
+                                CompileState::state_after_write_deps(input,
+                                                                     &sess,
+                                                                     outdir,
+                                                                     &ast_map,
+                                                                     &id[]));
 
         let arenas = ty::CtxtArenas::new();
-        let analysis = phase_3_run_analysis_passes(sess, ast_map, &arenas, id);
-        phase_save_analysis(&analysis.ty_cx.sess, analysis.ty_cx.map.krate(), &analysis, outdir);
+        let analysis = phase_3_run_analysis_passes(sess,
+                                                   ast_map,
+                                                   &arenas,
+                                                   id,
+                                                   control.make_glob_map);
+
+        controller_entry_point!(after_analysis,
+                                CompileState::state_after_analysis(input,
+                                                                   &analysis.ty_cx.sess,
+                                                                   outdir,
+                                                                   analysis.ty_cx.map.krate(),
+                                                                   &analysis,
+                                                                   &analysis.ty_cx));
 
         if log_enabled!(::log::INFO) {
             println!("Pre-trans");
             analysis.ty_cx.print_debug_stats();
         }
-
-        if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
         let (tcx, trans) = phase_4_translate_to_llvm(analysis);
 
         if log_enabled!(::log::INFO) {
@@ -102,7 +143,13 @@ pub fn compile_input(sess: Session,
         (outputs, trans, tcx.sess)
     };
     phase_5_run_llvm_passes(&sess, &trans, &outputs);
-    if stop_after_phase_5(&sess) { return; }
+
+    controller_entry_point!(after_llvm,
+                            CompileState::state_after_llvm(input,
+                                                           &sess,
+                                                           outdir,
+                                                           &trans));
+
     phase_6_link_output(&sess, &trans, &outputs);
 }
 
@@ -120,6 +167,161 @@ pub fn source_name(input: &Input) -> String {
     }
 }
 
+/// CompileController is used to customise compilation, it allows compilation to
+/// be stopped and/or to call arbitrary code at various points in compilation.
+/// It also allows for various flags to be set to influence what information gets
+/// colelcted during compilation.
+///
+/// This is a somewhat higher level controller than a Session - the Session
+/// controls what happens in each phase, whereas the CompileController controls
+/// whether a phase is run at all and whether other code (from outside the
+/// the compiler) is run between phases.
+///
+/// Note that if compilation is set to stop and a callback is provided for a
+/// given entry point, the callback is called before compilation is stopped.
+///
+/// Expect more entry points to be added in the future.
+pub struct CompileController<'a> {
+    pub after_parse: PhaseController<'a>,
+    pub after_expand: PhaseController<'a>,
+    pub after_write_deps: PhaseController<'a>,
+    pub after_analysis: PhaseController<'a>,
+    pub after_llvm: PhaseController<'a>,
+
+    pub make_glob_map: resolve::MakeGlobMap,
+}
+
+impl<'a> CompileController<'a> {
+    pub fn basic() -> CompileController<'a> {
+        CompileController {
+            after_parse: PhaseController::basic(),
+            after_expand: PhaseController::basic(),
+            after_write_deps:  PhaseController::basic(),
+            after_analysis: PhaseController::basic(),
+            after_llvm: PhaseController::basic(),
+            make_glob_map: resolve::MakeGlobMap::No,
+        }
+    }
+}
+
+pub struct PhaseController<'a> {
+    pub stop: bool,
+    pub callback: Box<Fn(CompileState) -> () + 'a>,
+}
+
+impl<'a> PhaseController<'a> {
+    pub fn basic() -> PhaseController<'a> {
+        PhaseController {
+            stop: false,
+            callback: box |&: _| {},
+        }
+    }
+}
+
+/// State that is passed to a callback. What state is available depends on when
+/// during compilation the callback is made. See the various constructor methods
+/// (`state_*`) in the impl to see which data is provided for any given entry point.
+pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
+    pub input: &'a Input,
+    pub session: &'a Session,
+    pub cfg: Option<&'a ast::CrateConfig>,
+    pub krate: Option<&'a ast::Crate>,
+    pub crate_name: Option<&'a str>,
+    pub output_filenames: Option<&'a OutputFilenames>,
+    pub out_dir: Option<&'a Path>,
+    pub expanded_crate: Option<&'a ast::Crate>,
+    pub ast_map: Option<&'a ast_map::Map<'ast>>,
+    pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>,
+    pub tcx: Option<&'a ty::ctxt<'tcx>>,
+    pub trans: Option<&'a trans::CrateTranslation>,
+}
+
+impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
+    fn empty(input: &'a Input,
+             session: &'a Session,
+             out_dir: &'a Option<Path>)
+             -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            input: input,
+            session: session,
+            out_dir: out_dir.as_ref(),
+            cfg: None,
+            krate: None,
+            crate_name: None,
+            output_filenames: None,
+            expanded_crate: None,
+            ast_map: None,
+            analysis: None,
+            tcx: None,
+            trans: None,
+        }
+    }
+
+    fn state_after_parse(input: &'a Input,
+                         session: &'a Session,
+                         out_dir: &'a Option<Path>,
+                         krate: &'a ast::Crate)
+                         -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            krate: Some(krate),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+
+    fn state_after_expand(input: &'a Input,
+                          session: &'a Session,
+                          out_dir: &'a Option<Path>,
+                          expanded_crate: &'a ast::Crate,
+                          crate_name: &'a str)
+                          -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            crate_name: Some(crate_name),
+            expanded_crate: Some(expanded_crate),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+
+    fn state_after_write_deps(input: &'a Input,
+                              session: &'a Session,
+                              out_dir: &'a Option<Path>,
+                              ast_map: &'a ast_map::Map<'ast>,
+                              crate_name: &'a str)
+                              -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            crate_name: Some(crate_name),
+            ast_map: Some(ast_map),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+
+    fn state_after_analysis(input: &'a Input,
+                            session: &'a Session,
+                            out_dir: &'a Option<Path>,
+                            krate: &'a ast::Crate,
+                            analysis: &'a ty::CrateAnalysis<'tcx>,
+                            tcx: &'a ty::ctxt<'tcx>)
+                            -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            analysis: Some(analysis),
+            tcx: Some(tcx),
+            krate: Some(krate),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+
+
+    fn state_after_llvm(input: &'a Input,
+                        session: &'a Session,
+                        out_dir: &'a Option<Path>,
+                        trans: &'a trans::CrateTranslation)
+                        -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            trans: Some(trans),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+}
+
 pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
     -> ast::Crate {
     // These may be left in an incoherent state after a previous compile.
@@ -347,7 +549,9 @@ pub fn assign_node_ids_and_map<'ast>(sess: &Session,
 pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                                          ast_map: ast_map::Map<'tcx>,
                                          arenas: &'tcx ty::CtxtArenas<'tcx>,
-                                         name: String) -> ty::CrateAnalysis<'tcx> {
+                                         name: String,
+                                         make_glob_map: resolve::MakeGlobMap)
+                                         -> ty::CrateAnalysis<'tcx> {
     let time_passes = sess.time_passes();
     let krate = ast_map.krate();
 
@@ -357,11 +561,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     let lang_items = time(time_passes, "language item collection", (), |_|
                           middle::lang_items::collect_language_items(krate, &sess));
 
-    let make_glob_map = if save_analysis(&sess) {
-        resolve::MakeGlobMap::Yes
-    } else {
-        resolve::MakeGlobMap::No
-    };
     let resolve::CrateMap {
         def_map,
         freevars,
@@ -432,7 +631,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     let maps = (external_exports, last_private_map);
     let (exported_items, public_items) =
             time(time_passes, "privacy checking", maps, |(a, b)|
-                 middle::privacy::check_crate(&ty_cx, &export_map, a, b));
+                 rustc_privacy::check_crate(&ty_cx, &export_map, a, b));
 
     time(time_passes, "intrinsic checking", (), |_|
          middle::intrinsicck::check_crate(&ty_cx));
@@ -483,21 +682,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     }
 }
 
-fn save_analysis(sess: &Session) -> bool {
-    sess.opts.debugging_opts.save_analysis
-}
-
-pub fn phase_save_analysis(sess: &Session,
-                           krate: &ast::Crate,
-                           analysis: &ty::CrateAnalysis,
-                           odir: &Option<Path>) {
-    if !save_analysis(sess) {
-        return;
-    }
-    time(sess.time_passes(), "save analysis", krate, |krate|
-         save::process_crate(sess, krate, analysis, odir));
-}
-
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
 pub fn phase_4_translate_to_llvm<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
@@ -559,41 +743,6 @@ pub fn phase_6_link_output(sess: &Session,
     os::setenv("PATH", old_path);
 }
 
-pub fn stop_after_phase_3(sess: &Session) -> bool {
-   if sess.opts.no_trans {
-        debug!("invoked with --no-trans, returning early from compile_input");
-        return true;
-    }
-    return false;
-}
-
-pub fn stop_after_phase_1(sess: &Session) -> bool {
-    if sess.opts.parse_only {
-        debug!("invoked with --parse-only, returning early from compile_input");
-        return true;
-    }
-    if sess.opts.show_span.is_some() {
-        return true;
-    }
-    return sess.opts.debugging_opts.ast_json_noexpand;
-}
-
-pub fn stop_after_phase_2(sess: &Session) -> bool {
-    if sess.opts.no_analysis {
-        debug!("invoked with --no-analysis, returning early from compile_input");
-        return true;
-    }
-    return sess.opts.debugging_opts.ast_json;
-}
-
-pub fn stop_after_phase_5(sess: &Session) -> bool {
-    if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
-        debug!("not building executable, returning early from compile_input");
-        return true;
-    }
-    return false;
-}
-
 fn escape_dep_filename(filename: &str) -> String {
     // Apparently clang and gcc *only* escape spaces:
     // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 9122a34a793..50ff4546c37 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -29,6 +29,7 @@
 #![feature(box_syntax)]
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate arena;
 extern crate flate;
@@ -38,6 +39,7 @@ extern crate libc;
 extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_borrowck;
+extern crate rustc_privacy;
 extern crate rustc_resolve;
 extern crate rustc_trans;
 extern crate rustc_typeck;
@@ -48,7 +50,11 @@ extern crate "rustc_llvm" as llvm;
 
 pub use syntax::diagnostic;
 
+use driver::CompileController;
+
+use rustc_resolve as resolve;
 use rustc_trans::back::link;
+use rustc_trans::save;
 use rustc::session::{config, Session, build_session};
 use rustc::session::config::{Input, PrintRequest, UnstableFeatures};
 use rustc::lint::Lint;
@@ -56,6 +62,7 @@ use rustc::lint;
 use rustc::metadata;
 use rustc::metadata::creader::CrateOrString::Str;
 use rustc::DIAGNOSTICS;
+use rustc::util::common::time;
 
 use std::cmp::Ordering::Equal;
 use std::io;
@@ -181,14 +188,50 @@ fn run_compiler(args: &[String]) {
                 list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
             }
             Input::Str(_) => {
-                early_error("can not list metadata for stdin");
+                early_error("cannot list metadata for stdin");
             }
         }
         return;
     }
 
     let plugins = sess.opts.debugging_opts.extra_plugins.clone();
-    driver::compile_input(sess, cfg, &input, &odir, &ofile, Some(plugins));
+    let control = build_controller(&sess);
+    driver::compile_input(sess, cfg, &input, &odir, &ofile, Some(plugins), control);
+}
+
+fn build_controller<'a>(sess: &Session) -> CompileController<'a> {
+    let mut control = CompileController::basic();
+
+    if sess.opts.parse_only ||
+       sess.opts.show_span.is_some() ||
+       sess.opts.debugging_opts.ast_json_noexpand {
+        control.after_parse.stop = true;
+    }
+
+    if sess.opts.no_analysis || sess.opts.debugging_opts.ast_json {
+        control.after_write_deps.stop = true;
+    }
+
+    if sess.opts.no_trans {
+        control.after_analysis.stop = true;
+    }
+
+    if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
+        control.after_llvm.stop = true;
+    }
+
+    if sess.opts.debugging_opts.save_analysis {
+        control.after_analysis.callback = box |state| {
+            time(state.session.time_passes(), "save analysis", state.krate.unwrap(), |krate|
+                 save::process_crate(state.session,
+                                     krate,
+                                     state.analysis.unwrap(),
+                                     state.out_dir));
+        };
+        control.make_glob_map = resolve::MakeGlobMap::Yes;
+    }
+
+    control
 }
 
 pub fn get_unstable_features_setting() -> UnstableFeatures {
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 1765c80f943..279442891be 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -27,6 +27,7 @@ use rustc::session::config::Input;
 use rustc::util::ppaux;
 use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
+use rustc_resolve as resolve;
 
 use syntax::ast;
 use syntax::ast_map::{self, blocks, NodePrinter};
@@ -52,10 +53,20 @@ pub enum PpSourceMode {
     PpmExpandedHygiene,
 }
 
+
+#[derive(Copy, PartialEq, Show)]
+pub enum PpFlowGraphMode {
+    Default,
+    /// Drops the labels from the edges in the flowgraph output. This
+    /// is mostly for use in the --xpretty flowgraph run-make tests,
+    /// since the labels are largely uninteresting in those cases and
+    /// have become a pain to maintain.
+    UnlabelledEdges,
+}
 #[derive(Copy, PartialEq, Show)]
 pub enum PpMode {
     PpmSource(PpSourceMode),
-    PpmFlowGraph,
+    PpmFlowGraph(PpFlowGraphMode),
 }
 
 pub fn parse_pretty(sess: &Session,
@@ -72,12 +83,13 @@ pub fn parse_pretty(sess: &Session,
         ("expanded,identified", _) => PpmSource(PpmExpandedIdentified),
         ("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene),
         ("identified", _)   => PpmSource(PpmIdentified),
-        ("flowgraph", true)    => PpmFlowGraph,
+        ("flowgraph", true)    => PpmFlowGraph(PpFlowGraphMode::Default),
+        ("flowgraph,unlabelled", true)    => PpmFlowGraph(PpFlowGraphMode::UnlabelledEdges),
         _ => {
             if extended {
                 sess.fatal(format!(
                     "argument to `xpretty` must be one of `normal`, \
-                     `expanded`, `flowgraph=<nodeid>`, `typed`, `identified`, \
+                     `expanded`, `flowgraph[,unlabelled]=<nodeid>`, `typed`, `identified`, \
                      `expanded,identified`, or `everybody_loops`; got {}", name).as_slice());
             } else {
                 sess.fatal(format!(
@@ -133,7 +145,11 @@ impl PpSourceMode {
             }
             PpmTyped => {
                 let ast_map = ast_map.expect("--pretty=typed missing ast_map");
-                let analysis = driver::phase_3_run_analysis_passes(sess, ast_map, arenas, id);
+                let analysis = driver::phase_3_run_analysis_passes(sess,
+                                                                   ast_map,
+                                                                   arenas,
+                                                                   id,
+                                                                   resolve::MakeGlobMap::No);
                 let annotation = TypedAnnotation { analysis: analysis };
                 f(&annotation, payload)
             }
@@ -412,7 +428,7 @@ fn needs_ast_map(ppm: &PpMode, opt_uii: &Option<UserIdentifiedItem>) -> bool {
         PpmSource(PpmExpandedIdentified) |
         PpmSource(PpmExpandedHygiene) |
         PpmSource(PpmTyped) |
-        PpmFlowGraph => true
+        PpmFlowGraph(_) => true
     }
 }
 
@@ -426,7 +442,7 @@ fn needs_expansion(ppm: &PpMode) -> bool {
         PpmSource(PpmExpandedIdentified) |
         PpmSource(PpmExpandedHygiene) |
         PpmSource(PpmTyped) |
-        PpmFlowGraph => true
+        PpmFlowGraph(_) => true
     }
 }
 
@@ -584,7 +600,7 @@ pub fn pretty_print_input(sess: Session,
                     pp::eof(&mut pp_state.s)
                 }),
 
-        (PpmFlowGraph, opt_uii) => {
+        (PpmFlowGraph(mode), opt_uii) => {
             debug!("pretty printing flow graph for {:?}", opt_uii);
             let uii = opt_uii.unwrap_or_else(|| {
                 sess.fatal(&format!("`pretty flowgraph=..` needs NodeId (int) or
@@ -603,8 +619,12 @@ pub fn pretty_print_input(sess: Session,
             match code {
                 Some(code) => {
                     let variants = gather_flowgraph_variants(&sess);
-                    let analysis = driver::phase_3_run_analysis_passes(sess, ast_map, &arenas, id);
-                    print_flowgraph(variants, analysis, code, out)
+                    let analysis = driver::phase_3_run_analysis_passes(sess,
+                                                                       ast_map,
+                                                                       &arenas,
+                                                                       id,
+                                                                       resolve::MakeGlobMap::No);
+                    print_flowgraph(variants, analysis, code, mode, out)
                 }
                 None => {
                     let message = format!("--pretty=flowgraph needs \
@@ -626,20 +646,23 @@ pub fn pretty_print_input(sess: Session,
 fn print_flowgraph<W:io::Writer>(variants: Vec<borrowck_dot::Variant>,
                                  analysis: ty::CrateAnalysis,
                                  code: blocks::Code,
+                                 mode: PpFlowGraphMode,
                                  mut out: W) -> io::IoResult<()> {
     let ty_cx = &analysis.ty_cx;
     let cfg = match code {
         blocks::BlockCode(block) => cfg::CFG::new(ty_cx, &*block),
         blocks::FnLikeCode(fn_like) => cfg::CFG::new(ty_cx, &*fn_like.body()),
     };
+    let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges;
+    let lcfg = LabelledCFG {
+        ast_map: &ty_cx.map,
+        cfg: &cfg,
+        name: format!("node_{}", code.id()),
+        labelled_edges: labelled_edges,
+    };
 
     match code {
         _ if variants.len() == 0 => {
-            let lcfg = LabelledCFG {
-                ast_map: &ty_cx.map,
-                cfg: &cfg,
-                name: format!("node_{}", code.id()),
-            };
             let r = dot::render(&lcfg, &mut out);
             return expand_err_details(r);
         }
@@ -653,11 +676,6 @@ fn print_flowgraph<W:io::Writer>(variants: Vec<borrowck_dot::Variant>,
             let (bccx, analysis_data) =
                 borrowck::build_borrowck_dataflow_data_for_fn(ty_cx, fn_parts);
 
-            let lcfg = LabelledCFG {
-                ast_map: &ty_cx.map,
-                cfg: &cfg,
-                name: format!("node_{}", code.id()),
-            };
             let lcfg = borrowck_dot::DataflowLabeller {
                 inner: lcfg,
                 variants: variants,
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index a4f9b1f98d4..4c9a25f42fb 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -26,8 +26,10 @@
 #![feature(link_args)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate libc;
+#[macro_use] #[no_link] extern crate rustc_bitflags;
 
 pub use self::OtherAttribute::*;
 pub use self::SpecialAttribute::*;
@@ -304,7 +306,7 @@ pub enum RealPredicate {
 
 // The LLVM TypeKind type - must stay in sync with the def of
 // LLVMTypeKind in llvm/include/llvm-c/Core.h
-#[derive(Copy, PartialEq)]
+#[derive(Copy, PartialEq, Show)]
 #[repr(C)]
 pub enum TypeKind {
     Void      = 0,
@@ -1974,6 +1976,11 @@ extern {
     pub fn LLVMInitializeMipsTargetMC();
     pub fn LLVMInitializeMipsAsmPrinter();
     pub fn LLVMInitializeMipsAsmParser();
+    pub fn LLVMInitializePowerPCTargetInfo();
+    pub fn LLVMInitializePowerPCTarget();
+    pub fn LLVMInitializePowerPCTargetMC();
+    pub fn LLVMInitializePowerPCAsmPrinter();
+    pub fn LLVMInitializePowerPCAsmParser();
 
     pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *const c_char) -> bool;
     pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
@@ -2249,6 +2256,12 @@ pub unsafe fn static_link_hack_this_sucks() {
     LLVMInitializeMipsAsmPrinter();
     LLVMInitializeMipsAsmParser();
 
+    LLVMInitializePowerPCTargetInfo();
+    LLVMInitializePowerPCTarget();
+    LLVMInitializePowerPCTargetMC();
+    LLVMInitializePowerPCAsmPrinter();
+    LLVMInitializePowerPCAsmParser();
+
     LLVMRustSetLLVMOptions(0 as c_int,
                                        0 as *const _);
 
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
new file mode 100644
index 00000000000..9b5913c659b
--- /dev/null
+++ b/src/librustc_privacy/lib.rs
@@ -0,0 +1,1599 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "rustc_privacy"]
+#![unstable]
+#![staged_api]
+#![crate_type = "dylib"]
+#![crate_type = "rlib"]
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_root_url = "http://doc.rust-lang.org/nightly/")]
+
+#![feature(rustc_diagnostic_macros)]
+#![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
+
+#[macro_use] extern crate log;
+#[macro_use] extern crate syntax;
+
+extern crate rustc;
+
+use self::PrivacyResult::*;
+use self::FieldName::*;
+
+use std::mem::replace;
+
+use rustc::metadata::csearch;
+use rustc::middle::def;
+use rustc::middle::privacy::ImportUse::*;
+use rustc::middle::privacy::LastPrivate::*;
+use rustc::middle::privacy::PrivateDep::*;
+use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap};
+use rustc::middle::privacy::{ExternalExports};
+use rustc::middle::ty::{MethodTypeParam, MethodStatic};
+use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
+use rustc::middle::ty::{MethodStaticUnboxedClosure, MethodObject};
+use rustc::middle::ty::{MethodTraitObject};
+use rustc::middle::ty::{self, Ty};
+use rustc::util::nodemap::{NodeMap, NodeSet};
+
+use syntax::{ast, ast_map};
+use syntax::ast_util::{is_local, local_def, PostExpansionMethod};
+use syntax::codemap::Span;
+use syntax::parse::token;
+use syntax::visit::{self, Visitor};
+
+type Context<'a, 'tcx> = (&'a MethodMap<'tcx>, &'a def::ExportMap);
+
+/// Result of a checking operation - None => no errors were found. Some => an
+/// error and contains the span and message for reporting that error and
+/// optionally the same for a note about the error.
+type CheckResult = Option<(Span, String, Option<(Span, String)>)>;
+
+////////////////////////////////////////////////////////////////////////////////
+/// The parent visitor, used to determine what's the parent of what (node-wise)
+////////////////////////////////////////////////////////////////////////////////
+
+struct ParentVisitor {
+    parents: NodeMap<ast::NodeId>,
+    curparent: ast::NodeId,
+}
+
+impl<'v> Visitor<'v> for ParentVisitor {
+    fn visit_item(&mut self, item: &ast::Item) {
+        self.parents.insert(item.id, self.curparent);
+
+        let prev = self.curparent;
+        match item.node {
+            ast::ItemMod(..) => { self.curparent = item.id; }
+            // Enum variants are parented to the enum definition itself because
+            // they inherit privacy
+            ast::ItemEnum(ref def, _) => {
+                for variant in def.variants.iter() {
+                    // The parent is considered the enclosing enum because the
+                    // enum will dictate the privacy visibility of this variant
+                    // instead.
+                    self.parents.insert(variant.node.id, item.id);
+                }
+            }
+
+            // Trait methods are always considered "public", but if the trait is
+            // private then we need some private item in the chain from the
+            // method to the root. In this case, if the trait is private, then
+            // parent all the methods to the trait to indicate that they're
+            // private.
+            ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
+                for m in methods.iter() {
+                    match *m {
+                        ast::ProvidedMethod(ref m) => {
+                            self.parents.insert(m.id, item.id);
+                        }
+                        ast::RequiredMethod(ref m) => {
+                            self.parents.insert(m.id, item.id);
+                        }
+                        ast::TypeTraitItem(_) => {}
+                    };
+                }
+            }
+
+            _ => {}
+        }
+        visit::walk_item(self, item);
+        self.curparent = prev;
+    }
+
+    fn visit_foreign_item(&mut self, a: &ast::ForeignItem) {
+        self.parents.insert(a.id, self.curparent);
+        visit::walk_foreign_item(self, a);
+    }
+
+    fn visit_fn(&mut self, a: visit::FnKind<'v>, b: &'v ast::FnDecl,
+                c: &'v ast::Block, d: Span, id: ast::NodeId) {
+        // We already took care of some trait methods above, otherwise things
+        // like impl methods and pub trait methods are parented to the
+        // containing module, not the containing trait.
+        if !self.parents.contains_key(&id) {
+            self.parents.insert(id, self.curparent);
+        }
+        visit::walk_fn(self, a, b, c, d);
+    }
+
+    fn visit_struct_def(&mut self, s: &ast::StructDef, _: ast::Ident,
+                        _: &'v ast::Generics, n: ast::NodeId) {
+        // Struct constructors are parented to their struct definitions because
+        // they essentially are the struct definitions.
+        match s.ctor_id {
+            Some(id) => { self.parents.insert(id, n); }
+            None => {}
+        }
+
+        // While we have the id of the struct definition, go ahead and parent
+        // all the fields.
+        for field in s.fields.iter() {
+            self.parents.insert(field.node.id, self.curparent);
+        }
+        visit::walk_struct_def(self, s)
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// The embargo visitor, used to determine the exports of the ast
+////////////////////////////////////////////////////////////////////////////////
+
+struct EmbargoVisitor<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    export_map: &'a def::ExportMap,
+
+    // This flag is an indicator of whether the previous item in the
+    // hierarchical chain was exported or not. This is the indicator of whether
+    // children should be exported as well. Note that this can flip from false
+    // to true if a reexported module is entered (or an action similar).
+    prev_exported: bool,
+
+    // This is a list of all exported items in the AST. An exported item is any
+    // function/method/item which is usable by external crates. This essentially
+    // means that the result is "public all the way down", but the "path down"
+    // may jump across private boundaries through reexport statements.
+    exported_items: ExportedItems,
+
+    // This sets contains all the destination nodes which are publicly
+    // re-exported. This is *not* a set of all reexported nodes, only a set of
+    // all nodes which are reexported *and* reachable from external crates. This
+    // means that the destination of the reexport is exported, and hence the
+    // destination must also be exported.
+    reexports: NodeSet,
+
+    // These two fields are closely related to one another in that they are only
+    // used for generation of the 'PublicItems' set, not for privacy checking at
+    // all
+    public_items: PublicItems,
+    prev_public: bool,
+}
+
+impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
+    // There are checks inside of privacy which depend on knowing whether a
+    // trait should be exported or not. The two current consumers of this are:
+    //
+    //  1. Should default methods of a trait be exported?
+    //  2. Should the methods of an implementation of a trait be exported?
+    //
+    // The answer to both of these questions partly rely on whether the trait
+    // itself is exported or not. If the trait is somehow exported, then the
+    // answers to both questions must be yes. Right now this question involves
+    // more analysis than is currently done in rustc, so we conservatively
+    // answer "yes" so that all traits need to be exported.
+    fn exported_trait(&self, _id: ast::NodeId) -> bool {
+        true
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        let orig_all_pub = self.prev_public;
+        self.prev_public = orig_all_pub && item.vis == ast::Public;
+        if self.prev_public {
+            self.public_items.insert(item.id);
+        }
+
+        let orig_all_exported = self.prev_exported;
+        match item.node {
+            // impls/extern blocks do not break the "public chain" because they
+            // cannot have visibility qualifiers on them anyway
+            ast::ItemImpl(..) | ast::ItemForeignMod(..) => {}
+
+            // Traits are a little special in that even if they themselves are
+            // not public they may still be exported.
+            ast::ItemTrait(..) => {
+                self.prev_exported = self.exported_trait(item.id);
+            }
+
+            // Private by default, hence we only retain the "public chain" if
+            // `pub` is explicitly listed.
+            _ => {
+                self.prev_exported =
+                    (orig_all_exported && item.vis == ast::Public) ||
+                     self.reexports.contains(&item.id);
+            }
+        }
+
+        let public_first = self.prev_exported &&
+                           self.exported_items.insert(item.id);
+
+        match item.node {
+            // Enum variants inherit from their parent, so if the enum is
+            // public all variants are public unless they're explicitly priv
+            ast::ItemEnum(ref def, _) if public_first => {
+                for variant in def.variants.iter() {
+                    self.exported_items.insert(variant.node.id);
+                }
+            }
+
+            // Implementations are a little tricky to determine what's exported
+            // out of them. Here's a few cases which are currently defined:
+            //
+            // * Impls for private types do not need to export their methods
+            //   (either public or private methods)
+            //
+            // * Impls for public types only have public methods exported
+            //
+            // * Public trait impls for public types must have all methods
+            //   exported.
+            //
+            // * Private trait impls for public types can be ignored
+            //
+            // * Public trait impls for private types have their methods
+            //   exported. I'm not entirely certain that this is the correct
+            //   thing to do, but I have seen use cases of where this will cause
+            //   undefined symbols at linkage time if this case is not handled.
+            //
+            // * Private trait impls for private types can be completely ignored
+            ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
+                let public_ty = match ty.node {
+                    ast::TyPath(_, id) => {
+                        match self.tcx.def_map.borrow()[id].clone() {
+                            def::DefPrimTy(..) => true,
+                            def => {
+                                let did = def.def_id();
+                                !is_local(did) ||
+                                 self.exported_items.contains(&did.node)
+                            }
+                        }
+                    }
+                    _ => true,
+                };
+                let tr = ty::impl_trait_ref(self.tcx, local_def(item.id));
+                let public_trait = tr.clone().map_or(false, |tr| {
+                    !is_local(tr.def_id) ||
+                     self.exported_items.contains(&tr.def_id.node)
+                });
+
+                if public_ty || public_trait {
+                    for impl_item in impl_items.iter() {
+                        match *impl_item {
+                            ast::MethodImplItem(ref method) => {
+                                let meth_public =
+                                    match method.pe_explicit_self().node {
+                                        ast::SelfStatic => public_ty,
+                                        _ => true,
+                                    } && method.pe_vis() == ast::Public;
+                                if meth_public || tr.is_some() {
+                                    self.exported_items.insert(method.id);
+                                }
+                            }
+                            ast::TypeImplItem(_) => {}
+                        }
+                    }
+                }
+            }
+
+            // Default methods on traits are all public so long as the trait
+            // is public
+            ast::ItemTrait(_, _, _, ref methods) if public_first => {
+                for method in methods.iter() {
+                    match *method {
+                        ast::ProvidedMethod(ref m) => {
+                            debug!("provided {}", m.id);
+                            self.exported_items.insert(m.id);
+                        }
+                        ast::RequiredMethod(ref m) => {
+                            debug!("required {}", m.id);
+                            self.exported_items.insert(m.id);
+                        }
+                        ast::TypeTraitItem(ref t) => {
+                            debug!("typedef {}", t.ty_param.id);
+                            self.exported_items.insert(t.ty_param.id);
+                        }
+                    }
+                }
+            }
+
+            // Struct constructors are public if the struct is all public.
+            ast::ItemStruct(ref def, _) if public_first => {
+                match def.ctor_id {
+                    Some(id) => { self.exported_items.insert(id); }
+                    None => {}
+                }
+            }
+
+            ast::ItemTy(ref ty, _) if public_first => {
+                if let ast::TyPath(_, id) = ty.node {
+                    match self.tcx.def_map.borrow()[id].clone() {
+                        def::DefPrimTy(..) | def::DefTyParam(..) => {},
+                        def => {
+                            let did = def.def_id();
+                            if is_local(did) {
+                                self.exported_items.insert(did.node);
+                            }
+                        }
+                    }
+                }
+            }
+
+            _ => {}
+        }
+
+        visit::walk_item(self, item);
+
+        self.prev_exported = orig_all_exported;
+        self.prev_public = orig_all_pub;
+    }
+
+    fn visit_foreign_item(&mut self, a: &ast::ForeignItem) {
+        if (self.prev_exported && a.vis == ast::Public) || self.reexports.contains(&a.id) {
+            self.exported_items.insert(a.id);
+        }
+    }
+
+    fn visit_mod(&mut self, m: &ast::Mod, _sp: Span, id: ast::NodeId) {
+        // This code is here instead of in visit_item so that the
+        // crate module gets processed as well.
+        if self.prev_exported {
+            assert!(self.export_map.contains_key(&id), "wut {}", id);
+            for export in self.export_map[id].iter() {
+                if is_local(export.def_id) {
+                    self.reexports.insert(export.def_id.node);
+                }
+            }
+        }
+        visit::walk_mod(self, m)
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// The privacy visitor, where privacy checks take place (violations reported)
+////////////////////////////////////////////////////////////////////////////////
+
+struct PrivacyVisitor<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    curitem: ast::NodeId,
+    in_foreign: bool,
+    parents: NodeMap<ast::NodeId>,
+    external_exports: ExternalExports,
+    last_private_map: LastPrivateMap,
+}
+
+enum PrivacyResult {
+    Allowable,
+    ExternallyDenied,
+    DisallowedBy(ast::NodeId),
+}
+
+enum FieldName {
+    UnnamedField(uint), // index
+    // FIXME #6993: change type (and name) from Ident to Name
+    NamedField(ast::Ident),
+}
+
+impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
+    // used when debugging
+    fn nodestr(&self, id: ast::NodeId) -> String {
+        self.tcx.map.node_to_string(id).to_string()
+    }
+
+    // Determines whether the given definition is public from the point of view
+    // of the current item.
+    fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
+        if !is_local(did) {
+            if self.external_exports.contains(&did) {
+                debug!("privacy - {:?} was externally exported", did);
+                return Allowable;
+            }
+            debug!("privacy - is {:?} a public method", did);
+
+            return match self.tcx.impl_or_trait_items.borrow().get(&did) {
+                Some(&ty::MethodTraitItem(ref meth)) => {
+                    debug!("privacy - well at least it's a method: {:?}",
+                           *meth);
+                    match meth.container {
+                        ty::TraitContainer(id) => {
+                            debug!("privacy - recursing on trait {:?}", id);
+                            self.def_privacy(id)
+                        }
+                        ty::ImplContainer(id) => {
+                            match ty::impl_trait_ref(self.tcx, id) {
+                                Some(t) => {
+                                    debug!("privacy - impl of trait {:?}", id);
+                                    self.def_privacy(t.def_id)
+                                }
+                                None => {
+                                    debug!("privacy - found a method {:?}",
+                                            meth.vis);
+                                    if meth.vis == ast::Public {
+                                        Allowable
+                                    } else {
+                                        ExternallyDenied
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                Some(&ty::TypeTraitItem(ref typedef)) => {
+                    match typedef.container {
+                        ty::TraitContainer(id) => {
+                            debug!("privacy - recursing on trait {:?}", id);
+                            self.def_privacy(id)
+                        }
+                        ty::ImplContainer(id) => {
+                            match ty::impl_trait_ref(self.tcx, id) {
+                                Some(t) => {
+                                    debug!("privacy - impl of trait {:?}", id);
+                                    self.def_privacy(t.def_id)
+                                }
+                                None => {
+                                    debug!("privacy - found a typedef {:?}",
+                                            typedef.vis);
+                                    if typedef.vis == ast::Public {
+                                        Allowable
+                                    } else {
+                                        ExternallyDenied
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                None => {
+                    debug!("privacy - nope, not even a method");
+                    ExternallyDenied
+                }
+            };
+        }
+
+        debug!("privacy - local {} not public all the way down",
+               self.tcx.map.node_to_string(did.node));
+        // return quickly for things in the same module
+        if self.parents.get(&did.node) == self.parents.get(&self.curitem) {
+            debug!("privacy - same parent, we're done here");
+            return Allowable;
+        }
+
+        // We now know that there is at least one private member between the
+        // destination and the root.
+        let mut closest_private_id = did.node;
+        loop {
+            debug!("privacy - examining {}", self.nodestr(closest_private_id));
+            let vis = match self.tcx.map.find(closest_private_id) {
+                // If this item is a method, then we know for sure that it's an
+                // actual method and not a static method. The reason for this is
+                // that these cases are only hit in the ExprMethodCall
+                // expression, and ExprCall will have its path checked later
+                // (the path of the trait/impl) if it's a static method.
+                //
+                // With this information, then we can completely ignore all
+                // trait methods. The privacy violation would be if the trait
+                // couldn't get imported, not if the method couldn't be used
+                // (all trait methods are public).
+                //
+                // However, if this is an impl method, then we dictate this
+                // decision solely based on the privacy of the method
+                // invocation.
+                // FIXME(#10573) is this the right behavior? Why not consider
+                //               where the method was defined?
+                Some(ast_map::NodeImplItem(ii)) => {
+                    match *ii {
+                        ast::MethodImplItem(ref m) => {
+                            let imp = self.tcx.map
+                                          .get_parent_did(closest_private_id);
+                            match ty::impl_trait_ref(self.tcx, imp) {
+                                Some(..) => return Allowable,
+                                _ if m.pe_vis() == ast::Public => {
+                                    return Allowable
+                                }
+                                _ => m.pe_vis()
+                            }
+                        }
+                        ast::TypeImplItem(_) => return Allowable,
+                    }
+                }
+                Some(ast_map::NodeTraitItem(_)) => {
+                    return Allowable;
+                }
+
+                // This is not a method call, extract the visibility as one
+                // would normally look at it
+                Some(ast_map::NodeItem(it)) => it.vis,
+                Some(ast_map::NodeForeignItem(_)) => {
+                    self.tcx.map.get_foreign_vis(closest_private_id)
+                }
+                Some(ast_map::NodeVariant(..)) => {
+                    ast::Public // need to move up a level (to the enum)
+                }
+                _ => ast::Public,
+            };
+            if vis != ast::Public { break }
+            // if we've reached the root, then everything was allowable and this
+            // access is public.
+            if closest_private_id == ast::CRATE_NODE_ID { return Allowable }
+            closest_private_id = self.parents[closest_private_id];
+
+            // If we reached the top, then we were public all the way down and
+            // we can allow this access.
+            if closest_private_id == ast::DUMMY_NODE_ID { return Allowable }
+        }
+        debug!("privacy - closest priv {}", self.nodestr(closest_private_id));
+        if self.private_accessible(closest_private_id) {
+            Allowable
+        } else {
+            DisallowedBy(closest_private_id)
+        }
+    }
+
+    /// For a local private node in the AST, this function will determine
+    /// whether the node is accessible by the current module that iteration is
+    /// inside.
+    fn private_accessible(&self, id: ast::NodeId) -> bool {
+        let parent = self.parents[id];
+        debug!("privacy - accessible parent {}", self.nodestr(parent));
+
+        // After finding `did`'s closest private member, we roll ourselves back
+        // to see if this private member's parent is anywhere in our ancestry.
+        // By the privacy rules, we can access all of our ancestor's private
+        // members, so that's why we test the parent, and not the did itself.
+        let mut cur = self.curitem;
+        loop {
+            debug!("privacy - questioning {}, {}", self.nodestr(cur), cur);
+            match cur {
+                // If the relevant parent is in our history, then we're allowed
+                // to look inside any of our ancestor's immediate private items,
+                // so this access is valid.
+                x if x == parent => return true,
+
+                // If we've reached the root, then we couldn't access this item
+                // in the first place
+                ast::DUMMY_NODE_ID => return false,
+
+                // Keep going up
+                _ => {}
+            }
+
+            cur = self.parents[cur];
+        }
+    }
+
+    fn report_error(&self, result: CheckResult) -> bool {
+        match result {
+            None => true,
+            Some((span, msg, note)) => {
+                self.tcx.sess.span_err(span, &msg[]);
+                match note {
+                    Some((span, msg)) => {
+                        self.tcx.sess.span_note(span, &msg[])
+                    }
+                    None => {},
+                }
+                false
+            },
+        }
+    }
+
+    /// Guarantee that a particular definition is public. Returns a CheckResult
+    /// which contains any errors found. These can be reported using `report_error`.
+    /// If the result is `None`, no errors were found.
+    fn ensure_public(&self, span: Span, to_check: ast::DefId,
+                     source_did: Option<ast::DefId>, msg: &str) -> CheckResult {
+        let id = match self.def_privacy(to_check) {
+            ExternallyDenied => {
+                return Some((span, format!("{} is private", msg), None))
+            }
+            Allowable => return None,
+            DisallowedBy(id) => id,
+        };
+
+        // If we're disallowed by a particular id, then we attempt to give a
+        // nice error message to say why it was disallowed. It was either
+        // because the item itself is private or because its parent is private
+        // and its parent isn't in our ancestry.
+        let (err_span, err_msg) = if id == source_did.unwrap_or(to_check).node {
+            return Some((span, format!("{} is private", msg), None));
+        } else {
+            (span, format!("{} is inaccessible", msg))
+        };
+        let item = match self.tcx.map.find(id) {
+            Some(ast_map::NodeItem(item)) => {
+                match item.node {
+                    // If an impl disallowed this item, then this is resolve's
+                    // way of saying that a struct/enum's static method was
+                    // invoked, and the struct/enum itself is private. Crawl
+                    // back up the chains to find the relevant struct/enum that
+                    // was private.
+                    ast::ItemImpl(_, _, _, _, ref ty, _) => {
+                        let id = match ty.node {
+                            ast::TyPath(_, id) => id,
+                            _ => return Some((err_span, err_msg, None)),
+                        };
+                        let def = self.tcx.def_map.borrow()[id].clone();
+                        let did = def.def_id();
+                        assert!(is_local(did));
+                        match self.tcx.map.get(did.node) {
+                            ast_map::NodeItem(item) => item,
+                            _ => self.tcx.sess.span_bug(item.span,
+                                                        "path is not an item")
+                        }
+                    }
+                    _ => item
+                }
+            }
+            Some(..) | None => return Some((err_span, err_msg, None)),
+        };
+        let desc = match item.node {
+            ast::ItemMod(..) => "module",
+            ast::ItemTrait(..) => "trait",
+            ast::ItemStruct(..) => "struct",
+            ast::ItemEnum(..) => "enum",
+            _ => return Some((err_span, err_msg, None))
+        };
+        let msg = format!("{} `{}` is private", desc,
+                          token::get_ident(item.ident));
+        Some((err_span, err_msg, Some((span, msg))))
+    }
+
+    // Checks that a field is in scope.
+    fn check_field(&mut self,
+                   span: Span,
+                   id: ast::DefId,
+                   name: FieldName) {
+        let fields = ty::lookup_struct_fields(self.tcx, id);
+        let field = match name {
+            NamedField(ident) => {
+                debug!("privacy - check named field {} in struct {:?}", ident.name, id);
+                fields.iter().find(|f| f.name == ident.name).unwrap()
+            }
+            UnnamedField(idx) => &fields[idx]
+        };
+        if field.vis == ast::Public ||
+            (is_local(field.id) && self.private_accessible(field.id.node)) {
+            return
+        }
+
+        let struct_type = ty::lookup_item_type(self.tcx, id).ty;
+        let struct_desc = match struct_type.sty {
+            ty::ty_struct(_, _) =>
+                format!("struct `{}`", ty::item_path_str(self.tcx, id)),
+            // struct variant fields have inherited visibility
+            ty::ty_enum(..) => return,
+            _ => self.tcx.sess.span_bug(span, "can't find struct for field")
+        };
+        let msg = match name {
+            NamedField(name) => format!("field `{}` of {} is private",
+                                        token::get_ident(name), struct_desc),
+            UnnamedField(idx) => format!("field #{} of {} is private",
+                                         idx + 1, struct_desc),
+        };
+        self.tcx.sess.span_err(span, &msg[]);
+    }
+
+    // Given the ID of a method, checks to ensure it's in scope.
+    fn check_static_method(&mut self,
+                           span: Span,
+                           method_id: ast::DefId,
+                           name: ast::Ident) {
+        // If the method is a default method, we need to use the def_id of
+        // the default implementation.
+        let method_id = match ty::impl_or_trait_item(self.tcx, method_id) {
+            ty::MethodTraitItem(method_type) => {
+                method_type.provided_source.unwrap_or(method_id)
+            }
+            ty::TypeTraitItem(_) => method_id,
+        };
+
+        let string = token::get_ident(name);
+        self.report_error(self.ensure_public(span,
+                                             method_id,
+                                             None,
+                                             &format!("method `{}`",
+                                                     string)[]));
+    }
+
+    // Checks that a path is in scope.
+    fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
+        debug!("privacy - path {}", self.nodestr(path_id));
+        let orig_def = self.tcx.def_map.borrow()[path_id].clone();
+        let ck = |&: tyname: &str| {
+            let ck_public = |&: def: ast::DefId| {
+                debug!("privacy - ck_public {:?}", def);
+                let name = token::get_ident(path.segments.last().unwrap().identifier);
+                let origdid = orig_def.def_id();
+                self.ensure_public(span,
+                                   def,
+                                   Some(origdid),
+                                   &format!("{} `{}`", tyname, name)[])
+            };
+
+            match self.last_private_map[path_id] {
+                LastMod(AllPublic) => {},
+                LastMod(DependsOn(def)) => {
+                    self.report_error(ck_public(def));
+                },
+                LastImport { value_priv,
+                             value_used: check_value,
+                             type_priv,
+                             type_used: check_type } => {
+                    // This dance with found_error is because we don't want to
+                    // report a privacy error twice for the same directive.
+                    let found_error = match (type_priv, check_type) {
+                        (Some(DependsOn(def)), Used) => {
+                            !self.report_error(ck_public(def))
+                        },
+                        _ => false,
+                    };
+                    if !found_error {
+                        match (value_priv, check_value) {
+                            (Some(DependsOn(def)), Used) => {
+                                self.report_error(ck_public(def));
+                            },
+                            _ => {},
+                        }
+                    }
+                    // If an import is not used in either namespace, we still
+                    // want to check that it could be legal. Therefore we check
+                    // in both namespaces and only report an error if both would
+                    // be illegal. We only report one error, even if it is
+                    // illegal to import from both namespaces.
+                    match (value_priv, check_value, type_priv, check_type) {
+                        (Some(p), Unused, None, _) |
+                        (None, _, Some(p), Unused) => {
+                            let p = match p {
+                                AllPublic => None,
+                                DependsOn(def) => ck_public(def),
+                            };
+                            if p.is_some() {
+                                self.report_error(p);
+                            }
+                        },
+                        (Some(v), Unused, Some(t), Unused) => {
+                            let v = match v {
+                                AllPublic => None,
+                                DependsOn(def) => ck_public(def),
+                            };
+                            let t = match t {
+                                AllPublic => None,
+                                DependsOn(def) => ck_public(def),
+                            };
+                            if let (Some(_), Some(t)) = (v, t) {
+                                self.report_error(Some(t));
+                            }
+                        },
+                        _ => {},
+                    }
+                },
+            }
+        };
+        // FIXME(#12334) Imports can refer to definitions in both the type and
+        // value namespaces. The privacy information is aware of this, but the
+        // def map is not. Therefore the names we work out below will not always
+        // be accurate and we can get slightly wonky error messages (but type
+        // checking is always correct).
+        match self.tcx.def_map.borrow()[path_id].clone() {
+            def::DefStaticMethod(..) => ck("static method"),
+            def::DefFn(..) => ck("function"),
+            def::DefStatic(..) => ck("static"),
+            def::DefConst(..) => ck("const"),
+            def::DefVariant(..) => ck("variant"),
+            def::DefTy(_, false) => ck("type"),
+            def::DefTy(_, true) => ck("enum"),
+            def::DefTrait(..) => ck("trait"),
+            def::DefStruct(..) => ck("struct"),
+            def::DefMethod(_, Some(..), _) => ck("trait method"),
+            def::DefMethod(..) => ck("method"),
+            def::DefMod(..) => ck("module"),
+            _ => {}
+        }
+    }
+
+    // Checks that a method is in scope.
+    fn check_method(&mut self, span: Span, origin: &MethodOrigin,
+                    ident: ast::Ident) {
+        match *origin {
+            MethodStatic(method_id) => {
+                self.check_static_method(span, method_id, ident)
+            }
+            MethodStaticUnboxedClosure(_) => {}
+            // Trait methods are always all public. The only controlling factor
+            // is whether the trait itself is accessible or not.
+            MethodTypeParam(MethodParam { ref trait_ref, .. }) |
+            MethodTraitObject(MethodObject { ref trait_ref, .. }) => {
+                self.report_error(self.ensure_public(span, trait_ref.def_id,
+                                                     None, "source trait"));
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        let orig_curitem = replace(&mut self.curitem, item.id);
+        visit::walk_item(self, item);
+        self.curitem = orig_curitem;
+    }
+
+    fn visit_expr(&mut self, expr: &ast::Expr) {
+        match expr.node {
+            ast::ExprField(ref base, ident) => {
+                if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
+                    self.check_field(expr.span, id, NamedField(ident.node));
+                }
+            }
+            ast::ExprTupField(ref base, idx) => {
+                if let ty::ty_struct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
+                    self.check_field(expr.span, id, UnnamedField(idx.node));
+                }
+            }
+            ast::ExprMethodCall(ident, _, _) => {
+                let method_call = MethodCall::expr(expr.id);
+                match self.tcx.method_map.borrow().get(&method_call) {
+                    None => {
+                        self.tcx.sess.span_bug(expr.span,
+                                                "method call not in \
+                                                method map");
+                    }
+                    Some(method) => {
+                        debug!("(privacy checking) checking impl method");
+                        self.check_method(expr.span, &method.origin, ident.node);
+                    }
+                }
+            }
+            ast::ExprStruct(_, ref fields, _) => {
+                match ty::expr_ty(self.tcx, expr).sty {
+                    ty::ty_struct(id, _) => {
+                        for field in (*fields).iter() {
+                            self.check_field(expr.span, id,
+                                             NamedField(field.ident.node));
+                        }
+                    }
+                    ty::ty_enum(_, _) => {
+                        match self.tcx.def_map.borrow()[expr.id].clone() {
+                            def::DefVariant(_, variant_id, _) => {
+                                for field in fields.iter() {
+                                    self.check_field(expr.span, variant_id,
+                                                     NamedField(field.ident.node));
+                                }
+                            }
+                            _ => self.tcx.sess.span_bug(expr.span,
+                                                        "resolve didn't \
+                                                         map enum struct \
+                                                         constructor to a \
+                                                         variant def"),
+                        }
+                    }
+                    _ => self.tcx.sess.span_bug(expr.span, "struct expr \
+                                                            didn't have \
+                                                            struct type?!"),
+                }
+            }
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
+                let guard = |&: did: ast::DefId| {
+                    let fields = ty::lookup_struct_fields(self.tcx, did);
+                    let any_priv = fields.iter().any(|f| {
+                        f.vis != ast::Public && (
+                            !is_local(f.id) ||
+                            !self.private_accessible(f.id.node))
+                    });
+                    if any_priv {
+                        self.tcx.sess.span_err(expr.span,
+                            "cannot invoke tuple struct constructor \
+                             with private fields");
+                    }
+                };
+                match self.tcx.def_map.borrow().get(&expr.id) {
+                    Some(&def::DefStruct(did)) => {
+                        guard(if is_local(did) {
+                            local_def(self.tcx.map.get_parent(did.node))
+                        } else {
+                            // "tuple structs" with zero fields (such as
+                            // `pub struct Foo;`) don't have a ctor_id, hence
+                            // the unwrap_or to the same struct id.
+                            let maybe_did =
+                                csearch::get_tuple_struct_definition_if_ctor(
+                                    &self.tcx.sess.cstore, did);
+                            maybe_did.unwrap_or(did)
+                        })
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
+        visit::walk_expr(self, expr);
+    }
+
+    fn visit_view_item(&mut self, a: &ast::ViewItem) {
+        match a.node {
+            ast::ViewItemExternCrate(..) => {}
+            ast::ViewItemUse(ref vpath) => {
+                match vpath.node {
+                    ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
+                    ast::ViewPathList(ref prefix, ref list, _) => {
+                        for pid in list.iter() {
+                            match pid.node {
+                                ast::PathListIdent { id, name } => {
+                                    debug!("privacy - ident item {}", id);
+                                    let seg = ast::PathSegment {
+                                        identifier: name,
+                                        parameters: ast::PathParameters::none(),
+                                    };
+                                    let segs = vec![seg];
+                                    let path = ast::Path {
+                                        global: false,
+                                        span: pid.span,
+                                        segments: segs,
+                                    };
+                                    self.check_path(pid.span, id, &path);
+                                }
+                                ast::PathListMod { id } => {
+                                    debug!("privacy - mod item {}", id);
+                                    self.check_path(pid.span, id, prefix);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        visit::walk_view_item(self, a);
+    }
+
+    fn visit_pat(&mut self, pattern: &ast::Pat) {
+        // Foreign functions do not have their patterns mapped in the def_map,
+        // and there's nothing really relevant there anyway, so don't bother
+        // checking privacy. If you can name the type then you can pass it to an
+        // external C function anyway.
+        if self.in_foreign { return }
+
+        match pattern.node {
+            ast::PatStruct(_, ref fields, _) => {
+                match ty::pat_ty(self.tcx, pattern).sty {
+                    ty::ty_struct(id, _) => {
+                        for field in fields.iter() {
+                            self.check_field(pattern.span, id,
+                                             NamedField(field.node.ident));
+                        }
+                    }
+                    ty::ty_enum(_, _) => {
+                        match self.tcx.def_map.borrow().get(&pattern.id) {
+                            Some(&def::DefVariant(_, variant_id, _)) => {
+                                for field in fields.iter() {
+                                    self.check_field(pattern.span, variant_id,
+                                                     NamedField(field.node.ident));
+                                }
+                            }
+                            _ => self.tcx.sess.span_bug(pattern.span,
+                                                        "resolve didn't \
+                                                         map enum struct \
+                                                         pattern to a \
+                                                         variant def"),
+                        }
+                    }
+                    _ => self.tcx.sess.span_bug(pattern.span,
+                                                "struct pattern didn't have \
+                                                 struct type?!"),
+                }
+            }
+
+            // Patterns which bind no fields are allowable (the path is check
+            // elsewhere).
+            ast::PatEnum(_, Some(ref fields)) => {
+                match ty::pat_ty(self.tcx, pattern).sty {
+                    ty::ty_struct(id, _) => {
+                        for (i, field) in fields.iter().enumerate() {
+                            if let ast::PatWild(..) = field.node {
+                                continue
+                            }
+                            self.check_field(field.span, id, UnnamedField(i));
+                        }
+                    }
+                    ty::ty_enum(..) => {
+                        // enum fields have no privacy at this time
+                    }
+                    _ => {}
+                }
+
+            }
+            _ => {}
+        }
+
+        visit::walk_pat(self, pattern);
+    }
+
+    fn visit_foreign_item(&mut self, fi: &ast::ForeignItem) {
+        self.in_foreign = true;
+        visit::walk_foreign_item(self, fi);
+        self.in_foreign = false;
+    }
+
+    fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
+        self.check_path(path.span, id, path);
+        visit::walk_path(self, path);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// The privacy sanity check visitor, ensures unnecessary visibility isn't here
+////////////////////////////////////////////////////////////////////////////////
+
+struct SanePrivacyVisitor<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    in_fn: bool,
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        if self.in_fn {
+            self.check_all_inherited(item);
+        } else {
+            self.check_sane_privacy(item);
+        }
+
+        let in_fn = self.in_fn;
+        let orig_in_fn = replace(&mut self.in_fn, match item.node {
+            ast::ItemMod(..) => false, // modules turn privacy back on
+            _ => in_fn,           // otherwise we inherit
+        });
+        visit::walk_item(self, item);
+        self.in_fn = orig_in_fn;
+    }
+
+    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
+                b: &'v ast::Block, s: Span, _: ast::NodeId) {
+        // This catches both functions and methods
+        let orig_in_fn = replace(&mut self.in_fn, true);
+        visit::walk_fn(self, fk, fd, b, s);
+        self.in_fn = orig_in_fn;
+    }
+
+    fn visit_view_item(&mut self, i: &ast::ViewItem) {
+        match i.vis {
+            ast::Inherited => {}
+            ast::Public => {
+                if self.in_fn {
+                    self.tcx.sess.span_err(i.span, "unnecessary `pub`, imports \
+                                                    in functions are never \
+                                                    reachable");
+                } else if let ast::ViewItemExternCrate(..) = i.node {
+                    self.tcx.sess.span_err(i.span, "`pub` visibility \
+                                                    is not allowed");
+                }
+            }
+        }
+        visit::walk_view_item(self, i);
+    }
+}
+
+impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
+    /// Validates all of the visibility qualifiers placed on the item given. This
+    /// ensures that there are no extraneous qualifiers that don't actually do
+    /// anything. In theory these qualifiers wouldn't parse, but that may happen
+    /// later on down the road...
+    fn check_sane_privacy(&self, item: &ast::Item) {
+        let tcx = self.tcx;
+        let check_inherited = |&: sp: Span, vis: ast::Visibility, note: &str| {
+            if vis != ast::Inherited {
+                tcx.sess.span_err(sp, "unnecessary visibility qualifier");
+                if note.len() > 0 {
+                    tcx.sess.span_note(sp, note);
+                }
+            }
+        };
+        match item.node {
+            // implementations of traits don't need visibility qualifiers because
+            // that's controlled by having the trait in scope.
+            ast::ItemImpl(_, _, _, Some(..), _, ref impl_items) => {
+                check_inherited(item.span, item.vis,
+                                "visibility qualifiers have no effect on trait \
+                                 impls");
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        ast::MethodImplItem(ref m) => {
+                            check_inherited(m.span, m.pe_vis(), "");
+                        }
+                        ast::TypeImplItem(_) => {}
+                    }
+                }
+            }
+
+            ast::ItemImpl(..) => {
+                check_inherited(item.span, item.vis,
+                                "place qualifiers on individual methods instead");
+            }
+            ast::ItemForeignMod(..) => {
+                check_inherited(item.span, item.vis,
+                                "place qualifiers on individual functions \
+                                 instead");
+            }
+
+            ast::ItemEnum(ref def, _) => {
+                for v in def.variants.iter() {
+                    match v.node.vis {
+                        ast::Public => {
+                            if item.vis == ast::Public {
+                                tcx.sess.span_err(v.span, "unnecessary `pub` \
+                                                           visibility");
+                            }
+                        }
+                        ast::Inherited => {}
+                    }
+                }
+            }
+
+            ast::ItemTrait(_, _, _, ref methods) => {
+                for m in methods.iter() {
+                    match *m {
+                        ast::ProvidedMethod(ref m) => {
+                            check_inherited(m.span, m.pe_vis(),
+                                            "unnecessary visibility");
+                        }
+                        ast::RequiredMethod(ref m) => {
+                            check_inherited(m.span, m.vis,
+                                            "unnecessary visibility");
+                        }
+                        ast::TypeTraitItem(_) => {}
+                    }
+                }
+            }
+
+            ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) |
+            ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
+            ast::ItemMac(..) => {}
+        }
+    }
+
+    /// When inside of something like a function or a method, visibility has no
+    /// control over anything so this forbids any mention of any visibility
+    fn check_all_inherited(&self, item: &ast::Item) {
+        let tcx = self.tcx;
+        fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
+            if vis != ast::Inherited {
+                tcx.sess.span_err(sp, "visibility has no effect inside functions");
+            }
+        }
+        let check_struct = |&: def: &ast::StructDef| {
+            for f in def.fields.iter() {
+               match f.node.kind {
+                    ast::NamedField(_, p) => check_inherited(tcx, f.span, p),
+                    ast::UnnamedField(..) => {}
+                }
+            }
+        };
+        check_inherited(tcx, item.span, item.vis);
+        match item.node {
+            ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
+                for impl_item in impl_items.iter() {
+                    match *impl_item {
+                        ast::MethodImplItem(ref m) => {
+                            check_inherited(tcx, m.span, m.pe_vis());
+                        }
+                        ast::TypeImplItem(_) => {}
+                    }
+                }
+            }
+            ast::ItemForeignMod(ref fm) => {
+                for i in fm.items.iter() {
+                    check_inherited(tcx, i.span, i.vis);
+                }
+            }
+            ast::ItemEnum(ref def, _) => {
+                for v in def.variants.iter() {
+                    check_inherited(tcx, v.span, v.node.vis);
+                }
+            }
+
+            ast::ItemStruct(ref def, _) => check_struct(&**def),
+
+            ast::ItemTrait(_, _, _, ref methods) => {
+                for m in methods.iter() {
+                    match *m {
+                        ast::RequiredMethod(..) => {}
+                        ast::ProvidedMethod(ref m) => check_inherited(tcx, m.span,
+                                                                m.pe_vis()),
+                        ast::TypeTraitItem(_) => {}
+                    }
+                }
+            }
+
+            ast::ItemStatic(..) | ast::ItemConst(..) |
+            ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
+            ast::ItemMac(..) => {}
+        }
+    }
+}
+
+struct VisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    exported_items: &'a ExportedItems,
+    public_items: &'a PublicItems,
+    in_variant: bool,
+}
+
+struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
+    inner: &'a VisiblePrivateTypesVisitor<'b, 'tcx>,
+    /// whether the type refers to private types.
+    contains_private: bool,
+    /// whether we've recurred at all (i.e. if we're pointing at the
+    /// first type on which visit_ty was called).
+    at_outer_type: bool,
+    // whether that first type is a public path.
+    outer_type_is_public_path: bool,
+}
+
+impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
+    fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
+        let did = match self.tcx.def_map.borrow().get(&path_id).cloned() {
+            // `int` etc. (None doesn't seem to occur.)
+            None | Some(def::DefPrimTy(..)) => return false,
+            Some(def) => def.def_id()
+        };
+        // A path can only be private if:
+        // it's in this crate...
+        if !is_local(did) {
+            return false
+        }
+        // .. and it corresponds to a private type in the AST (this returns
+        // None for type parameters)
+        match self.tcx.map.find(did.node) {
+            Some(ast_map::NodeItem(ref item)) => item.vis != ast::Public,
+            Some(_) | None => false,
+        }
+    }
+
+    fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
+        // FIXME: this would preferably be using `exported_items`, but all
+        // traits are exported currently (see `EmbargoVisitor.exported_trait`)
+        self.public_items.contains(&trait_id)
+    }
+
+    fn check_ty_param_bound(&self,
+                            ty_param_bound: &ast::TyParamBound) {
+        if let ast::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
+            if !self.tcx.sess.features.borrow().visible_private_types &&
+                self.path_is_private_type(trait_ref.trait_ref.ref_id) {
+                    let span = trait_ref.trait_ref.path.span;
+                    self.tcx.sess.span_err(span,
+                                           "private trait in exported type \
+                                            parameter bound");
+            }
+        }
+    }
+}
+
+impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
+    fn visit_ty(&mut self, ty: &ast::Ty) {
+        if let ast::TyPath(_, path_id) = ty.node {
+            if self.inner.path_is_private_type(path_id) {
+                self.contains_private = true;
+                // found what we're looking for so let's stop
+                // working.
+                return
+            } else if self.at_outer_type {
+                self.outer_type_is_public_path = true;
+            }
+        }
+        self.at_outer_type = false;
+        visit::walk_ty(self, ty)
+    }
+
+    // don't want to recurse into [, .. expr]
+    fn visit_expr(&mut self, _: &ast::Expr) {}
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        match item.node {
+            // contents of a private mod can be reexported, so we need
+            // to check internals.
+            ast::ItemMod(_) => {}
+
+            // An `extern {}` doesn't introduce a new privacy
+            // namespace (the contents have their own privacies).
+            ast::ItemForeignMod(_) => {}
+
+            ast::ItemTrait(_, _, ref bounds, _) => {
+                if !self.trait_is_public(item.id) {
+                    return
+                }
+
+                for bound in bounds.iter() {
+                    self.check_ty_param_bound(bound)
+                }
+            }
+
+            // impls need some special handling to try to offer useful
+            // error messages without (too many) false positives
+            // (i.e. we could just return here to not check them at
+            // all, or some worse estimation of whether an impl is
+            // publicly visible.
+            ast::ItemImpl(_, _, ref g, ref trait_ref, ref self_, ref impl_items) => {
+                // `impl [... for] Private` is never visible.
+                let self_contains_private;
+                // impl [... for] Public<...>, but not `impl [... for]
+                // ~[Public]` or `(Public,)` etc.
+                let self_is_public_path;
+
+                // check the properties of the Self type:
+                {
+                    let mut visitor = CheckTypeForPrivatenessVisitor {
+                        inner: self,
+                        contains_private: false,
+                        at_outer_type: true,
+                        outer_type_is_public_path: false,
+                    };
+                    visitor.visit_ty(&**self_);
+                    self_contains_private = visitor.contains_private;
+                    self_is_public_path = visitor.outer_type_is_public_path;
+                }
+
+                // miscellaneous info about the impl
+
+                // `true` iff this is `impl Private for ...`.
+                let not_private_trait =
+                    trait_ref.as_ref().map_or(true, // no trait counts as public trait
+                                              |tr| {
+                        let did = ty::trait_ref_to_def_id(self.tcx, tr);
+
+                        !is_local(did) || self.trait_is_public(did.node)
+                    });
+
+                // `true` iff this is a trait impl or at least one method is public.
+                //
+                // `impl Public { $( fn ...() {} )* }` is not visible.
+                //
+                // This is required over just using the methods' privacy
+                // directly because we might have `impl<T: Foo<Private>> ...`,
+                // and we shouldn't warn about the generics if all the methods
+                // are private (because `T` won't be visible externally).
+                let trait_or_some_public_method =
+                    trait_ref.is_some() ||
+                    impl_items.iter()
+                              .any(|impl_item| {
+                                  match *impl_item {
+                                      ast::MethodImplItem(ref m) => {
+                                          self.exported_items.contains(&m.id)
+                                      }
+                                      ast::TypeImplItem(_) => false,
+                                  }
+                              });
+
+                if !self_contains_private &&
+                        not_private_trait &&
+                        trait_or_some_public_method {
+
+                    visit::walk_generics(self, g);
+
+                    match *trait_ref {
+                        None => {
+                            for impl_item in impl_items.iter() {
+                                match *impl_item {
+                                    ast::MethodImplItem(ref method) => {
+                                        visit::walk_method_helper(self, &**method)
+                                    }
+                                    ast::TypeImplItem(_) => {}
+                                }
+                            }
+                        }
+                        Some(ref tr) => {
+                            // Any private types in a trait impl fall into two
+                            // categories.
+                            // 1. mentioned in the trait definition
+                            // 2. mentioned in the type params/generics
+                            //
+                            // Those in 1. can only occur if the trait is in
+                            // this crate and will've been warned about on the
+                            // trait definition (there's no need to warn twice
+                            // so we don't check the methods).
+                            //
+                            // Those in 2. are warned via walk_generics and this
+                            // call here.
+                            self.visit_trait_ref(tr)
+                        }
+                    }
+                } else if trait_ref.is_none() && self_is_public_path {
+                    // impl Public<Private> { ... }. Any public static
+                    // methods will be visible as `Public::foo`.
+                    let mut found_pub_static = false;
+                    for impl_item in impl_items.iter() {
+                        match *impl_item {
+                            ast::MethodImplItem(ref method) => {
+                                if method.pe_explicit_self().node ==
+                                        ast::SelfStatic &&
+                                        self.exported_items
+                                            .contains(&method.id) {
+                                    found_pub_static = true;
+                                    visit::walk_method_helper(self, &**method);
+                                }
+                            }
+                            ast::TypeImplItem(_) => {}
+                        }
+                    }
+                    if found_pub_static {
+                        visit::walk_generics(self, g)
+                    }
+                }
+                return
+            }
+
+            // `type ... = ...;` can contain private types, because
+            // we're introducing a new name.
+            ast::ItemTy(..) => return,
+
+            // not at all public, so we don't care
+            _ if !self.exported_items.contains(&item.id) => return,
+
+            _ => {}
+        }
+
+        // we've carefully constructed it so that if we're here, then
+        // any `visit_ty`'s will be called on things that are in
+        // public signatures, i.e. things that we're interested in for
+        // this visitor.
+        visit::walk_item(self, item);
+    }
+
+    fn visit_generics(&mut self, generics: &ast::Generics) {
+        for ty_param in generics.ty_params.iter() {
+            for bound in ty_param.bounds.iter() {
+                self.check_ty_param_bound(bound)
+            }
+        }
+        for predicate in generics.where_clause.predicates.iter() {
+            match predicate {
+                &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
+                    for bound in bound_pred.bounds.iter() {
+                        self.check_ty_param_bound(bound)
+                    }
+                }
+                &ast::WherePredicate::RegionPredicate(_) => {}
+                &ast::WherePredicate::EqPredicate(ref eq_pred) => {
+                    self.visit_ty(&*eq_pred.ty);
+                }
+            }
+        }
+    }
+
+    fn visit_foreign_item(&mut self, item: &ast::ForeignItem) {
+        if self.exported_items.contains(&item.id) {
+            visit::walk_foreign_item(self, item)
+        }
+    }
+
+    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
+                b: &'v ast::Block, s: Span, id: ast::NodeId) {
+        // needs special handling for methods.
+        if self.exported_items.contains(&id) {
+            visit::walk_fn(self, fk, fd, b, s);
+        }
+    }
+
+    fn visit_ty(&mut self, t: &ast::Ty) {
+        if let ast::TyPath(ref p, path_id) = t.node {
+            if !self.tcx.sess.features.borrow().visible_private_types &&
+                self.path_is_private_type(path_id) {
+                self.tcx.sess.span_err(p.span,
+                                       "private type in exported type signature");
+            }
+        }
+        visit::walk_ty(self, t)
+    }
+
+    fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) {
+        if self.exported_items.contains(&v.node.id) {
+            self.in_variant = true;
+            visit::walk_variant(self, v, g);
+            self.in_variant = false;
+        }
+    }
+
+    fn visit_struct_field(&mut self, s: &ast::StructField) {
+        match s.node.kind {
+            ast::NamedField(_, vis) if vis == ast::Public || self.in_variant => {
+                visit::walk_struct_field(self, s);
+            }
+            _ => {}
+        }
+    }
+
+
+    // we don't need to introspect into these at all: an
+    // expression/block context can't possibly contain exported
+    // things, and neither do view_items. (Making them no-ops stops us
+    // from traversing the whole AST without having to be super
+    // careful about our `walk_...` calls above.)
+    fn visit_view_item(&mut self, _: &ast::ViewItem) {}
+    fn visit_block(&mut self, _: &ast::Block) {}
+    fn visit_expr(&mut self, _: &ast::Expr) {}
+}
+
+pub fn check_crate(tcx: &ty::ctxt,
+                   export_map: &def::ExportMap,
+                   external_exports: ExternalExports,
+                   last_private_map: LastPrivateMap)
+                   -> (ExportedItems, PublicItems) {
+    let krate = tcx.map.krate();
+
+    // Figure out who everyone's parent is
+    let mut visitor = ParentVisitor {
+        parents: NodeMap::new(),
+        curparent: ast::DUMMY_NODE_ID,
+    };
+    visit::walk_crate(&mut visitor, krate);
+
+    // Use the parent map to check the privacy of everything
+    let mut visitor = PrivacyVisitor {
+        curitem: ast::DUMMY_NODE_ID,
+        in_foreign: false,
+        tcx: tcx,
+        parents: visitor.parents,
+        external_exports: external_exports,
+        last_private_map: last_private_map,
+    };
+    visit::walk_crate(&mut visitor, krate);
+
+    // Sanity check to make sure that all privacy usage and controls are
+    // reasonable.
+    let mut visitor = SanePrivacyVisitor {
+        in_fn: false,
+        tcx: tcx,
+    };
+    visit::walk_crate(&mut visitor, krate);
+
+    tcx.sess.abort_if_errors();
+
+    // Build up a set of all exported items in the AST. This is a set of all
+    // items which are reachable from external crates based on visibility.
+    let mut visitor = EmbargoVisitor {
+        tcx: tcx,
+        exported_items: NodeSet::new(),
+        public_items: NodeSet::new(),
+        reexports: NodeSet::new(),
+        export_map: export_map,
+        prev_exported: true,
+        prev_public: true,
+    };
+    loop {
+        let before = visitor.exported_items.len();
+        visit::walk_crate(&mut visitor, krate);
+        if before == visitor.exported_items.len() {
+            break
+        }
+    }
+
+    let EmbargoVisitor { exported_items, public_items, .. } = visitor;
+
+    {
+        let mut visitor = VisiblePrivateTypesVisitor {
+            tcx: tcx,
+            exported_items: &exported_items,
+            public_items: &public_items,
+            in_variant: false,
+        };
+        visit::walk_crate(&mut visitor, krate);
+    }
+    return (exported_items, public_items);
+}
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 466bd608736..8d62c5e1ca0 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -999,7 +999,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                                   root: &Rc<Module>,
                                                   def_like: DefLike,
                                                   name: Name,
-                                                  visibility: Visibility) {
+                                                  def_visibility: Visibility) {
         match def_like {
             DlDef(def) => {
                 // Add the new child item, if necessary.
@@ -1027,7 +1027,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                            DUMMY_SP);
 
                         self.handle_external_def(def,
-                                                 visibility,
+                                                 def_visibility,
                                                  &*child_name_bindings,
                                                  token::get_name(name).get(),
                                                  name,
@@ -1106,7 +1106,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                     let def = DefFn(method_info.def_id, false);
 
                                     // NB: not IMPORTABLE
-                                    let modifiers = if visibility == ast::Public {
+                                    let modifiers = if method_info.vis == ast::Public {
                                         PUBLIC
                                     } else {
                                         DefModifiers::empty()
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index ea6ecfbb92b..8c1e847748c 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -20,9 +20,11 @@
 #![feature(slicing_syntax)]
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
+#[macro_use] #[no_link] extern crate rustc_bitflags;
 
 extern crate rustc;
 
@@ -61,7 +63,7 @@ use rustc::util::lev_distance::lev_distance;
 use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
 use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
 use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
-use syntax::ast::{ExprPath, ExprStruct, FnDecl};
+use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
 use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
 use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn};
 use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
@@ -2081,7 +2083,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                             // idx +- 1 to account for the
                                             // colons on either side
                                             &mpath[(idx + 1)..],
-                                            &mpath[0..(idx - 1)]);
+                                            &mpath[..(idx - 1)]);
                         return Failed(Some((span, msg)));
                     },
                     None => {
@@ -3169,7 +3171,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     TraitImplementation        => "implement",
                     TraitDerivation            => "derive",
                     TraitObject                => "reference",
-                    TraitQPath                 => "extract an associated type from",
+                    TraitQPath                 => "extract an associated item from",
                 };
 
                 let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
@@ -3565,31 +3567,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     }
                 }
 
-                match result_def {
-                    None => {
-                        match self.resolve_path(ty.id, path, TypeNS, true) {
-                            Some(def) => {
-                                debug!("(resolving type) resolved `{:?}` to \
-                                        type {:?}",
-                                       token::get_ident(path.segments.last().unwrap() .identifier),
-                                       def);
-                                result_def = Some(def);
-                            }
-                            None => {
-                                result_def = None;
-                            }
-                        }
-                    }
-                    Some(_) => {}   // Continue.
+                if let None = result_def {
+                    result_def = self.resolve_path(ty.id, path, TypeNS, true);
                 }
 
                 match result_def {
                     Some(def) => {
                         // Write the result into the def map.
                         debug!("(resolving type) writing resolution for `{}` \
-                                (id {})",
+                                (id {}) = {:?}",
                                self.path_names_to_string(path),
-                               path_id);
+                               path_id, def);
                         self.record_def(path_id, def);
                     }
                     None => {
@@ -3609,6 +3597,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             TyQPath(ref qpath) => {
                 self.resolve_type(&*qpath.self_type);
                 self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
+                for ty in qpath.item_path.parameters.types().into_iter() {
+                    self.resolve_type(&**ty);
+                }
+                for binding in qpath.item_path.parameters.bindings().into_iter() {
+                    self.resolve_type(&*binding.ty);
+                }
             }
 
             TyPolyTraitRef(ref bounds) => {
@@ -4400,15 +4394,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             // The interpretation of paths depends on whether the path has
             // multiple elements in it or not.
 
-            ExprPath(ref path) => {
+            ExprPath(_) | ExprQPath(_) => {
+                let mut path_from_qpath;
+                let path = match expr.node {
+                    ExprPath(ref path) => path,
+                    ExprQPath(ref qpath) => {
+                        self.resolve_type(&*qpath.self_type);
+                        self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
+                        path_from_qpath = qpath.trait_ref.path.clone();
+                        path_from_qpath.segments.push(qpath.item_path.clone());
+                        &path_from_qpath
+                    }
+                    _ => unreachable!()
+                };
                 // This is a local path in the value namespace. Walk through
                 // scopes looking for it.
-
-                let path_name = self.path_names_to_string(path);
-
                 match self.resolve_path(expr.id, path, ValueNS, true) {
                     // Check if struct variant
                     Some((DefVariant(_, _, true), _)) => {
+                        let path_name = self.path_names_to_string(path);
                         self.resolve_error(expr.span,
                                 format!("`{}` is a struct variant name, but \
                                          this expression \
@@ -4423,7 +4427,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     Some(def) => {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `{}`",
-                               path_name);
+                               self.path_names_to_string(path));
 
                         self.record_def(expr.id, def);
                     }
@@ -4432,6 +4436,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         // (The pattern matching def_tys where the id is in self.structs
                         // matches on regular structs while excluding tuple- and enum-like
                         // structs, which wouldn't result in this error.)
+                        let path_name = self.path_names_to_string(path);
                         match self.with_no_errors(|this|
                             this.resolve_path(expr.id, path, TypeNS, false)) {
                             Some((DefTy(struct_id, _), _))
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 351be70cf52..dacf620cbd1 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -507,7 +507,7 @@ fn link_binary_output(sess: &Session,
 
 fn archive_search_paths(sess: &Session) -> Vec<Path> {
     let mut search = Vec::new();
-    sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path| {
+    sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path, _| {
         search.push(path.clone());
         FileDoesntMatch
     });
@@ -1043,7 +1043,7 @@ fn link_args(cmd: &mut Command,
 // in the current crate. Upstream crates with native library dependencies
 // may have their native library pulled in above.
 fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
-    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path| {
+    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, _| {
         cmd.arg("-L").arg(path);
         FileDoesntMatch
     });
@@ -1146,10 +1146,10 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
         let src = sess.cstore.get_used_crate_source(cnum).unwrap();
         match kind {
             cstore::RequireDynamic => {
-                add_dynamic_crate(cmd, sess, src.dylib.unwrap())
+                add_dynamic_crate(cmd, sess, src.dylib.unwrap().0)
             }
             cstore::RequireStatic => {
-                add_static_crate(cmd, sess, tmpdir, src.rlib.unwrap())
+                add_static_crate(cmd, sess, tmpdir, src.rlib.unwrap().0)
             }
         }
 
diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs
index b6a6b526fac..c0b1492a784 100644
--- a/src/librustc_trans/back/lto.rs
+++ b/src/librustc_trans/back/lto.rs
@@ -167,7 +167,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
         llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
         llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
 
+        let opt = sess.opts.cg.opt_level.unwrap_or(0) as libc::c_uint;
+
         let builder = llvm::LLVMPassManagerBuilderCreate();
+        llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt);
         llvm::LLVMPassManagerBuilderPopulateLTOPassManager(builder, pm,
             /* Internalize = */ False,
             /* RunInliner = */ True);
@@ -186,7 +189,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
 fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
     let magic_id_byte_count = link::RLIB_BYTECODE_OBJECT_MAGIC.len();
     return bc.len() > magic_id_byte_count &&
-           &bc[0..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
+           &bc[..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
 }
 
 fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index c818dda7581..aa51b0c5ee2 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -1039,6 +1039,12 @@ unsafe fn configure_llvm(sess: &Session) {
         llvm::LLVMInitializeMipsAsmPrinter();
         llvm::LLVMInitializeMipsAsmParser();
 
+        llvm::LLVMInitializePowerPCTargetInfo();
+        llvm::LLVMInitializePowerPCTarget();
+        llvm::LLVMInitializePowerPCTargetMC();
+        llvm::LLVMInitializePowerPCAsmPrinter();
+        llvm::LLVMInitializePowerPCAsmParser();
+
         llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                      llvm_args.as_ptr());
     });
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 4859598e63c..c3e88e65b2f 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -29,6 +29,7 @@
 #![feature(box_syntax)]
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate arena;
 extern crate flate;
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index eb163ed7406..b12903c814c 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -186,7 +186,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         if len <= 2 {
             return;
         }
-        let sub_paths = &sub_paths[0..(len-2)];
+        let sub_paths = &sub_paths[..(len-2)];
         for &(ref span, ref qualname) in sub_paths.iter() {
             self.fmt.sub_mod_ref_str(path.span,
                                      *span,
@@ -278,7 +278,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in followed by the method's name.
         let mut qualname = match ty::impl_of_method(&self.analysis.ty_cx,
-                                                ast_util::local_def(method.id)) {
+                                                    ast_util::local_def(method.id)) {
             Some(impl_id) => match self.analysis.ty_cx.map.get(impl_id.node) {
                 NodeItem(item) => {
                     scope_id = item.id;
@@ -349,7 +349,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
             .and_then(|def_id| {
                 if match def_id {
                     ty::MethodTraitItemId(def_id) => {
-                        method.id != 0 && def_id.node == 0
+                        def_id.node != 0 && def_id != ast_util::local_def(method.id)
                     }
                     ty::TypeTraitItemId(_) => false,
                 } {
@@ -392,8 +392,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
     }
 
     fn process_trait_ref(&mut self,
-                         trait_ref: &ast::TraitRef,
-                         impl_id: Option<NodeId>) {
+                         trait_ref: &ast::TraitRef) {
         match self.lookup_type_ref(trait_ref.ref_id) {
             Some(id) => {
                 let sub_span = self.span.sub_span_for_type_name(trait_ref.path.span);
@@ -402,14 +401,6 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                                  sub_span,
                                  id,
                                  self.cur_scope);
-                match impl_id {
-                    Some(impl_id) => self.fmt.impl_str(trait_ref.path.span,
-                                                       sub_span,
-                                                       impl_id,
-                                                       id,
-                                                       self.cur_scope),
-                    None => (),
-                }
                 visit::walk_path(self, &trait_ref.path);
             },
             None => ()
@@ -652,7 +643,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                     trait_ref: &Option<ast::TraitRef>,
                     typ: &ast::Ty,
                     impl_items: &Vec<ast::ImplItem>) {
+        let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id));
         match typ.node {
+            // Common case impl for a struct or something basic.
             ast::TyPath(ref path, id) => {
                 match self.lookup_type_ref(id) {
                     Some(id) => {
@@ -665,17 +658,29 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                         self.fmt.impl_str(path.span,
                                           sub_span,
                                           item.id,
-                                          id,
+                                          Some(id),
+                                          trait_id,
                                           self.cur_scope);
                     },
                     None => ()
                 }
             },
-            _ => self.visit_ty(&*typ),
+            _ => {
+                // Less useful case, impl for a compound type.
+                self.visit_ty(&*typ);
+
+                let sub_span = self.span.sub_span_for_type_name(typ.span);
+                self.fmt.impl_str(typ.span,
+                                  sub_span,
+                                  item.id,
+                                  None,
+                                  trait_id,
+                                  self.cur_scope);
+            }
         }
 
         match *trait_ref {
-            Some(ref trait_ref) => self.process_trait_ref(trait_ref, Some(item.id)),
+            Some(ref trait_ref) => self.process_trait_ref(trait_ref),
             None => (),
         }
 
@@ -767,7 +772,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                     span: Span,
                     path: &ast::Path,
                     ref_kind: Option<recorder::Row>) {
-        if generated_code(path.span) {
+        if generated_code(span) {
             return
         }
 
@@ -1076,7 +1081,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
         for param in generics.ty_params.iter() {
             for bound in param.bounds.iter() {
                 if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
-                    self.process_trait_ref(&trait_ref.trait_ref, None);
+                    self.process_trait_ref(&trait_ref.trait_ref);
                 }
             }
             if let Some(ref ty) = param.default {
@@ -1307,9 +1312,15 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                 visit::walk_expr(self, ex);
             },
             ast::ExprPath(ref path) => {
-                self.process_path(ex.id, ex.span, path, None);
+                self.process_path(ex.id, path.span, path, None);
                 visit::walk_path(self, path);
             }
+            ast::ExprQPath(ref qpath) => {
+                let mut path = qpath.trait_ref.path.clone();
+                path.segments.push(qpath.item_path.clone());
+                self.process_path(ex.id, ex.span, &path, None);
+                visit::walk_qpath(self, ex.span, &**qpath);
+            }
             ast::ExprStruct(ref path, ref fields, ref base) =>
                 self.process_struct_lit(ex, path, fields, base),
             ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
@@ -1439,7 +1450,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                                           "")
                 }
                 def::DefVariant(..) => {
-                    paths_to_process.push((id, p.span, p.clone(), Some(ref_kind)))
+                    paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
                 // FIXME(nrc) what are these doing here?
                 def::DefStatic(_, _) => {}
@@ -1448,8 +1459,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                             *def)
             }
         }
-        for &(id, span, ref path, ref_kind) in paths_to_process.iter() {
-            self.process_path(id, span, path, ref_kind);
+        for &(id, ref path, ref_kind) in paths_to_process.iter() {
+            self.process_path(id, path.span, path, ref_kind);
         }
         self.collecting = false;
         self.collected_paths.clear();
@@ -1505,7 +1516,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
 pub fn process_crate(sess: &Session,
                      krate: &ast::Crate,
                      analysis: &ty::CrateAnalysis,
-                     odir: &Option<Path>) {
+                     odir: Option<&Path>) {
     if generated_code(krate.span) {
         return;
     }
@@ -1524,8 +1535,8 @@ pub fn process_crate(sess: &Session,
     // find a path to dump our data to
     let mut root_path = match os::getenv("DXR_RUST_TEMP_FOLDER") {
         Some(val) => Path::new(val),
-        None => match *odir {
-            Some(ref val) => val.join("dxr"),
+        None => match odir {
+            Some(val) => val.join("dxr"),
             None => Path::new("dxr-temp"),
         },
     };
diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs
index 23598751c08..eefaeca8306 100644
--- a/src/librustc_trans/save/recorder.rs
+++ b/src/librustc_trans/save/recorder.rs
@@ -19,6 +19,8 @@ use syntax::ast;
 use syntax::ast::{NodeId,DefId};
 use syntax::codemap::*;
 
+const ZERO_DEF_ID: DefId = DefId { node: 0, krate: 0 };
+
 pub struct Recorder {
     // output file
     pub out: Box<Writer+'static>,
@@ -121,7 +123,9 @@ impl<'a> FmtStrs<'a> {
             MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true),
             Struct => ("struct", vec!("id","ctor_id","qualname","scopeid","value"), true, true),
             Trait => ("trait", vec!("id","qualname","scopeid","value"), true, true),
-            Impl => ("impl", vec!("id","refid","refidcrate","scopeid"), true, true),
+            Impl => ("impl",
+                     vec!("id","refid","refidcrate","traitid","traitidcrate","scopeid"),
+                     true, true),
             Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
             UseAlias => ("use_alias",
                          vec!("id","refid","refidcrate","name","scopeid"),
@@ -166,7 +170,7 @@ impl<'a> FmtStrs<'a> {
         let values = values.iter().map(|s| {
             // Never take more than 1020 chars
             if s.len() > 1020 {
-                &s[0..1020]
+                &s[..1020]
             } else {
                 &s[]
             }
@@ -444,12 +448,20 @@ impl<'a> FmtStrs<'a> {
                     span: Span,
                     sub_span: Option<Span>,
                     id: NodeId,
-                    ref_id: DefId,
+                    ref_id: Option<DefId>,
+                    trait_id: Option<DefId>,
                     scope_id: NodeId) {
+        let ref_id = ref_id.unwrap_or(ZERO_DEF_ID);
+        let trait_id = trait_id.unwrap_or(ZERO_DEF_ID);
         self.check_and_record(Impl,
                               span,
                               sub_span,
-                              svec!(id, ref_id.node, ref_id.krate, scope_id));
+                              svec!(id,
+                                    ref_id.node,
+                                    ref_id.krate,
+                                    trait_id.node,
+                                    trait_id.krate,
+                                    scope_id));
     }
 
     pub fn mod_str(&mut self,
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index fc19a582db2..be927503bad 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -201,7 +201,7 @@ use middle::pat_util::*;
 use trans::adt;
 use trans::base::*;
 use trans::build::{AddCase, And, BitCast, Br, CondBr, GEPi, InBoundsGEP, Load};
-use trans::build::{Mul, Not, Store, Sub, add_comment};
+use trans::build::{Not, Store, Sub, add_comment};
 use trans::build;
 use trans::callee;
 use trans::cleanup::{self, CleanupMethods};
@@ -471,7 +471,7 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // Collect all of the matches that can match against anything.
     enter_match(bcx, dm, m, col, val, |pats| {
         if pat_is_binding_or_wild(dm, &*pats[col]) {
-            let mut r = pats[0..col].to_vec();
+            let mut r = pats[..col].to_vec();
             r.push_all(&pats[(col + 1)..]);
             Some(r)
         } else {
@@ -630,8 +630,7 @@ fn bind_subslice_pat(bcx: Block,
     let vec_datum = match_datum(val, vec_ty);
     let (base, len) = vec_datum.get_vec_base_and_len(bcx);
 
-    let slice_byte_offset = Mul(bcx, vt.llunit_size, C_uint(bcx.ccx(), offset_left));
-    let slice_begin = tvec::pointer_add_byte(bcx, base, slice_byte_offset);
+    let slice_begin = InBoundsGEP(bcx, base, &[C_uint(bcx.ccx(), offset_left)]);
     let slice_len_offset = C_uint(bcx.ccx(), offset_left + offset_right);
     let slice_len = Sub(bcx, len, slice_len_offset);
     let slice_ty = ty::mk_slice(bcx.tcx(),
@@ -857,16 +856,9 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             bcx.fcx.schedule_lifetime_end(cs, binding_info.llmatch);
         }
 
-        debug!("binding {} to {}",
-               binding_info.id,
-               bcx.val_to_string(llval));
+        debug!("binding {} to {}", binding_info.id, bcx.val_to_string(llval));
         bcx.fcx.lllocals.borrow_mut().insert(binding_info.id, datum);
-
-        if bcx.sess().opts.debuginfo == FullDebugInfo {
-            debuginfo::create_match_binding_metadata(bcx,
-                                                     ident,
-                                                     binding_info);
-        }
+        debuginfo::create_match_binding_metadata(bcx, ident, binding_info);
     }
     bcx
 }
@@ -1235,7 +1227,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
 fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
     let (vid, field) = match discr.node {
-        ast::ExprPath(..) => match bcx.def(discr.id) {
+        ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) {
             def::DefLocal(vid) | def::DefUpvar(vid, _, _) => (vid, None),
             _ => return false
         },
diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs
index 9b6fa32405f..05abd3ff557 100644
--- a/src/librustc_trans/trans/asm.rs
+++ b/src/librustc_trans/trans/asm.rs
@@ -161,10 +161,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
 // Default per-arch clobbers
 // Basically what clang does
 
-#[cfg(any(target_arch = "arm",
-          target_arch = "aarch64",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 fn get_clobbers() -> String {
     "".to_string()
 }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 88ce36a710a..037f20ee4c5 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -44,7 +44,7 @@ use middle::subst;
 use middle::weak_lang_items;
 use middle::subst::{Subst, Substs};
 use middle::ty::{self, Ty, UnboxedClosureTyper};
-use session::config::{self, NoDebugInfo, FullDebugInfo};
+use session::config::{self, NoDebugInfo};
 use session::Session;
 use trans::_match;
 use trans::adt;
@@ -248,9 +248,8 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
 
     let f = decl_rust_fn(ccx, fn_ty, name);
 
-    csearch::get_item_attrs(&ccx.sess().cstore, did, |attrs| {
-        set_llvm_fn_attrs(ccx, &attrs[], f)
-    });
+    let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
+    set_llvm_fn_attrs(ccx, &attrs[], f);
 
     ccx.externs().borrow_mut().insert(name.to_string(), f);
     f
@@ -353,12 +352,11 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
         // don't do this then linker errors can be generated where the linker
         // complains that one object files has a thread local version of the
         // symbol and another one doesn't.
-        ty::each_attr(ccx.tcx(), did, |attr| {
+        for attr in ty::get_attrs(ccx.tcx(), did).iter() {
             if attr.check_name("thread_local") {
                 llvm::set_thread_local(c, true);
             }
-            true
-        });
+        }
         ccx.externs().borrow_mut().insert(name.to_string(), c);
         return c;
     }
@@ -546,15 +544,6 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
-// Structural comparison: a rather involved form of glue.
-pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
-    if cx.sess().opts.cg.save_temps {
-        let buf = CString::from_slice(s.as_bytes());
-        unsafe { llvm::LLVMSetValueName(v, buf.as_ptr()) }
-    }
-}
-
-
 // Used only for creating scalar comparison glue.
 #[derive(Copy)]
 pub enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
@@ -702,9 +691,8 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
         let mut cx = cx;
 
         for (i, &arg) in variant.args.iter().enumerate() {
-            cx = (*f)(cx,
-                   adt::trans_field_ptr(cx, repr, av, variant.disr_val, i),
-                   arg.subst(tcx, substs));
+            let arg = monomorphize::apply_param_substs(tcx, substs, &arg);
+            cx = f(cx, adt::trans_field_ptr(cx, repr, av, variant.disr_val, i), arg);
         }
         return cx;
     }
@@ -847,26 +835,24 @@ pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
     G: FnOnce(ValueRef, Type) -> ValueRef,
 {
     // Shifts may have any size int on the rhs
-    unsafe {
-        if ast_util::is_shift_binop(op) {
-            let mut rhs_llty = val_ty(rhs);
-            let mut lhs_llty = val_ty(lhs);
-            if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() }
-            if lhs_llty.kind() == Vector { lhs_llty = lhs_llty.element_type() }
-            let rhs_sz = llvm::LLVMGetIntTypeWidth(rhs_llty.to_ref());
-            let lhs_sz = llvm::LLVMGetIntTypeWidth(lhs_llty.to_ref());
-            if lhs_sz < rhs_sz {
-                trunc(rhs, lhs_llty)
-            } else if lhs_sz > rhs_sz {
-                // FIXME (#1877: If shifting by negative
-                // values becomes not undefined then this is wrong.
-                zext(rhs, lhs_llty)
-            } else {
-                rhs
-            }
+    if ast_util::is_shift_binop(op) {
+        let mut rhs_llty = val_ty(rhs);
+        let mut lhs_llty = val_ty(lhs);
+        if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() }
+        if lhs_llty.kind() == Vector { lhs_llty = lhs_llty.element_type() }
+        let rhs_sz = rhs_llty.int_width();
+        let lhs_sz = lhs_llty.int_width();
+        if lhs_sz < rhs_sz {
+            trunc(rhs, lhs_llty)
+        } else if lhs_sz > rhs_sz {
+            // FIXME (#1877: If shifting by negative
+            // values becomes not undefined then this is wrong.
+            zext(rhs, lhs_llty)
         } else {
             rhs
         }
+    } else {
+        rhs
     }
 }
 
@@ -1054,6 +1040,11 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         C_undef(type_of::type_of(cx.ccx(), t))
     } else if ty::type_is_bool(t) {
         Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, llvm::False), Type::i1(cx.ccx()))
+    } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
+        // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
+        // for this leads to bad optimizations, so its arg type is an appropriately sized integer
+        // and we have to convert it
+        Load(cx, BitCast(cx, ptr, type_of::arg_type_of(cx.ccx(), t).ptr_to()))
     } else if ty::type_is_char(t) {
         // a char is a Unicode codepoint, and so takes values from 0
         // to 0x10FFFF inclusive only.
@@ -1065,9 +1056,14 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
 
 /// Helper for storing values in memory. Does the necessary conversion if the in-memory type
 /// differs from the type used for SSA values.
-pub fn store_ty(cx: Block, v: ValueRef, dst: ValueRef, t: Ty) {
+pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
     if ty::type_is_bool(t) {
         Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst);
+    } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
+        // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
+        // for this leads to bad optimizations, so its arg type is an appropriately sized integer
+        // and we have to convert it
+        Store(cx, v, BitCast(cx, dst, type_of::arg_type_of(cx.ccx(), t).ptr_to()));
     } else {
         Store(cx, v, dst);
     };
@@ -1619,9 +1615,8 @@ fn create_datums_for_fn_args_under_call_abi<'blk, 'tcx>(
     result
 }
 
-fn copy_args_to_allocas<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
+fn copy_args_to_allocas<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     arg_scope: cleanup::CustomScopeIndex,
-                                    bcx: Block<'blk, 'tcx>,
                                     args: &[ast::Arg],
                                     arg_datums: Vec<RvalueDatum<'tcx>>)
                                     -> Block<'blk, 'tcx> {
@@ -1642,10 +1637,7 @@ fn copy_args_to_allocas<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
         // the event it's not truly needed.
 
         bcx = _match::store_arg(bcx, &*args[i].pat, arg_datum, arg_scope_id);
-
-        if fcx.ccx.sess().opts.debuginfo == FullDebugInfo {
-            debuginfo::create_argument_metadata(bcx, &args[i]);
-        }
+        debuginfo::create_argument_metadata(bcx, &args[i]);
     }
 
     bcx
@@ -1695,9 +1687,7 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>(
                                 tuple_element_datum,
                                 arg_scope_id);
 
-        if bcx.fcx.ccx.sess().opts.debuginfo == FullDebugInfo {
-            debuginfo::create_argument_metadata(bcx, &args[j]);
-        }
+        debuginfo::create_argument_metadata(bcx, &args[j]);
     }
 
     bcx
@@ -1870,9 +1860,8 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     bcx = match closure_env.kind {
         closure::NotClosure | closure::BoxedClosure(..) => {
-            copy_args_to_allocas(&fcx,
+            copy_args_to_allocas(bcx,
                                  arg_scope,
-                                 bcx,
                                  &decl.inputs[],
                                  arg_datums)
         }
diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs
index b80088e4690..75194e3d21f 100644
--- a/src/librustc_trans/trans/builder.rs
+++ b/src/librustc_trans/trans/builder.rs
@@ -552,7 +552,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             for (small_vec_e, &ix) in small_vec.iter_mut().zip(ixs.iter()) {
                 *small_vec_e = C_i32(self.ccx, ix as i32);
             }
-            self.inbounds_gep(base, &small_vec[0..ixs.len()])
+            self.inbounds_gep(base, &small_vec[..ixs.len()])
         } else {
             let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
             self.count_insn("gepi");
diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs
index f7ffbb95feb..7abcdd07cc5 100644
--- a/src/librustc_trans/trans/cabi.rs
+++ b/src/librustc_trans/trans/cabi.rs
@@ -18,6 +18,7 @@ use trans::cabi_x86_64;
 use trans::cabi_x86_win64;
 use trans::cabi_arm;
 use trans::cabi_aarch64;
+use trans::cabi_powerpc;
 use trans::cabi_mips;
 use trans::type_::Type;
 
@@ -125,6 +126,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
             cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor)
         },
         "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
+        "powerpc" => cabi_powerpc::compute_abi_info(ccx, atys, rty, ret_def),
         a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
                               []),
     }
diff --git a/src/librustc_trans/trans/cabi_aarch64.rs b/src/librustc_trans/trans/cabi_aarch64.rs
index 66308503b81..0d8ef9e2fc9 100644
--- a/src/librustc_trans/trans/cabi_aarch64.rs
+++ b/src/librustc_trans/trans/cabi_aarch64.rs
@@ -10,8 +10,7 @@
 
 #![allow(non_upper_case_globals)]
 
-use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
 use llvm::{StructRetAttribute, ZExtAttribute};
 use trans::cabi::{FnType, ArgType};
 use trans::context::CrateContext;
@@ -30,11 +29,7 @@ fn align(off: uint, ty: Type) -> uint {
 
 fn ty_align(ty: Type) -> uint {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as uint) + 7) / 8,
         Pointer => 8,
         Float => 4,
         Double => 8,
@@ -50,17 +45,18 @@ fn ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             ty_align(elt)
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            ty_align(elt) * len
+        }
         _ => panic!("ty_align: unhandled type")
     }
 }
 
 fn ty_size(ty: Type) -> uint {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as uint) + 7) / 8,
         Pointer => 8,
         Float => 4,
         Double => 8,
@@ -80,6 +76,12 @@ fn ty_size(ty: Type) -> uint {
             let eltsz = ty_size(elt);
             len * eltsz
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
         _ => panic!("ty_size: unhandled type")
     }
 }
@@ -137,7 +139,8 @@ fn is_reg_ty(ty: Type) -> bool {
         Integer
         | Pointer
         | Float
-        | Double => true,
+        | Double
+        | Vector => true,
         _ => false
     }
 }
diff --git a/src/librustc_trans/trans/cabi_arm.rs b/src/librustc_trans/trans/cabi_arm.rs
index 830771d7397..7d1a8ab1452 100644
--- a/src/librustc_trans/trans/cabi_arm.rs
+++ b/src/librustc_trans/trans/cabi_arm.rs
@@ -10,8 +10,7 @@
 
 #![allow(non_upper_case_globals)]
 
-use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
 use llvm::{StructRetAttribute, ZExtAttribute};
 use trans::cabi::{FnType, ArgType};
 use trans::context::CrateContext;
@@ -37,11 +36,7 @@ fn align(off: uint, ty: Type, align_fn: TyAlignFn) -> uint {
 
 fn general_ty_align(ty: Type) -> uint {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as uint) + 7) / 8,
         Pointer => 4,
         Float => 4,
         Double => 8,
@@ -57,6 +52,11 @@ fn general_ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             general_ty_align(elt)
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            general_ty_align(elt) * len
+        }
         _ => panic!("ty_align: unhandled type")
     }
 }
@@ -70,11 +70,7 @@ fn general_ty_align(ty: Type) -> uint {
 //    /iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
 fn ios_ty_align(ty: Type) -> uint {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                cmp::min(4, ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8)
-            }
-        }
+        Integer => cmp::min(4, ((ty.int_width() as uint) + 7) / 8),
         Pointer => 4,
         Float => 4,
         Double => 4,
@@ -90,17 +86,18 @@ fn ios_ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             ios_ty_align(elt)
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            ios_ty_align(elt) * len
+        }
         _ => panic!("ty_align: unhandled type")
     }
 }
 
 fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as uint) + 7) / 8,
         Pointer => 4,
         Float => 4,
         Double => 8,
@@ -123,6 +120,12 @@ fn ty_size(ty: Type, align_fn: TyAlignFn) -> uint {
             let eltsz = ty_size(elt, align_fn);
             len * eltsz
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt, align_fn);
+            len * eltsz
+        }
         _ => panic!("ty_size: unhandled type")
     }
 }
@@ -166,7 +169,8 @@ fn is_reg_ty(ty: Type) -> bool {
         Integer
         | Pointer
         | Float
-        | Double => true,
+        | Double
+        | Vector => true,
         _ => false
     }
 }
diff --git a/src/librustc_trans/trans/cabi_mips.rs b/src/librustc_trans/trans/cabi_mips.rs
index 4dfe8daf339..776be8855cb 100644
--- a/src/librustc_trans/trans/cabi_mips.rs
+++ b/src/librustc_trans/trans/cabi_mips.rs
@@ -13,7 +13,7 @@
 use libc::c_uint;
 use std::cmp;
 use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
 use llvm::{StructRetAttribute, ZExtAttribute};
 use trans::cabi::{ArgType, FnType};
 use trans::context::CrateContext;
@@ -30,11 +30,7 @@ fn align(off: uint, ty: Type) -> uint {
 
 fn ty_align(ty: Type) -> uint {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as uint) + 7) / 8,
         Pointer => 4,
         Float => 4,
         Double => 8,
@@ -50,17 +46,18 @@ fn ty_align(ty: Type) -> uint {
             let elt = ty.element_type();
             ty_align(elt)
         }
-        _ => panic!("ty_size: unhandled type")
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            ty_align(elt) * len
+        }
+        _ => panic!("ty_align: unhandled type")
     }
 }
 
 fn ty_size(ty: Type) -> uint {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as uint) + 7) / 8,
         Pointer => 4,
         Float => 4,
         Double => 8,
@@ -80,6 +77,12 @@ fn ty_size(ty: Type) -> uint {
             let eltsz = ty_size(elt);
             len * eltsz
         }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
         _ => panic!("ty_size: unhandled type")
     }
 }
@@ -120,7 +123,8 @@ fn is_reg_ty(ty: Type) -> bool {
         Integer
         | Pointer
         | Float
-        | Double => true,
+        | Double
+        | Vector => true,
         _ => false
     };
 }
diff --git a/src/librustc_trans/trans/cabi_powerpc.rs b/src/librustc_trans/trans/cabi_powerpc.rs
new file mode 100644
index 00000000000..9fc67e19662
--- /dev/null
+++ b/src/librustc_trans/trans/cabi_powerpc.rs
@@ -0,0 +1,183 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use libc::c_uint;
+use llvm;
+use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{StructRetAttribute, ZExtAttribute};
+use trans::cabi::{FnType, ArgType};
+use trans::context::CrateContext;
+use trans::type_::Type;
+
+use std::cmp;
+
+fn align_up_to(off: uint, a: uint) -> uint {
+    return (off + a - 1u) / a * a;
+}
+
+fn align(off: uint, ty: Type) -> uint {
+    let a = ty_align(ty);
+    return align_up_to(off, a);
+}
+
+fn ty_align(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
+            }
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+          if ty.is_packed() {
+            1
+          } else {
+            let str_tys = ty.field_types();
+            str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
+          }
+        }
+        Array => {
+            let elt = ty.element_type();
+            ty_align(elt)
+        }
+        _ => panic!("ty_size: unhandled type")
+    }
+}
+
+fn ty_size(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
+            }
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+            if ty.is_packed() {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(0, |s, t| s + ty_size(*t))
+            } else {
+                let str_tys = ty.field_types();
+                let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
+                align(size, ty)
+            }
+        }
+        Array => {
+            let len = ty.array_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
+        _ => panic!("ty_size: unhandled type")
+    }
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        ArgType::direct(ty, None, None, attr)
+    } else {
+        ArgType::indirect(ty, Some(StructRetAttribute))
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType {
+    let orig_offset = *offset;
+    let size = ty_size(ty) * 8;
+    let mut align = ty_align(ty);
+
+    align = cmp::min(cmp::max(align, 4), 8);
+    *offset = align_up_to(*offset, align);
+    *offset += align_up_to(size, align * 8) / 8;
+
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        ArgType::direct(ty, None, None, attr)
+    } else {
+        ArgType::direct(
+            ty,
+            Some(struct_ty(ccx, ty)),
+            padding_ty(ccx, align, orig_offset),
+            None
+        )
+    }
+}
+
+fn is_reg_ty(ty: Type) -> bool {
+    return match ty.kind() {
+        Integer
+        | Pointer
+        | Float
+        | Double => true,
+        _ => false
+    };
+}
+
+fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option<Type> {
+    if ((align - 1 ) & offset) > 0 {
+        Some(Type::i32(ccx))
+    } else {
+        None
+    }
+}
+
+fn coerce_to_int(ccx: &CrateContext, size: uint) -> Vec<Type> {
+    let int_ty = Type::i32(ccx);
+    let mut args = Vec::new();
+
+    let mut n = size / 32;
+    while n > 0 {
+        args.push(int_ty);
+        n -= 1;
+    }
+
+    let r = size % 32;
+    if r > 0 {
+        unsafe {
+            args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx(), r as c_uint)));
+        }
+    }
+
+    args
+}
+
+fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
+    let size = ty_size(ty) * 8;
+    Type::struct_(ccx, coerce_to_int(ccx, size).as_slice(), false)
+}
+
+pub fn compute_abi_info(ccx: &CrateContext,
+                        atys: &[Type],
+                        rty: Type,
+                        ret_def: bool) -> FnType {
+    let ret_ty = if ret_def {
+        classify_ret_ty(ccx, rty)
+    } else {
+        ArgType::direct(Type::void(ccx), None, None, None)
+    };
+
+    let sret = ret_ty.is_indirect();
+    let mut arg_tys = Vec::new();
+    let mut offset = if sret { 4 } else { 0 };
+
+    for aty in atys.iter() {
+        let ty = classify_arg_ty(ccx, *aty, &mut offset);
+        arg_tys.push(ty);
+    };
+
+    return FnType {
+        arg_tys: arg_tys,
+        ret_ty: ret_ty,
+    };
+}
diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs
index 86190b1e566..980a70256e9 100644
--- a/src/librustc_trans/trans/cabi_x86_64.rs
+++ b/src/librustc_trans/trans/cabi_x86_64.rs
@@ -14,9 +14,8 @@
 #![allow(non_upper_case_globals)]
 use self::RegClass::*;
 
-use llvm;
 use llvm::{Integer, Pointer, Float, Double};
-use llvm::{Struct, Array, Attribute};
+use llvm::{Struct, Array, Attribute, Vector};
 use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
 use trans::cabi::{ArgType, FnType};
 use trans::context::CrateContext;
@@ -33,7 +32,8 @@ enum RegClass {
     SSEFv,
     SSEDs,
     SSEDv,
-    SSEInt,
+    SSEInt(/* bitwidth */ u64),
+    /// Data that can appear in the upper half of an SSE register.
     SSEUp,
     X87,
     X87Up,
@@ -57,7 +57,7 @@ impl TypeMethods for Type {
 impl RegClass {
     fn is_sse(&self) -> bool {
         match *self {
-            SSEFs | SSEFv | SSEDs | SSEDv => true,
+            SSEFs | SSEFv | SSEDs | SSEDv | SSEInt(_) => true,
             _ => false
         }
     }
@@ -93,11 +93,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
 
     fn ty_align(ty: Type) -> uint {
         match ty.kind() {
-            Integer => {
-                unsafe {
-                    ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-                }
-            }
+            Integer => ((ty.int_width() as uint) + 7) / 8,
             Pointer => 8,
             Float => 4,
             Double => 8,
@@ -113,17 +109,18 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
                 let elt = ty.element_type();
                 ty_align(elt)
             }
-            _ => panic!("ty_size: unhandled type")
+            Vector => {
+                let len = ty.vector_length();
+                let elt = ty.element_type();
+                ty_align(elt) * len
+            }
+            _ => panic!("ty_align: unhandled type")
         }
     }
 
     fn ty_size(ty: Type) -> uint {
         match ty.kind() {
-            Integer => {
-                unsafe {
-                    ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
-                }
-            }
+            Integer => (ty.int_width() as uint + 7) / 8,
             Pointer => 8,
             Float => 4,
             Double => 8,
@@ -142,6 +139,13 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
                 let eltsz = ty_size(elt);
                 len * eltsz
             }
+            Vector => {
+                let len = ty.vector_length();
+                let elt = ty.element_type();
+                let eltsz = ty_size(elt);
+                len * eltsz
+            }
+
             _ => panic!("ty_size: unhandled type")
         }
     }
@@ -155,26 +159,34 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
     fn unify(cls: &mut [RegClass],
              i: uint,
              newv: RegClass) {
-        if cls[i] == newv {
-            return;
-        } else if cls[i] == NoClass {
-            cls[i] = newv;
-        } else if newv == NoClass {
-            return;
-        } else if cls[i] == Memory || newv == Memory {
-            cls[i] = Memory;
-        } else if cls[i] == Int || newv == Int {
-            cls[i] = Int;
-        } else if cls[i] == X87 ||
-                  cls[i] == X87Up ||
-                  cls[i] == ComplexX87 ||
-                  newv == X87 ||
-                  newv == X87Up ||
-                  newv == ComplexX87 {
-            cls[i] = Memory;
-        } else {
-            cls[i] = newv;
-        }
+        if cls[i] == newv { return }
+
+        let to_write = match (cls[i], newv) {
+            (NoClass,     _) => newv,
+            (_,           NoClass) => return,
+
+            (Memory,      _) |
+            (_,           Memory) => Memory,
+
+            (Int,         _) |
+            (_,           Int) => Int,
+
+            (X87,         _) |
+            (X87Up,       _) |
+            (ComplexX87,  _) |
+            (_,           X87) |
+            (_,           X87Up) |
+            (_,           ComplexX87) => Memory,
+
+            (SSEFv,       SSEUp) |
+            (SSEFs,       SSEUp) |
+            (SSEDv,       SSEUp) |
+            (SSEDs,       SSEUp) |
+            (SSEInt(_),   SSEUp) => return,
+
+            (_,           _) => newv
+        };
+        cls[i] = to_write;
     }
 
     fn classify_struct(tys: &[Type],
@@ -237,6 +249,27 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
                     i += 1u;
                 }
             }
+            Vector => {
+                let len = ty.vector_length();
+                let elt = ty.element_type();
+                let eltsz = ty_size(elt);
+                let mut reg = match elt.kind() {
+                    Integer => SSEInt(elt.int_width()),
+                    Float => SSEFv,
+                    Double => SSEDv,
+                    _ => panic!("classify: unhandled vector element type")
+                };
+
+                let mut i = 0u;
+                while i < len {
+                    unify(cls, ix + (off + i * eltsz) / 8, reg);
+
+                    // everything after the first one is the upper
+                    // half of a register.
+                    reg = SSEUp;
+                    i += 1u;
+                }
+            }
             _ => panic!("classify: unhandled type")
         }
     }
@@ -245,7 +278,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
         let mut i = 0u;
         let ty_kind = ty.kind();
         let e = cls.len();
-        if cls.len() > 2u && (ty_kind == Struct || ty_kind == Array) {
+        if cls.len() > 2u && (ty_kind == Struct || ty_kind == Array || ty_kind == Vector) {
             if cls[i].is_sse() {
                 i += 1u;
                 while i < e {
@@ -317,9 +350,19 @@ fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
             Int => {
                 tys.push(Type::i64(ccx));
             }
-            SSEFv => {
+            SSEFv | SSEDv | SSEInt(_) => {
+                let (elts_per_word, elt_ty) = match cls[i] {
+                    SSEFv => (2, Type::f32(ccx)),
+                    SSEDv => (1, Type::f64(ccx)),
+                    SSEInt(bits) => {
+                        assert!(bits == 8 || bits == 16 || bits == 32 || bits == 64,
+                                "llreg_ty: unsupported SSEInt width {}", bits);
+                        (64 / bits, Type::ix(ccx, bits))
+                    }
+                    _ => unreachable!(),
+                };
                 let vec_len = llvec_len(&cls[(i + 1u)..]);
-                let vec_ty = Type::vector(&Type::f32(ccx), (vec_len * 2u) as u64);
+                let vec_ty = Type::vector(&elt_ty, vec_len as u64 * elts_per_word);
                 tys.push(vec_ty);
                 i += vec_len;
                 continue;
@@ -334,7 +377,12 @@ fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
         }
         i += 1u;
     }
-    return Type::struct_(ccx, tys.as_slice(), false);
+    if tys.len() == 1 && tys[0].kind() == Vector {
+        // if the type contains only a vector, pass it as that vector.
+        tys[0]
+    } else {
+        Type::struct_(ccx, tys.as_slice(), false)
+    }
 }
 
 pub fn compute_abi_info(ccx: &CrateContext,
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 6196f9e5eab..11006f37531 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -91,8 +91,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
     debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
 
     // pick out special kinds of expressions that can be called:
-    if let ast::ExprPath(_) = expr.node {
-        return trans_def(bcx, bcx.def(expr.id), expr);
+    match expr.node {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
+            return trans_def(bcx, bcx.def(expr.id), expr);
+        }
+        _ => {}
     }
 
     // any other expressions are closures:
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 3afd33d324d..3eee4637de1 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -217,15 +217,15 @@ pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
     ty::type_contents(cx, ty).needs_drop(cx)
 }
 
-fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                   ty: Ty<'tcx>) -> bool {
+fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.sty {
         ty::ty_struct(def_id, substs) => {
-            let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
-            fields.len() == 1 &&
-                fields[0].name ==
-                    token::special_idents::unnamed_field.name &&
-                type_is_immediate(ccx, fields[0].mt.ty)
+            let fields = ty::lookup_struct_fields(ccx.tcx(), def_id);
+            fields.len() == 1 && {
+                let ty = ty::lookup_field_type(ccx.tcx(), def_id, fields[0].id, substs);
+                let ty = monomorphize::normalize_associated_type(ccx.tcx(), &ty);
+                type_is_immediate(ccx, ty)
+            }
         }
         _ => false
     }
@@ -247,7 +247,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
         return false;
     }
     match ty.sty {
-        ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) |
+        ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) | ty::ty_vec(_, Some(_)) |
         ty::ty_unboxed_closure(..) => {
             let llty = sizing_type_of(ccx, ty);
             llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type())
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 00b97286de3..29cf9f72ef8 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -600,7 +600,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
                 C_array(llunitty, &vs[])
             }
           }
-          ast::ExprPath(_) => {
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
             let def = cx.tcx().def_map.borrow()[e.id];
             match def {
                 def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs
index adf302501cd..5dc939dc202 100644
--- a/src/librustc_trans/trans/controlflow.rs
+++ b/src/librustc_trans/trans/controlflow.rs
@@ -28,7 +28,6 @@ use trans::type_::Type;
 use trans;
 use middle::ty;
 use middle::ty::MethodCall;
-use session::config::FullDebugInfo;
 use util::ppaux::Repr;
 use util::ppaux;
 
@@ -66,10 +65,7 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
             match d.node {
                 ast::DeclLocal(ref local) => {
                     bcx = init_local(bcx, &**local);
-                    if cx.sess().opts.debuginfo == FullDebugInfo {
-                        trans::debuginfo::create_local_var_metadata(bcx,
-                                                                    &**local);
-                    }
+                    debuginfo::create_local_var_metadata(bcx, &**local);
                 }
                 // Inner items are visited by `trans_item`/`trans_meth`.
                 ast::DeclItem(_) => {},
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index 2f58baab7fc..a03a5090c05 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -854,7 +854,9 @@ pub fn create_global_var_metadata(cx: &CrateContext,
 /// local in `bcx.fcx.lllocals`.
 /// Adds the created metadata nodes directly to the crate's IR.
 pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
-    if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo  {
         return;
     }
 
@@ -898,7 +900,9 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                 env_index: uint,
                                                 captured_by_ref: bool,
                                                 span: Span) {
-    if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo {
         return;
     }
 
@@ -962,7 +966,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let variable_access = IndirectVariable {
         alloca: env_pointer,
-        address_operations: &address_operations[0..address_op_count]
+        address_operations: &address_operations[..address_op_count]
     };
 
     declare_local(bcx,
@@ -981,7 +985,9 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                  variable_ident: ast::Ident,
                                                  binding: BindingInfo<'tcx>) {
-    if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo {
         return;
     }
 
@@ -1021,7 +1027,9 @@ pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// argument in `bcx.fcx.lllocals`.
 /// Adds the created metadata nodes directly to the crate's IR.
 pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
-    if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo {
         return;
     }
 
@@ -1075,7 +1083,9 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
 /// loop variable in `bcx.fcx.lllocals`.
 /// Adds the created metadata nodes directly to the crate's IR.
 pub fn create_for_loop_var_metadata(bcx: Block, pat: &ast::Pat) {
-    if bcx.unreachable.get() || fn_should_be_ignored(bcx.fcx) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo {
         return;
     }
 
@@ -3502,7 +3512,8 @@ fn create_scope_map(cx: &CrateContext,
             ast::ExprLit(_)   |
             ast::ExprBreak(_) |
             ast::ExprAgain(_) |
-            ast::ExprPath(_)  => {}
+            ast::ExprPath(_)  |
+            ast::ExprQPath(_) => {}
 
             ast::ExprCast(ref sub_exp, _)     |
             ast::ExprAddrOf(_, ref sub_exp)  |
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index ac50445be2f..11d1c7e6796 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -564,7 +564,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans(bcx, &**e)
         }
-        ast::ExprPath(_) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             trans_def(bcx, expr, bcx.def(expr.id))
         }
         ast::ExprField(ref base, ident) => {
@@ -768,7 +768,6 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 tvec::vec_types(bcx,
                                 ty::sequence_element_type(bcx.tcx(),
                                                           base_datum.ty));
-            base::maybe_name_value(bcx.ccx(), vt.llunit_size, "unit_sz");
 
             let (base, len) = base_datum.get_vec_base_and_len(bcx);
 
@@ -997,7 +996,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans_into(bcx, &**e, dest)
         }
-        ast::ExprPath(_) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
         }
         ast::ExprIf(ref cond, ref thn, ref els) => {
@@ -1906,18 +1905,16 @@ fn int_cast(bcx: Block,
             signed: bool)
             -> ValueRef {
     let _icx = push_ctxt("int_cast");
-    unsafe {
-        let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype.to_ref());
-        let dstsz = llvm::LLVMGetIntTypeWidth(lldsttype.to_ref());
-        return if dstsz == srcsz {
-            BitCast(bcx, llsrc, lldsttype)
-        } else if srcsz > dstsz {
-            TruncOrBitCast(bcx, llsrc, lldsttype)
-        } else if signed {
-            SExtOrBitCast(bcx, llsrc, lldsttype)
-        } else {
-            ZExtOrBitCast(bcx, llsrc, lldsttype)
-        };
+    let srcsz = llsrctype.int_width();
+    let dstsz = lldsttype.int_width();
+    return if dstsz == srcsz {
+        BitCast(bcx, llsrc, lldsttype)
+    } else if srcsz > dstsz {
+        TruncOrBitCast(bcx, llsrc, lldsttype)
+    } else if signed {
+        SExtOrBitCast(bcx, llsrc, lldsttype)
+    } else {
+        ZExtOrBitCast(bcx, llsrc, lldsttype)
     }
 }
 
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 3dfb36c854b..abb961d87de 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -36,6 +36,7 @@ use syntax::parse::token::{InternedString, special_idents};
 use syntax::parse::token;
 use syntax::{ast};
 use syntax::{attr, ast_map};
+use syntax::print::pprust;
 use util::ppaux::Repr;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -426,16 +427,47 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     return bcx;
 }
 
+// feature gate SIMD types in FFI, since I (huonw) am not sure the
+// ABIs are handled at all correctly.
+fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
+    if !tcx.sess.features.borrow().simd_ffi {
+        let check = |&: ast_ty: &ast::Ty, ty: ty::Ty| {
+            if ty::type_is_simd(tcx, ty) {
+                tcx.sess.span_err(ast_ty.span,
+                              &format!("use of SIMD type `{}` in FFI is highly experimental and \
+                                        may result in invalid code",
+                                       pprust::ty_to_string(ast_ty))[]);
+                tcx.sess.span_help(ast_ty.span,
+                                   "add #![feature(simd_ffi)] to the crate attributes to enable");
+            }
+        };
+        let sig = &ty.sig.0;
+        for (input, ty) in decl.inputs.iter().zip(sig.inputs.iter()) {
+            check(&*input.ty, *ty)
+        }
+        match decl.output {
+            ast::NoReturn(_) => {}
+            ast::Return(ref ty) => check(&**ty, sig.output.unwrap())
+        }
+    }
+}
+
 pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
     let _icx = push_ctxt("foreign::trans_foreign_mod");
     for foreign_item in foreign_mod.items.iter() {
         let lname = link_name(&**foreign_item);
 
-        if let ast::ForeignItemFn(..) = foreign_item.node {
+        if let ast::ForeignItemFn(ref decl, _) = foreign_item.node {
             match foreign_mod.abi {
                 Rust | RustIntrinsic => {}
                 abi => {
                     let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
+                    match ty.sty {
+                        ty::ty_bare_fn(_, bft) => gate_simd_ffi(ccx.tcx(), &**decl, bft),
+                        _ => ccx.tcx().sess.span_bug(foreign_item.span,
+                                                     "foreign fn's sty isn't a bare_fn_ty?")
+                    }
+
                     register_foreign_item_fn(ccx, abi, ty,
                                              &lname.get()[]);
                     // Unlike for other items, we shouldn't call
@@ -736,6 +768,13 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 if ty::type_is_bool(rust_ty) {
                     let tmp = builder.load_range_assert(llforeign_arg, 0, 2, llvm::False);
                     builder.trunc(tmp, Type::i1(ccx))
+                } else if type_of::type_of(ccx, rust_ty).is_aggregate() {
+                    // We want to pass small aggregates as immediate values, but using an aggregate
+                    // LLVM type for this leads to bad optimizations, so its arg type is an
+                    // appropriately sized integer and we have to convert it
+                    let tmp = builder.bitcast(llforeign_arg,
+                                              type_of::arg_type_of(ccx, rust_ty).ptr_to());
+                    builder.load(tmp)
                 } else {
                     builder.load(llforeign_arg)
                 }
@@ -834,10 +873,10 @@ fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                fn_sig: &ty::FnSig<'tcx>,
                                arg_tys: &[Ty<'tcx>])
                                -> LlvmSignature {
-    let llarg_tys = arg_tys.iter().map(|&arg| arg_type_of(ccx, arg)).collect();
+    let llarg_tys = arg_tys.iter().map(|&arg| foreign_arg_type_of(ccx, arg)).collect();
     let (llret_ty, ret_def) = match fn_sig.output {
         ty::FnConverging(ret_ty) =>
-            (type_of::arg_type_of(ccx, ret_ty), !return_type_is_void(ccx, ret_ty)),
+            (type_of::foreign_arg_type_of(ccx, ret_ty), !return_type_is_void(ccx, ret_ty)),
         ty::FnDiverging =>
             (Type::nil(ccx), false)
     };
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index 2219cd59263..d3f3f34b76b 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -138,7 +138,7 @@ pub fn drop_ty_immediate<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                      -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("drop_ty_immediate");
     let vp = alloca(bcx, type_of(bcx.ccx(), t), "");
-    Store(bcx, v, vp);
+    store_ty(bcx, v, vp, t);
     drop_ty(bcx, vp, t, source_location)
 }
 
@@ -346,12 +346,14 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info:
             let align_ptr = GEPi(bcx, info, &[2u]);
             (Load(bcx, size_ptr), Load(bcx, align_ptr))
         }
-        ty::ty_vec(unit_ty, None) => {
-            // The info in this case is the length of the vec, so the size is that
+        ty::ty_vec(_, None) | ty::ty_str => {
+            let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
+            // The info in this case is the length of the str, so the size is that
             // times the unit size.
             let llunit_ty = sizing_type_of(bcx.ccx(), unit_ty);
+            let unit_align = llalign_of_min(bcx.ccx(), llunit_ty);
             let unit_size = llsize_of_alloc(bcx.ccx(), llunit_ty);
-            (Mul(bcx, info, C_uint(bcx.ccx(), unit_size)), C_uint(bcx.ccx(), 8u))
+            (Mul(bcx, info, C_uint(bcx.ccx(), unit_size)), C_uint(bcx.ccx(), unit_align))
         }
         _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}",
                                     bcx.ty_to_string(t))[])
@@ -456,8 +458,11 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
                  &[PointerCast(bcx, Load(bcx, lluniquevalue), Type::i8p(bcx.ccx()))],
                  None);
             bcx
-        }
-        ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false),
+        },
+        ty::ty_vec(_, None) | ty::ty_str => {
+            let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
+            tvec::make_drop_glue_unboxed(bcx, v0, unit_ty, false)
+        },
         _ => {
             assert!(type_is_sized(bcx.tcx(), t));
             if type_needs_drop(bcx.tcx(), t) &&
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index b22c7f763f0..91c7409182d 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -357,11 +357,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 &ccx.link_meta().crate_hash);
             // NB: This needs to be kept in lockstep with the TypeId struct in
             //     the intrinsic module
-            C_named_struct(llret_ty, &[C_u64(ccx, hash)])
+            C_u64(ccx, hash)
         }
         (_, "init") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
-            let lltp_ty = type_of::type_of(ccx, tp_ty);
+            let lltp_ty = type_of::arg_type_of(ccx, tp_ty);
             if return_type_is_void(ccx, tp_ty) {
                 C_nil(ccx)
             } else {
@@ -686,6 +686,11 @@ fn with_overflow_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, name: &'static st
     let ret = C_undef(type_of::type_of(bcx.ccx(), t));
     let ret = InsertValue(bcx, ret, result, 0);
     let ret = InsertValue(bcx, ret, overflow, 1);
-
-    ret
+    if type_is_immediate(bcx.ccx(), t) {
+        let tmp = alloc_ty(bcx, t, "tmp");
+        Store(bcx, ret, tmp);
+        load_ty(bcx, tmp, t)
+    } else {
+        ret
+    }
 }
diff --git a/src/librustc_trans/trans/machine.rs b/src/librustc_trans/trans/machine.rs
index 95d67cd54c1..1552ac0bea0 100644
--- a/src/librustc_trans/trans/machine.rs
+++ b/src/librustc_trans/trans/machine.rs
@@ -82,17 +82,6 @@ pub fn llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
     return C_uint(cx, llsize_of_alloc(cx, ty));
 }
 
-// Returns the "default" size of t (see above), or 1 if the size would
-// be zero.  This is important for things like vectors that expect
-// space to be consumed.
-pub fn nonzero_llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
-    if llbitsize_of_real(cx, ty) == 0 {
-        unsafe { llvm::LLVMConstInt(cx.int_type().to_ref(), 1, False) }
-    } else {
-        llsize_of(cx, ty)
-    }
-}
-
 // Returns the preferred alignment of the given type for the current target.
 // The preferred alignment may be larger than the alignment used when
 // packing the type into structs. This will be used for things like
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 7ac062108f3..0fb0dffe930 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -288,6 +288,17 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                      param_substs,
                                      callee_substs)
         }
+        traits::VtableObject(ref data) => {
+            let trait_item_def_ids =
+                ty::trait_item_def_ids(ccx.tcx(), trait_id);
+            let method_offset_in_trait =
+                trait_item_def_ids.iter()
+                                  .position(|item| item.def_id() == method_id)
+                                  .unwrap();
+            let (llfn, ty) =
+                trans_object_shim(ccx, data.object_ty, trait_id, method_offset_in_trait);
+            immediate_rvalue(llfn, ty)
+        }
         _ => {
             tcx.sess.bug(&format!("static call to invalid vtable: {}",
                                  vtbl.repr(tcx))[]);
@@ -371,7 +382,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             Callee { bcx: bcx, data: Fn(llfn) }
         }
         traits::VtableObject(ref data) => {
-            let llfn = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method);
+            let (llfn, _) = trans_object_shim(bcx.ccx(), data.object_ty, trait_id, n_method);
             Callee { bcx: bcx, data: Fn(llfn) }
         }
         traits::VtableBuiltin(..) |
@@ -540,7 +551,7 @@ pub fn trans_object_shim<'a, 'tcx>(
     object_ty: Ty<'tcx>,
     trait_id: ast::DefId,
     method_offset_in_trait: uint)
-    -> ValueRef
+    -> (ValueRef, Ty<'tcx>)
 {
     let _icx = push_ctxt("trans_object_shim");
     let tcx = ccx.tcx();
@@ -667,7 +678,7 @@ pub fn trans_object_shim<'a, 'tcx>(
 
     finish_fn(&fcx, bcx, sig.output);
 
-    llfn
+    (llfn, method_bare_fn_ty)
 }
 
 /// Creates a returns a dynamic vtable for the given type and vtable origin.
@@ -736,7 +747,7 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     format!("cannot get vtable for an object type: {}",
                             data.repr(bcx.tcx())).as_slice());
             }
-            traits::VtableParam => {
+            traits::VtableParam(..) => {
                 bcx.sess().bug(
                     &format!("resolved vtable for {} to bad vtable {} in trans",
                             trait_ref.repr(bcx.tcx()),
diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs
index 42134789546..91c6c9a13a3 100644
--- a/src/librustc_trans/trans/mod.rs
+++ b/src/librustc_trans/trans/mod.rs
@@ -45,6 +45,7 @@ mod cabi_x86_win64;
 mod cabi_arm;
 mod cabi_aarch64;
 mod cabi_mips;
+mod cabi_powerpc;
 mod foreign;
 mod intrinsic;
 mod debuginfo;
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 93076260349..f52e7c0ec94 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -274,6 +274,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ast_map::NodeArg(..) |
         ast_map::NodeBlock(..) |
         ast_map::NodePat(..) |
+        ast_map::NodeViewItem(..) |
         ast_map::NodeLocal(..) => {
             ccx.sess().bug(&format!("can't monomorphize a {:?}",
                                    map_node)[])
diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs
index e3288466aa7..f8b01ebf4cc 100644
--- a/src/librustc_trans/trans/tvec.rs
+++ b/src/librustc_trans/trans/tvec.rs
@@ -25,7 +25,7 @@ use trans::expr::{Dest, Ignore, SaveIn};
 use trans::expr;
 use trans::glue;
 use trans::machine;
-use trans::machine::{nonzero_llsize_of, llsize_of_alloc};
+use trans::machine::llsize_of_alloc;
 use trans::type_::Type;
 use trans::type_of;
 use middle::ty::{self, Ty};
@@ -44,13 +44,6 @@ fn get_dataptr(bcx: Block, vptr: ValueRef) -> ValueRef {
     Load(bcx, expr::get_dataptr(bcx, vptr))
 }
 
-pub fn pointer_add_byte(bcx: Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
-    let _icx = push_ctxt("tvec::pointer_add_byte");
-    let old_ty = val_ty(ptr);
-    let bptr = PointerCast(bcx, ptr, Type::i8p(bcx.ccx()));
-    return PointerCast(bcx, InBoundsGEP(bcx, bptr, &[bytes]), old_ty);
-}
-
 pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                           vptr: ValueRef,
                                           unit_ty: Ty<'tcx>,
@@ -94,17 +87,14 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub struct VecTypes<'tcx> {
     pub unit_ty: Ty<'tcx>,
     pub llunit_ty: Type,
-    pub llunit_size: ValueRef,
     pub llunit_alloc_size: u64
 }
 
 impl<'tcx> VecTypes<'tcx> {
     pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String {
-        format!("VecTypes {{unit_ty={}, llunit_ty={}, \
-                 llunit_size={}, llunit_alloc_size={}}}",
+        format!("VecTypes {{unit_ty={}, llunit_ty={}, llunit_alloc_size={}}}",
                 ty_to_string(ccx.tcx(), self.unit_ty),
                 ccx.tn().type_to_string(self.llunit_ty),
-                ccx.tn().val_to_string(self.llunit_size),
                 self.llunit_alloc_size)
     }
 }
@@ -333,13 +323,11 @@ pub fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              -> VecTypes<'tcx> {
     let ccx = bcx.ccx();
     let llunit_ty = type_of::type_of(ccx, unit_ty);
-    let llunit_size = nonzero_llsize_of(ccx, llunit_ty);
     let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty);
 
     VecTypes {
         unit_ty: unit_ty,
         llunit_ty: llunit_ty,
-        llunit_size: llunit_size,
         llunit_alloc_size: llunit_alloc_size
     }
 }
@@ -486,17 +474,13 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     let fcx = bcx.fcx;
 
     let vt = vec_types(bcx, unit_ty);
-    let fill = Mul(bcx, len, vt.llunit_size);
 
     if vt.llunit_alloc_size == 0 {
         // Special-case vectors with elements of size 0  so they don't go out of bounds (#9890)
-        iter_vec_loop(bcx, data_ptr, &vt, fill, f)
+        iter_vec_loop(bcx, data_ptr, &vt, len, f)
     } else {
         // Calculate the last pointer address we want to handle.
-        // FIXME (#3729): Optimize this when the size of the unit type is
-        // statically known to not use pointer casts, which tend to confuse
-        // LLVM.
-        let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
+        let data_end_ptr = InBoundsGEP(bcx, data_ptr, &[len]);
 
         // Now perform the iteration.
         let header_bcx = fcx.new_temp_block("iter_vec_loop_header");
diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs
index 71a7789eb39..0124ab72f6b 100644
--- a/src/librustc_trans/trans/type_.rs
+++ b/src/librustc_trans/trans/type_.rs
@@ -82,6 +82,11 @@ impl Type {
         ty!(llvm::LLVMInt64TypeInContext(ccx.llcx()))
     }
 
+    // Creates an integer type with the given number of bits, e.g. i24
+    pub fn ix(ccx: &CrateContext, num_bits: u64) -> Type {
+        ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), num_bits as c_uint))
+    }
+
     pub fn f32(ccx: &CrateContext) -> Type {
         ty!(llvm::LLVMFloatTypeInContext(ccx.llcx()))
     }
@@ -260,6 +265,13 @@ impl Type {
         ty!(llvm::LLVMPointerType(self.to_ref(), 0))
     }
 
+    pub fn is_aggregate(&self) -> bool {
+        match self.kind() {
+            TypeKind::Struct | TypeKind::Array => true,
+            _ =>  false
+        }
+    }
+
     pub fn is_packed(&self) -> bool {
         unsafe {
             llvm::LLVMIsPackedStruct(self.to_ref()) == True
@@ -272,6 +284,13 @@ impl Type {
         }
     }
 
+    /// Return the number of elements in `self` if it is a LLVM vector type.
+    pub fn vector_length(&self) -> uint {
+        unsafe {
+            llvm::LLVMGetVectorSize(self.to_ref()) as uint
+        }
+    }
+
     pub fn array_length(&self) -> uint {
         unsafe {
             llvm::LLVMGetArrayLength(self.to_ref()) as uint
@@ -314,6 +333,13 @@ impl Type {
             _ => panic!("llvm_float_width called on a non-float type")
         }
     }
+
+    /// Retrieve the bit width of the integer type `self`.
+    pub fn int_width(&self) -> u64 {
+        unsafe {
+            llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64
+        }
+    }
 }
 
 
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 99330797422..76e0e0d0545 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -243,9 +243,24 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
     llsizingty
 }
 
+pub fn foreign_arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
+    if ty::type_is_bool(t) {
+        Type::i1(cx)
+    } else {
+        type_of(cx, t)
+    }
+}
+
 pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     if ty::type_is_bool(t) {
         Type::i1(cx)
+    } else if type_is_immediate(cx, t) && type_of(cx, t).is_aggregate() {
+        // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
+        // for this leads to bad optimizations, so its arg type is an appropriately sized integer
+        match machine::llsize_of_alloc(cx, sizing_type_of(cx, t)) {
+            0 => type_of(cx, t),
+            n => Type::ix(cx, n * 8),
+        }
     } else {
         type_of(cx, t)
     }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 45e05c12713..f2927dfd843 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -516,8 +516,15 @@ pub fn instantiate_poly_trait_ref<'tcx>(
 {
     let mut projections = Vec::new();
 
+    // the trait reference introduces a binding level here, so
+    // we need to shift the `rscope`. It'd be nice if we could
+    // do away with this rscope stuff and work this knowledge
+    // into resolve_lifetimes, as we do with non-omitted
+    // lifetimes. Oh well, not there yet.
+    let shifted_rscope = ShiftedRscope::new(rscope);
+
     let trait_ref =
-        instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref,
+        instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
                               self_ty, Some(&mut projections));
 
     for projection in projections.into_iter() {
@@ -561,6 +568,29 @@ pub fn instantiate_trait_ref<'tcx>(
     }
 }
 
+fn object_path_to_poly_trait_ref<'a,'tcx>(
+    this: &AstConv<'tcx>,
+    rscope: &RegionScope,
+    trait_def_id: ast::DefId,
+    path: &ast::Path,
+    mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+    -> ty::PolyTraitRef<'tcx>
+{
+    // we are introducing a binder here, so shift the
+    // anonymous regions depth to account for that
+    let shifted_rscope = ShiftedRscope::new(rscope);
+
+    let mut tmp = Vec::new();
+    let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
+                                                     &shifted_rscope,
+                                                     trait_def_id,
+                                                     None,
+                                                     path,
+                                                     Some(&mut tmp)));
+    projections.extend(tmp.into_iter().map(ty::Binder));
+    trait_ref
+}
+
 fn ast_path_to_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
@@ -573,13 +603,6 @@ fn ast_path_to_trait_ref<'a,'tcx>(
     debug!("ast_path_to_trait_ref {:?}", path);
     let trait_def = this.get_trait_def(trait_def_id);
 
-    // the trait reference introduces a binding level here, so
-    // we need to shift the `rscope`. It'd be nice if we could
-    // do away with this rscope stuff and work this knowledge
-    // into resolve_lifetimes, as we do with non-omitted
-    // lifetimes. Oh well, not there yet.
-    let shifted_rscope = ShiftedRscope::new(rscope);
-
     let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
         ast::AngleBracketedParameters(ref data) => {
             // For now, require that parenthetical notation be used
@@ -595,7 +618,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
                             the crate attributes to enable");
             }
 
-            convert_angle_bracketed_parameters(this, &shifted_rscope, data)
+            convert_angle_bracketed_parameters(this, rscope, data)
         }
         ast::ParenthesizedParameters(ref data) => {
             // For now, require that parenthetical notation be used
@@ -616,7 +639,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
     };
 
     let substs = create_substs_for_ast_path(this,
-                                            &shifted_rscope,
+                                            rscope,
                                             path.span,
                                             &trait_def.generics,
                                             self_ty,
@@ -851,15 +874,11 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
             match this.tcx().def_map.borrow().get(&id) {
                 Some(&def::DefTrait(trait_def_id)) => {
                     let mut projection_bounds = Vec::new();
-                    let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
-                                                                     rscope,
-                                                                     trait_def_id,
-                                                                     None,
-                                                                     path,
-                                                                     Some(&mut projection_bounds)));
-                    let projection_bounds = projection_bounds.into_iter()
-                                                             .map(ty::Binder)
-                                                             .collect();
+                    let trait_ref = object_path_to_poly_trait_ref(this,
+                                                                  rscope,
+                                                                  trait_def_id,
+                                                                  path,
+                                                                  &mut projection_bounds);
                     Ok((trait_ref, projection_bounds))
                 }
                 _ => {
@@ -1001,9 +1020,12 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
 
     debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
 
+    // `<T as Trait>::U<V>` shouldn't parse right now.
+    assert!(qpath.item_path.parameters.is_empty());
+
     return this.projected_ty(ast_ty.span,
                              trait_ref,
-                             qpath.item_name.name);
+                             qpath.item_path.identifier.name);
 }
 
 // Parses the programmer's textual representation of a type into our
@@ -1095,16 +1117,13 @@ pub fn ast_ty_to_ty<'tcx>(
                         // N.B. this case overlaps somewhat with
                         // TyObjectSum, see that fn for details
                         let mut projection_bounds = Vec::new();
-                        let trait_ref = ast_path_to_trait_ref(this,
-                                                              rscope,
-                                                              trait_def_id,
-                                                              None,
-                                                              path,
-                                                              Some(&mut projection_bounds));
-                        let trait_ref = ty::Binder(trait_ref);
-                        let projection_bounds = projection_bounds.into_iter()
-                                                                 .map(ty::Binder)
-                                                                 .collect();
+
+                        let trait_ref = object_path_to_poly_trait_ref(this,
+                                                                      rscope,
+                                                                      trait_def_id,
+                                                                      path,
+                                                                      &mut projection_bounds);
+
                         trait_ref_to_object_type(this, rscope, path.span,
                                                  trait_ref, projection_bounds, &[])
                     }
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index cacf9bb19d2..47346592c86 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -467,7 +467,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
     };
 
     instantiate_path(pcx.fcx, path, ty::lookup_item_type(tcx, enum_def_id),
-                     def, pat.span, pat.id);
+                     None, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
@@ -505,7 +505,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
     } else {
         ctor_scheme
     };
-    instantiate_path(pcx.fcx, path, path_scheme, def, pat.span, pat.id);
+    instantiate_path(pcx.fcx, path, path_scheme, None, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
@@ -619,6 +619,8 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             }
         };
 
+        let field_type = pcx.fcx.normalize_associated_types_in(span, &field_type);
+
         check_pat(pcx, &*field.pat, field_type);
     }
 
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 19a88dfc553..d851206f384 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -14,6 +14,8 @@ use super::check_argument_types;
 use super::check_expr;
 use super::check_method_argument_types;
 use super::err_args;
+use super::Expectation;
+use super::expected_types_for_fn_args;
 use super::FnCtxt;
 use super::LvaluePreference;
 use super::method;
@@ -65,7 +67,8 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id:
 pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                             call_expr: &ast::Expr,
                             callee_expr: &ast::Expr,
-                            arg_exprs: &[P<ast::Expr>])
+                            arg_exprs: &[P<ast::Expr>],
+                            expected: Expectation<'tcx>)
 {
     check_expr(fcx, callee_expr);
     let original_callee_ty = fcx.expr_ty(callee_expr);
@@ -84,15 +87,15 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match result {
         None => {
             // this will report an error since original_callee_ty is not a fn
-            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs);
+            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs, expected);
         }
 
         Some(CallStep::Builtin) => {
-            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs);
+            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs, expected);
         }
 
         Some(CallStep::Overloaded(method_callee)) => {
-            confirm_overloaded_call(fcx, call_expr, arg_exprs, method_callee);
+            confirm_overloaded_call(fcx, call_expr, arg_exprs, method_callee, expected);
         }
     }
 }
@@ -153,7 +156,8 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                  call_expr: &ast::Expr,
                                  callee_ty: Ty<'tcx>,
-                                 arg_exprs: &[P<ast::Expr>])
+                                 arg_exprs: &[P<ast::Expr>],
+                                 expected: Expectation<'tcx>)
 {
     let error_fn_sig;
 
@@ -192,11 +196,16 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         fcx.normalize_associated_types_in(call_expr.span, &fn_sig);
 
     // Call the generic checker.
-    let arg_exprs: Vec<_> = arg_exprs.iter().collect(); // for some weird reason we take &[&P<...>].
+    let expected_arg_tys = expected_types_for_fn_args(fcx,
+                                                      call_expr.span,
+                                                      expected,
+                                                      fn_sig.output,
+                                                      fn_sig.inputs.as_slice());
     check_argument_types(fcx,
                          call_expr.span,
                          fn_sig.inputs.as_slice(),
-                         arg_exprs.as_slice(),
+                         &expected_arg_tys[],
+                         arg_exprs,
                          AutorefArgs::No,
                          fn_sig.variadic,
                          TupleArgumentsFlag::DontTupleArguments);
@@ -207,16 +216,17 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                     call_expr: &ast::Expr,
                                     arg_exprs: &[P<ast::Expr>],
-                                    method_callee: ty::MethodCallee<'tcx>)
+                                    method_callee: ty::MethodCallee<'tcx>,
+                                    expected: Expectation<'tcx>)
 {
-    let arg_exprs: Vec<_> = arg_exprs.iter().collect(); // for some weird reason we take &[&P<...>].
     let output_type = check_method_argument_types(fcx,
                                                   call_expr.span,
                                                   method_callee.ty,
                                                   call_expr,
-                                                  arg_exprs.as_slice(),
+                                                  arg_exprs,
                                                   AutorefArgs::No,
-                                                  TupleArgumentsFlag::TupleArguments);
+                                                  TupleArgumentsFlag::TupleArguments,
+                                                  expected);
     let method_call = ty::MethodCall::expr(call_expr.id);
     fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
     write_call(fcx, call_expr, output_type);
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 00791157569..bfe43086aab 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -33,7 +33,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
            expr.repr(fcx.tcx()),
            expected.repr(fcx.tcx()));
 
-    let expected_sig_and_kind = expected.map_to_option(fcx, |ty| {
+    let expected_sig_and_kind = expected.to_option(fcx).and_then(|ty| {
         deduce_unboxed_closure_expectations_from_expected_type(fcx, ty)
     });
 
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
new file mode 100644
index 00000000000..27d4b2055d4
--- /dev/null
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -0,0 +1,413 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use middle::infer;
+use middle::traits;
+use middle::ty::{self};
+use middle::subst::{self, Subst, Substs, VecPerParamSpace};
+use util::ppaux::{self, Repr};
+
+use syntax::ast;
+use syntax::codemap::{Span};
+use syntax::parse::token;
+
+use super::assoc;
+
+/// Checks that a method from an impl conforms to the signature of
+/// the same method as declared in the trait.
+///
+/// # Parameters
+///
+/// - impl_m: type of the method we are checking
+/// - impl_m_span: span to use for reporting errors
+/// - impl_m_body_id: id of the method body
+/// - trait_m: the method in the trait
+/// - impl_trait_ref: the TraitRef corresponding to the trait implementation
+
+pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                 impl_m: &ty::Method<'tcx>,
+                                 impl_m_span: Span,
+                                 impl_m_body_id: ast::NodeId,
+                                 trait_m: &ty::Method<'tcx>,
+                                 impl_trait_ref: &ty::TraitRef<'tcx>) {
+    debug!("compare_impl_method(impl_trait_ref={})",
+           impl_trait_ref.repr(tcx));
+
+    debug!("compare_impl_method: impl_trait_ref (liberated) = {}",
+           impl_trait_ref.repr(tcx));
+
+    let infcx = infer::new_infer_ctxt(tcx);
+    let mut fulfillment_cx = traits::FulfillmentContext::new();
+
+    let trait_to_impl_substs = &impl_trait_ref.substs;
+
+    // Try to give more informative error messages about self typing
+    // mismatches.  Note that any mismatch will also be detected
+    // below, where we construct a canonical function type that
+    // includes the self parameter as a normal parameter.  It's just
+    // that the error messages you get out of this code are a bit more
+    // inscrutable, particularly for cases where one method has no
+    // self.
+    match (&trait_m.explicit_self, &impl_m.explicit_self) {
+        (&ty::StaticExplicitSelfCategory,
+         &ty::StaticExplicitSelfCategory) => {}
+        (&ty::StaticExplicitSelfCategory, _) => {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("method `{}` has a `{}` declaration in the impl, \
+                        but not in the trait",
+                        token::get_name(trait_m.name),
+                        ppaux::explicit_self_category_to_str(
+                            &impl_m.explicit_self)).as_slice());
+            return;
+        }
+        (_, &ty::StaticExplicitSelfCategory) => {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("method `{}` has a `{}` declaration in the trait, \
+                        but not in the impl",
+                        token::get_name(trait_m.name),
+                        ppaux::explicit_self_category_to_str(
+                            &trait_m.explicit_self)).as_slice());
+            return;
+        }
+        _ => {
+            // Let the type checker catch other errors below
+        }
+    }
+
+    let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
+    let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
+    if num_impl_m_type_params != num_trait_m_type_params {
+        span_err!(tcx.sess, impl_m_span, E0049,
+            "method `{}` has {} type parameter{} \
+             but its trait declaration has {} type parameter{}",
+            token::get_name(trait_m.name),
+            num_impl_m_type_params,
+            if num_impl_m_type_params == 1 {""} else {"s"},
+            num_trait_m_type_params,
+            if num_trait_m_type_params == 1 {""} else {"s"});
+        return;
+    }
+
+    if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() {
+        span_err!(tcx.sess, impl_m_span, E0050,
+            "method `{}` has {} parameter{} \
+             but the declaration in trait `{}` has {}",
+            token::get_name(trait_m.name),
+            impl_m.fty.sig.0.inputs.len(),
+            if impl_m.fty.sig.0.inputs.len() == 1 {""} else {"s"},
+            ty::item_path_str(tcx, trait_m.def_id),
+            trait_m.fty.sig.0.inputs.len());
+        return;
+    }
+
+    // This code is best explained by example. Consider a trait:
+    //
+    //     trait Trait<'t,T> {
+    //          fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
+    //     }
+    //
+    // And an impl:
+    //
+    //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
+    //          fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
+    //     }
+    //
+    // We wish to decide if those two method types are compatible.
+    //
+    // We start out with trait_to_impl_substs, that maps the trait
+    // type parameters to impl type parameters. This is taken from the
+    // impl trait reference:
+    //
+    //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+    //
+    // We create a mapping `dummy_substs` that maps from the impl type
+    // parameters to fresh types and regions. For type parameters,
+    // this is the identity transform, but we could as well use any
+    // skolemized types. For regions, we convert from bound to free
+    // regions (Note: but only early-bound regions, i.e., those
+    // declared on the impl or used in type parameter bounds).
+    //
+    //     impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
+    //
+    // Now we can apply skol_substs to the type of the impl method
+    // to yield a new function type in terms of our fresh, skolemized
+    // types:
+    //
+    //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+    //
+    // We now want to extract and substitute the type of the *trait*
+    // method and compare it. To do so, we must create a compound
+    // substitution by combining trait_to_impl_substs and
+    // impl_to_skol_substs, and also adding a mapping for the method
+    // type parameters. We extend the mapping to also include
+    // the method parameters.
+    //
+    //     trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+    //
+    // Applying this to the trait method type yields:
+    //
+    //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+    //
+    // This type is also the same but the name of the bound region ('a
+    // vs 'b).  However, the normal subtyping rules on fn types handle
+    // this kind of equivalency just fine.
+    //
+    // We now use these subsititions to ensure that all declared bounds are
+    // satisfied by the implementation's method.
+    //
+    // We do this by creating a parameter environment which contains a
+    // substition corresponding to impl_to_skol_substs. We then build
+    // trait_to_skol_substs and use it to convert the predicates contained
+    // in the trait_m.generics to the skolemized form.
+    //
+    // Finally we register each of these predicates as an obligation in
+    // a fresh FulfillmentCtxt, and invoke select_all_or_error.
+
+    // Create a parameter environment that represents the implementation's
+    // method.
+    let impl_param_env =
+        ty::ParameterEnvironment::for_item(tcx, impl_m.def_id.node);
+
+    // Create mapping from impl to skolemized.
+    let impl_to_skol_substs = &impl_param_env.free_substs;
+
+    // Create mapping from trait to skolemized.
+    let trait_to_skol_substs =
+        trait_to_impl_substs
+        .subst(tcx, impl_to_skol_substs)
+        .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
+                     impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
+    debug!("compare_impl_method: trait_to_skol_substs={}",
+           trait_to_skol_substs.repr(tcx));
+
+    // Check region bounds. FIXME(@jroesch) refactor this away when removing
+    // ParamBounds.
+    if !check_region_bounds_on_impl_method(tcx,
+                                           impl_m_span,
+                                           impl_m,
+                                           &trait_m.generics,
+                                           &impl_m.generics,
+                                           &trait_to_skol_substs,
+                                           impl_to_skol_substs) {
+        return;
+    }
+
+    // Create obligations for each predicate declared by the impl
+    // definition in the context of the trait's parameter
+    // environment. We can't just use `impl_env.caller_bounds`,
+    // however, because we want to replace all late-bound regions with
+    // region variables.
+    let impl_bounds =
+        impl_m.generics.to_bounds(tcx, impl_to_skol_substs);
+
+    let (impl_bounds, _) =
+        infcx.replace_late_bound_regions_with_fresh_var(
+            impl_m_span,
+            infer::HigherRankedType,
+            &ty::Binder(impl_bounds));
+    debug!("compare_impl_method: impl_bounds={}",
+           impl_bounds.repr(tcx));
+
+    // // Normalize the associated types in the impl_bounds.
+    // let traits::Normalized { value: impl_bounds, .. } =
+    //     traits::normalize(&mut selcx, normalize_cause.clone(), &impl_bounds);
+
+    // Normalize the associated types in the trait_bounds.
+    let trait_bounds = trait_m.generics.to_bounds(tcx, &trait_to_skol_substs);
+    // let traits::Normalized { value: trait_bounds, .. } =
+    //     traits::normalize(&mut selcx, normalize_cause, &trait_bounds);
+
+    // Obtain the predicate split predicate sets for each.
+    let trait_pred = trait_bounds.predicates.split();
+    let impl_pred = impl_bounds.predicates.split();
+
+    // This is the only tricky bit of the new way we check implementation methods
+    // We need to build a set of predicates where only the FnSpace bounds
+    // are from the trait and we assume all other bounds from the implementation
+    // to be previously satisfied.
+    //
+    // We then register the obligations from the impl_m and check to see
+    // if all constraints hold.
+    let hybrid_preds = VecPerParamSpace::new(
+        impl_pred.types,
+        impl_pred.selfs,
+        trait_pred.fns
+    );
+
+    // Construct trait parameter environment and then shift it into the skolemized viewpoint.
+    let mut trait_param_env = impl_param_env.clone();
+    // The key step here is to update the caller_bounds's predicates to be
+    // the new hybrid bounds we computed.
+    trait_param_env.caller_bounds.predicates = hybrid_preds;
+
+    debug!("compare_impl_method: trait_bounds={}",
+        trait_param_env.caller_bounds.repr(tcx));
+
+    let mut selcx = traits::SelectionContext::new(&infcx, &trait_param_env);
+
+    let normalize_cause =
+        traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
+
+    for predicate in impl_pred.fns.into_iter() {
+        let traits::Normalized { value: predicate, .. } =
+            traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
+
+        let cause = traits::ObligationCause {
+            span: impl_m_span,
+            body_id: impl_m_body_id,
+            code: traits::ObligationCauseCode::CompareImplMethodObligation
+        };
+
+        fulfillment_cx.register_predicate_obligation(
+            &infcx,
+            traits::Obligation::new(cause, predicate));
+    }
+
+    // We now need to check that the signature of the impl method is
+    // compatible with that of the trait method. We do this by
+    // checking that `impl_fty <: trait_fty`.
+    //
+    // FIXME. Unfortunately, this doesn't quite work right now because
+    // associated type normalization is not integrated into subtype
+    // checks. For the comparison to be valid, we need to
+    // normalize the associated types in the impl/trait methods
+    // first. However, because function types bind regions, just
+    // calling `normalize_associated_types_in` would have no effect on
+    // any associated types appearing in the fn arguments or return
+    // type.
+
+    // Compute skolemized form of impl and trait method tys.
+    let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone()));
+    let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs);
+    let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone()));
+    let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
+
+    let err = infcx.try(|snapshot| {
+        let origin = infer::MethodCompatCheck(impl_m_span);
+
+        let (impl_sig, _) =
+            infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
+                                                            infer::HigherRankedType,
+                                                            &impl_m.fty.sig);
+        let impl_sig =
+            impl_sig.subst(tcx, impl_to_skol_substs);
+        let impl_sig =
+            assoc::normalize_associated_types_in(&infcx,
+                                                 &impl_param_env,
+                                                 &mut fulfillment_cx,
+                                                 impl_m_span,
+                                                 impl_m_body_id,
+                                                 &impl_sig);
+        let impl_fty =
+            ty::mk_bare_fn(tcx,
+                           None,
+                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety,
+                                                         abi: impl_m.fty.abi,
+                                                         sig: ty::Binder(impl_sig) }));
+        debug!("compare_impl_method: impl_fty={}",
+               impl_fty.repr(tcx));
+
+        let (trait_sig, skol_map) =
+            infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot);
+        let trait_sig =
+            trait_sig.subst(tcx, &trait_to_skol_substs);
+        let trait_sig =
+            assoc::normalize_associated_types_in(&infcx,
+                                                 &impl_param_env,
+                                                 &mut fulfillment_cx,
+                                                 impl_m_span,
+                                                 impl_m_body_id,
+                                                 &trait_sig);
+        let trait_fty =
+            ty::mk_bare_fn(tcx,
+                           None,
+                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: trait_m.fty.unsafety,
+                                                         abi: trait_m.fty.abi,
+                                                         sig: ty::Binder(trait_sig) }));
+
+        debug!("compare_impl_method: trait_fty={}",
+               trait_fty.repr(tcx));
+
+        try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty));
+
+        infcx.leak_check(&skol_map, snapshot)
+    });
+
+    match err {
+        Ok(()) => { }
+        Err(terr) => {
+            debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
+                   impl_fty.repr(tcx),
+                   trait_fty.repr(tcx));
+            span_err!(tcx.sess, impl_m_span, E0053,
+                      "method `{}` has an incompatible type for trait: {}",
+                      token::get_name(trait_m.name),
+                      ty::type_err_to_str(tcx, &terr));
+            return;
+        }
+    }
+
+    // Check that all obligations are satisfied by the implementation's
+    // version.
+    match fulfillment_cx.select_all_or_error(&infcx, &trait_param_env) {
+        Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) }
+        Ok(_) => {}
+    }
+
+    // Finally, resolve all regions. This catches wily misuses of lifetime
+    // parameters.
+    infcx.resolve_regions_and_report_errors(impl_m_body_id);
+
+    fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                                span: Span,
+                                                impl_m: &ty::Method<'tcx>,
+                                                trait_generics: &ty::Generics<'tcx>,
+                                                impl_generics: &ty::Generics<'tcx>,
+                                                trait_to_skol_substs: &Substs<'tcx>,
+                                                impl_to_skol_substs: &Substs<'tcx>)
+                                                -> bool
+    {
+
+        let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
+        let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
+
+        debug!("check_region_bounds_on_impl_method: \
+               trait_generics={} \
+               impl_generics={} \
+               trait_to_skol_substs={} \
+               impl_to_skol_substs={}",
+               trait_generics.repr(tcx),
+               impl_generics.repr(tcx),
+               trait_to_skol_substs.repr(tcx),
+               impl_to_skol_substs.repr(tcx));
+
+        // Must have same number of early-bound lifetime parameters.
+        // Unfortunately, if the user screws up the bounds, then this
+        // will change classification between early and late.  E.g.,
+        // if in trait we have `<'a,'b:'a>`, and in impl we just have
+        // `<'a,'b>`, then we have 2 early-bound lifetime parameters
+        // in trait but 0 in the impl. But if we report "expected 2
+        // but found 0" it's confusing, because it looks like there
+        // are zero. Since I don't quite know how to phrase things at
+        // the moment, give a kind of vague error message.
+        if trait_params.len() != impl_params.len() {
+            tcx.sess.span_err(
+                span,
+                &format!("lifetime parameters or bounds on method `{}` do \
+                         not match the trait declaration",
+                         token::get_name(impl_m.name))[]);
+            return false;
+        }
+
+        return true;
+    }
+}
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 0c53a16a811..345bc5fd2aa 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -12,7 +12,6 @@
 
 use astconv::AstConv;
 use check::{FnCtxt};
-use check::{impl_self_ty};
 use check::vtable;
 use check::vtable::select_new_fcx_obligations;
 use middle::subst;
@@ -20,7 +19,7 @@ use middle::traits;
 use middle::ty::*;
 use middle::ty;
 use middle::infer;
-use util::ppaux::{Repr, UserString};
+use util::ppaux::Repr;
 
 use std::rc::Rc;
 use syntax::ast::{DefId};
@@ -30,14 +29,18 @@ use syntax::codemap::Span;
 pub use self::MethodError::*;
 pub use self::CandidateSource::*;
 
+pub use self::suggest::{report_error, AllTraitsVec};
+
 mod confirm;
 mod doc;
 mod probe;
+mod suggest;
 
 pub enum MethodError {
     // Did not find an applicable method, but we did find various
-    // static methods that may apply.
-    NoMatch(Vec<CandidateSource>),
+    // static methods that may apply, as well as a list of
+    // not-in-scope traits which may work.
+    NoMatch(Vec<CandidateSource>, Vec<ast::DefId>),
 
     // Multiple methods might apply.
     Ambiguity(Vec<CandidateSource>),
@@ -63,7 +66,7 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 {
     match probe::probe(fcx, span, method_name, self_ty, call_expr_id) {
         Ok(_) => true,
-        Err(NoMatch(_)) => false,
+        Err(NoMatch(_, _)) => false,
         Err(Ambiguity(_)) => true,
     }
 }
@@ -294,105 +297,6 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     Some(callee)
 }
 
-pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                              span: Span,
-                              rcvr_ty: Ty<'tcx>,
-                              method_name: ast::Name,
-                              error: MethodError)
-{
-    match error {
-        NoMatch(static_sources) => {
-            let cx = fcx.tcx();
-            let method_ustring = method_name.user_string(cx);
-
-            // True if the type is a struct and contains a field with
-            // the same name as the not-found method
-            let is_field = match rcvr_ty.sty {
-                ty_struct(did, _) =>
-                    ty::lookup_struct_fields(cx, did)
-                        .iter()
-                        .any(|f| f.name.user_string(cx) == method_ustring),
-                _ => false
-            };
-
-            fcx.type_error_message(
-                span,
-                |actual| {
-                    format!("type `{}` does not implement any \
-                             method in scope named `{}`",
-                            actual,
-                            method_ustring)
-                },
-                rcvr_ty,
-                None);
-
-            // If the method has the name of a field, give a help note
-            if is_field {
-                cx.sess.span_note(span,
-                    &format!("use `(s.{0})(...)` if you meant to call the \
-                            function stored in the `{0}` field", method_ustring)[]);
-            }
-
-            if static_sources.len() > 0 {
-                fcx.tcx().sess.fileline_note(
-                    span,
-                    "found defined static methods, maybe a `self` is missing?");
-
-                report_candidates(fcx, span, method_name, static_sources);
-            }
-        }
-
-        Ambiguity(sources) => {
-            span_err!(fcx.sess(), span, E0034,
-                      "multiple applicable methods in scope");
-
-            report_candidates(fcx, span, method_name, sources);
-        }
-    }
-
-    fn report_candidates(fcx: &FnCtxt,
-                         span: Span,
-                         method_name: ast::Name,
-                         mut sources: Vec<CandidateSource>) {
-        sources.sort();
-        sources.dedup();
-
-        for (idx, source) in sources.iter().enumerate() {
-            match *source {
-                ImplSource(impl_did) => {
-                    // Provide the best span we can. Use the method, if local to crate, else
-                    // the impl, if local to crate (method may be defaulted), else the call site.
-                    let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap();
-                    let impl_span = fcx.tcx().map.def_id_span(impl_did, span);
-                    let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span);
-
-                    let impl_ty = impl_self_ty(fcx, span, impl_did).ty;
-
-                    let insertion = match impl_trait_ref(fcx.tcx(), impl_did) {
-                        None => format!(""),
-                        Some(trait_ref) => format!(" of the trait `{}`",
-                                                   ty::item_path_str(fcx.tcx(),
-                                                                     trait_ref.def_id)),
-                    };
-
-                    span_note!(fcx.sess(), method_span,
-                               "candidate #{} is defined in an impl{} for the type `{}`",
-                               idx + 1u,
-                               insertion,
-                               impl_ty.user_string(fcx.tcx()));
-                }
-                TraitSource(trait_did) => {
-                    let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap();
-                    let method_span = fcx.tcx().map.def_id_span(method.def_id, span);
-                    span_note!(fcx.sess(), method_span,
-                               "candidate #{} is defined in the trait `{}`",
-                               idx + 1u,
-                               ty::item_path_str(fcx.tcx(), trait_did));
-                }
-            }
-        }
-    }
-}
 
 /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
 /// index (or `None`, if no such method).
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index dc4d6c9a826..9bbc7b258e2 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -11,6 +11,7 @@
 use super::{MethodError,Ambiguity,NoMatch};
 use super::MethodIndex;
 use super::{CandidateSource,ImplSource,TraitSource};
+use super::suggest;
 
 use check;
 use check::{FnCtxt, NoPreference};
@@ -25,6 +26,7 @@ use middle::infer::InferCtxt;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
 use std::collections::HashSet;
+use std::mem;
 use std::rc::Rc;
 use util::ppaux::Repr;
 
@@ -127,7 +129,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // take place in the `fcx.infcx().probe` below.
     let steps = match create_steps(fcx, span, self_ty) {
         Some(steps) => steps,
-        None => return Err(NoMatch(Vec::new())),
+        None => return Err(NoMatch(Vec::new(), Vec::new())),
     };
 
     // Create a list of simplified self types, if we can.
@@ -211,6 +213,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         }
     }
 
+    fn reset(&mut self) {
+        self.inherent_candidates.clear();
+        self.extension_candidates.clear();
+        self.impl_dups.clear();
+        self.static_candidates.clear();
+    }
+
     fn tcx(&self) -> &'a ty::ctxt<'tcx> {
         self.fcx.tcx()
     }
@@ -446,6 +455,15 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         }
     }
 
+    fn assemble_extension_candidates_for_all_traits(&mut self) {
+        let mut duplicates = HashSet::new();
+        for trait_info in suggest::all_traits(self.fcx.ccx) {
+            if duplicates.insert(trait_info.def_id) {
+                self.assemble_extension_candidates_for_trait(trait_info.def_id)
+            }
+        }
+    }
+
     fn assemble_extension_candidates_for_trait(&mut self,
                                                trait_def_id: ast::DefId) {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={})",
@@ -704,18 +722,51 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     // THE ACTUAL SEARCH
 
     fn pick(mut self) -> PickResult<'tcx> {
-        let steps = self.steps.clone();
+        match self.pick_core() {
+            Some(r) => return r,
+            None => {}
+        }
 
-        for step in steps.iter() {
-            match self.pick_step(step) {
-                Some(r) => {
-                    return r;
+        let static_candidates = mem::replace(&mut self.static_candidates, vec![]);
+
+        // things failed, so lets look at all traits, for diagnostic purposes now:
+        self.reset();
+
+        let span = self.span;
+        let tcx = self.tcx();
+
+        self.assemble_extension_candidates_for_all_traits();
+
+        let out_of_scope_traits = match self.pick_core() {
+            Some(Ok(p)) => vec![p.method_ty.container.id()],
+            Some(Err(Ambiguity(v))) => v.into_iter().map(|source| {
+                match source {
+                    TraitSource(id) => id,
+                    ImplSource(impl_id) => {
+                        match ty::trait_id_of_impl(tcx, impl_id) {
+                            Some(id) => id,
+                            None =>
+                                tcx.sess.span_bug(span,
+                                                  "found inherent method when looking at traits")
+                        }
+                    }
                 }
-                None => { }
+            }).collect(),
+            Some(Err(NoMatch(_, others))) => {
+                assert!(others.is_empty());
+                vec![]
             }
-        }
+            None => vec![],
+        };
+;
+        Err(NoMatch(static_candidates, out_of_scope_traits))
+    }
+
+    fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
+        let steps = self.steps.clone();
 
-        Err(NoMatch(self.static_candidates))
+        // find the first step that works
+        steps.iter().filter_map(|step| self.pick_step(step)).next()
     }
 
     fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
new file mode 100644
index 00000000000..2a89a1d28bf
--- /dev/null
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -0,0 +1,308 @@
+// 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.
+
+//! Give useful errors and suggestions to users when a method can't be
+//! found or is otherwise invalid.
+
+use CrateCtxt;
+
+use astconv::AstConv;
+use check::{self, FnCtxt};
+use middle::ty::{self, Ty};
+use middle::def;
+use metadata::{csearch, cstore, decoder};
+use util::ppaux::UserString;
+
+use syntax::{ast, ast_util};
+use syntax::codemap::Span;
+
+use std::cell;
+use std::cmp::Ordering;
+
+use super::{MethodError, CandidateSource, impl_method, trait_method};
+
+pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                              span: Span,
+                              rcvr_ty: Ty<'tcx>,
+                              method_name: ast::Name,
+                              error: MethodError)
+{
+    match error {
+        MethodError::NoMatch(static_sources, out_of_scope_traits) => {
+            let cx = fcx.tcx();
+            let method_ustring = method_name.user_string(cx);
+
+            // True if the type is a struct and contains a field with
+            // the same name as the not-found method
+            let is_field = match rcvr_ty.sty {
+                ty::ty_struct(did, _) =>
+                    ty::lookup_struct_fields(cx, did)
+                        .iter()
+                        .any(|f| f.name.user_string(cx) == method_ustring),
+                _ => false
+            };
+
+            fcx.type_error_message(
+                span,
+                |actual| {
+                    format!("type `{}` does not implement any \
+                             method in scope named `{}`",
+                            actual,
+                            method_ustring)
+                },
+                rcvr_ty,
+                None);
+
+            // If the method has the name of a field, give a help note
+            if is_field {
+                cx.sess.span_note(span,
+                    &format!("use `(s.{0})(...)` if you meant to call the \
+                            function stored in the `{0}` field", method_ustring)[]);
+            }
+
+            if static_sources.len() > 0 {
+                fcx.tcx().sess.fileline_note(
+                    span,
+                    "found defined static methods, maybe a `self` is missing?");
+
+                report_candidates(fcx, span, method_name, static_sources);
+            }
+
+            suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits)
+        }
+
+        MethodError::Ambiguity(sources) => {
+            span_err!(fcx.sess(), span, E0034,
+                      "multiple applicable methods in scope");
+
+            report_candidates(fcx, span, method_name, sources);
+        }
+    }
+
+    fn report_candidates(fcx: &FnCtxt,
+                         span: Span,
+                         method_name: ast::Name,
+                         mut sources: Vec<CandidateSource>) {
+        sources.sort();
+        sources.dedup();
+
+        for (idx, source) in sources.iter().enumerate() {
+            match *source {
+                CandidateSource::ImplSource(impl_did) => {
+                    // Provide the best span we can. Use the method, if local to crate, else
+                    // the impl, if local to crate (method may be defaulted), else the call site.
+                    let method = impl_method(fcx.tcx(), impl_did, method_name).unwrap();
+                    let impl_span = fcx.tcx().map.def_id_span(impl_did, span);
+                    let method_span = fcx.tcx().map.def_id_span(method.def_id, impl_span);
+
+                    let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty;
+
+                    let insertion = match ty::impl_trait_ref(fcx.tcx(), impl_did) {
+                        None => format!(""),
+                        Some(trait_ref) => format!(" of the trait `{}`",
+                                                   ty::item_path_str(fcx.tcx(),
+                                                                     trait_ref.def_id)),
+                    };
+
+                    span_note!(fcx.sess(), method_span,
+                               "candidate #{} is defined in an impl{} for the type `{}`",
+                               idx + 1u,
+                               insertion,
+                               impl_ty.user_string(fcx.tcx()));
+                }
+                CandidateSource::TraitSource(trait_did) => {
+                    let (_, method) = trait_method(fcx.tcx(), trait_did, method_name).unwrap();
+                    let method_span = fcx.tcx().map.def_id_span(method.def_id, span);
+                    span_note!(fcx.sess(), method_span,
+                               "candidate #{} is defined in the trait `{}`",
+                               idx + 1u,
+                               ty::item_path_str(fcx.tcx(), trait_did));
+                }
+            }
+        }
+    }
+}
+
+
+pub type AllTraitsVec = Vec<TraitInfo>;
+
+fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                      span: Span,
+                                      _rcvr_ty: Ty<'tcx>,
+                                      method_name: ast::Name,
+                                      valid_out_of_scope_traits: Vec<ast::DefId>)
+{
+    let tcx = fcx.tcx();
+    let method_ustring = method_name.user_string(tcx);
+
+    if !valid_out_of_scope_traits.is_empty() {
+        let mut candidates = valid_out_of_scope_traits;
+        candidates.sort();
+        let msg = format!(
+            "methods from traits can only be called if the trait is in scope; \
+             the following {traits_are} implemented but not in scope, \
+             perhaps add a `use` for {one_of_them}:",
+            traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
+            one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
+
+        fcx.sess().fileline_help(span, &msg[]);
+
+        for (i, trait_did) in candidates.iter().enumerate() {
+            fcx.sess().fileline_help(span,
+                                     &*format!("candidate #{}: use `{}`",
+                                               i + 1,
+                                               ty::item_path_str(fcx.tcx(), *trait_did)))
+
+        }
+        return
+    }
+
+    // there's no implemented traits, so lets suggest some traits to implement
+    let mut candidates = all_traits(fcx.ccx)
+        .filter(|info| trait_method(tcx, info.def_id, method_name).is_some())
+        .collect::<Vec<_>>();
+
+    if candidates.len() > 0 {
+        // sort from most relevant to least relevant
+        candidates.sort_by(|a, b| a.cmp(b).reverse());
+
+        let msg = format!(
+            "methods from traits can only be called if the trait is implemented and in scope; \
+             the following {traits_define} a method `{name}`, \
+             perhaps you need to implement {one_of_them}:",
+            traits_define = if candidates.len() == 1 {"trait defines"} else {"traits define"},
+            one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
+            name = method_ustring);
+
+        fcx.sess().fileline_help(span, &msg[]);
+
+        for (i, trait_info) in candidates.iter().enumerate() {
+            fcx.sess().fileline_help(span,
+                                     &*format!("candidate #{}: `{}`",
+                                               i + 1,
+                                               ty::item_path_str(fcx.tcx(), trait_info.def_id)))
+        }
+    }
+}
+
+#[derive(Copy)]
+pub struct TraitInfo {
+    pub def_id: ast::DefId,
+}
+
+impl TraitInfo {
+    fn new(def_id: ast::DefId) -> TraitInfo {
+        TraitInfo {
+            def_id: def_id,
+        }
+    }
+}
+impl PartialEq for TraitInfo {
+    fn eq(&self, other: &TraitInfo) -> bool {
+        self.cmp(other) == Ordering::Equal
+    }
+}
+impl Eq for TraitInfo {}
+impl PartialOrd for TraitInfo {
+    fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> { Some(self.cmp(other)) }
+}
+impl Ord for TraitInfo {
+    fn cmp(&self, other: &TraitInfo) -> Ordering {
+        // accessible traits are more important/relevant than
+        // inaccessible ones, local crates are more important than
+        // remote ones (local: cnum == 0), and NodeIds just for
+        // totality.
+
+        let lhs = (other.def_id.krate, other.def_id.node);
+        let rhs = (self.def_id.krate, self.def_id.node);
+        lhs.cmp(&rhs)
+    }
+}
+
+/// Retrieve all traits in this crate and any dependent crates.
+pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
+    if ccx.all_traits.borrow().is_none() {
+        use syntax::visit;
+
+        let mut traits = vec![];
+
+        // Crate-local:
+        //
+        // meh.
+        struct Visitor<'a, 'b: 'a, 'tcx: 'a + 'b> {
+            traits: &'a mut AllTraitsVec,
+        }
+        impl<'v,'a, 'b, 'tcx> visit::Visitor<'v> for Visitor<'a, 'b, 'tcx> {
+            fn visit_item(&mut self, i: &'v ast::Item) {
+                match i.node {
+                    ast::ItemTrait(..) => {
+                        self.traits.push(TraitInfo::new(ast_util::local_def(i.id)));
+                    }
+                    _ => {}
+                }
+                visit::walk_item(self, i)
+            }
+        }
+        visit::walk_crate(&mut Visitor {
+            traits: &mut traits
+        }, ccx.tcx.map.krate());
+
+        // Cross-crate:
+        fn handle_external_def(traits: &mut AllTraitsVec,
+                               ccx: &CrateCtxt,
+                               cstore: &cstore::CStore,
+                               dl: decoder::DefLike) {
+            match dl {
+                decoder::DlDef(def::DefTrait(did)) => {
+                    traits.push(TraitInfo::new(did));
+                }
+                decoder::DlDef(def::DefMod(did)) => {
+                    csearch::each_child_of_item(cstore, did, |dl, _, _| {
+                        handle_external_def(traits, ccx, cstore, dl)
+                    })
+                }
+                _ => {}
+            }
+        }
+        let cstore = &ccx.tcx.sess.cstore;
+        cstore.iter_crate_data(|&mut: cnum, _| {
+            csearch::each_top_level_item_of_crate(cstore, cnum, |dl, _, _| {
+                handle_external_def(&mut traits, ccx, cstore, dl)
+            })
+        });
+
+        *ccx.all_traits.borrow_mut() = Some(traits);
+    }
+
+    let borrow = ccx.all_traits.borrow();
+    assert!(borrow.is_some());
+    AllTraits {
+        borrow: borrow,
+        idx: 0
+    }
+}
+
+pub struct AllTraits<'a> {
+    borrow: cell::Ref<'a Option<AllTraitsVec>>,
+    idx: usize
+}
+
+impl<'a> Iterator for AllTraits<'a> {
+    type Item = TraitInfo;
+
+    fn next(&mut self) -> Option<TraitInfo> {
+        let AllTraits { ref borrow, ref mut idx } = *self;
+        // ugh.
+        borrow.as_ref().unwrap().get(*idx).map(|info| {
+            *idx += 1;
+            *info
+        })
+    }
+}
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 1d184131ded..7e38321049e 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -78,11 +78,13 @@ type parameter).
 
 pub use self::LvaluePreference::*;
 pub use self::Expectation::*;
+pub use self::compare_method::compare_impl_method;
 use self::IsBinopAssignment::*;
 use self::TupleArgumentsFlag::*;
 
 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
 use check::_match::pat_ctxt;
+use fmt_macros::{Parser, Piece, Position};
 use middle::{const_eval, def};
 use middle::infer;
 use middle::lang_items::IteratorItem;
@@ -105,14 +107,16 @@ use TypeAndSubsts;
 use middle::lang_items::TypeIdLangItem;
 use lint;
 use util::common::{block_query, indenter, loop_query};
-use util::ppaux::{self, UserString, Repr};
+use util::ppaux::{self, Repr};
 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
 
 use std::cell::{Cell, Ref, RefCell};
 use std::mem::replace;
 use std::rc::Rc;
 use std::iter::repeat;
+use std::slice;
 use syntax::{self, abi, attr};
+use syntax::attr::AttrMetaMethods;
 use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
 use syntax::ast_util::{self, local_def, PostExpansionMethod};
 use syntax::codemap::{self, Span};
@@ -134,8 +138,8 @@ mod upvar;
 pub mod wf;
 mod closure;
 mod callee;
+mod compare_method;
 
-/// Fields that are part of a `FnCtxt` which are inherited by
 /// closures defined within the function.  For example:
 ///
 ///     fn foo() {
@@ -726,7 +730,8 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         }
 
       }
-      ast::ItemTrait(_, _, _, ref trait_methods) => {
+      ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
+        check_trait_on_unimplemented(ccx, generics, it);
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_method in trait_methods.iter() {
             match *trait_method {
@@ -776,6 +781,51 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
     }
 }
 
+fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                               generics: &ast::Generics,
+                               item: &ast::Item) {
+    if let Some(ref attr) = item.attrs.iter().find(|&: a| {
+        a.check_name("rustc_on_unimplemented")
+    }) {
+        if let Some(ref istring) = attr.value_str() {
+            let mut parser = Parser::new(istring.get());
+            let types = generics.ty_params.as_slice();
+            for token in parser {
+                match token {
+                    Piece::String(_) => (), // Normal string, no need to check it
+                    Piece::NextArgument(a) => match a.position {
+                        // `{Self}` is allowed
+                        Position::ArgumentNamed(s) if s == "Self" => (),
+                        // So is `{A}` if A is a type parameter
+                        Position::ArgumentNamed(s) => match types.iter().find(|t| {
+                            t.ident.as_str() == s
+                        }) {
+                            Some(_) => (),
+                            None => {
+                                ccx.tcx.sess.span_err(attr.span,
+                                                 format!("there is no type parameter \
+                                                          {} on trait {}",
+                                                           s, item.ident.as_str())
+                                            .as_slice());
+                            }
+                        },
+                        // `{:1}` and `{}` are not to be used
+                        Position::ArgumentIs(_) | Position::ArgumentNext => {
+                            ccx.tcx.sess.span_err(attr.span,
+                                                  "only named substitution \
+                                                   parameters are allowed");
+                        }
+                    }
+                }
+            }
+        } else {
+            ccx.tcx.sess.span_err(attr.span,
+                                  "this attribute must have a value, \
+                                   eg `#[rustc_on_unimplemented = \"foo\"]`")
+        }
+    }
+}
+
 /// Type checks a method body.
 ///
 /// # Parameters
@@ -944,503 +994,6 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-/// Checks that a method from an impl conforms to the signature of
-/// the same method as declared in the trait.
-///
-/// # Parameters
-///
-/// - impl_generics: the generics declared on the impl itself (not the method!)
-/// - impl_m: type of the method we are checking
-/// - impl_m_span: span to use for reporting errors
-/// - impl_m_body_id: id of the method body
-/// - trait_m: the method in the trait
-/// - trait_to_impl_substs: the substitutions used on the type of the trait
-fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                             impl_m: &ty::Method<'tcx>,
-                             impl_m_span: Span,
-                             impl_m_body_id: ast::NodeId,
-                             trait_m: &ty::Method<'tcx>,
-                             impl_trait_ref: &ty::TraitRef<'tcx>) {
-    debug!("compare_impl_method(impl_trait_ref={})",
-           impl_trait_ref.repr(tcx));
-
-    debug!("impl_trait_ref (liberated) = {}",
-           impl_trait_ref.repr(tcx));
-
-    let infcx = infer::new_infer_ctxt(tcx);
-    let mut fulfillment_cx = traits::FulfillmentContext::new();
-
-    let trait_to_impl_substs = &impl_trait_ref.substs;
-
-    // Try to give more informative error messages about self typing
-    // mismatches.  Note that any mismatch will also be detected
-    // below, where we construct a canonical function type that
-    // includes the self parameter as a normal parameter.  It's just
-    // that the error messages you get out of this code are a bit more
-    // inscrutable, particularly for cases where one method has no
-    // self.
-    match (&trait_m.explicit_self, &impl_m.explicit_self) {
-        (&ty::StaticExplicitSelfCategory,
-         &ty::StaticExplicitSelfCategory) => {}
-        (&ty::StaticExplicitSelfCategory, _) => {
-            tcx.sess.span_err(
-                impl_m_span,
-                &format!("method `{}` has a `{}` declaration in the impl, \
-                        but not in the trait",
-                        token::get_name(trait_m.name),
-                        ppaux::explicit_self_category_to_str(
-                            &impl_m.explicit_self))[]);
-            return;
-        }
-        (_, &ty::StaticExplicitSelfCategory) => {
-            tcx.sess.span_err(
-                impl_m_span,
-                &format!("method `{}` has a `{}` declaration in the trait, \
-                        but not in the impl",
-                        token::get_name(trait_m.name),
-                        ppaux::explicit_self_category_to_str(
-                            &trait_m.explicit_self))[]);
-            return;
-        }
-        _ => {
-            // Let the type checker catch other errors below
-        }
-    }
-
-    let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
-    let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
-    if num_impl_m_type_params != num_trait_m_type_params {
-        span_err!(tcx.sess, impl_m_span, E0049,
-            "method `{}` has {} type parameter{} \
-             but its trait declaration has {} type parameter{}",
-            token::get_name(trait_m.name),
-            num_impl_m_type_params,
-            if num_impl_m_type_params == 1 {""} else {"s"},
-            num_trait_m_type_params,
-            if num_trait_m_type_params == 1 {""} else {"s"});
-        return;
-    }
-
-    if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() {
-        span_err!(tcx.sess, impl_m_span, E0050,
-            "method `{}` has {} parameter{} \
-             but the declaration in trait `{}` has {}",
-            token::get_name(trait_m.name),
-            impl_m.fty.sig.0.inputs.len(),
-            if impl_m.fty.sig.0.inputs.len() == 1 {""} else {"s"},
-            ty::item_path_str(tcx, trait_m.def_id),
-            trait_m.fty.sig.0.inputs.len());
-        return;
-    }
-
-    // This code is best explained by example. Consider a trait:
-    //
-    //     trait Trait<'t,T> {
-    //          fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
-    //     }
-    //
-    // And an impl:
-    //
-    //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
-    //          fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
-    //     }
-    //
-    // We wish to decide if those two method types are compatible.
-    //
-    // We start out with trait_to_impl_substs, that maps the trait
-    // type parameters to impl type parameters. This is taken from the
-    // impl trait reference:
-    //
-    //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
-    //
-    // We create a mapping `dummy_substs` that maps from the impl type
-    // parameters to fresh types and regions. For type parameters,
-    // this is the identity transform, but we could as well use any
-    // skolemized types. For regions, we convert from bound to free
-    // regions (Note: but only early-bound regions, i.e., those
-    // declared on the impl or used in type parameter bounds).
-    //
-    //     impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
-    //
-    // Now we can apply skol_substs to the type of the impl method
-    // to yield a new function type in terms of our fresh, skolemized
-    // types:
-    //
-    //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
-    //
-    // We now want to extract and substitute the type of the *trait*
-    // method and compare it. To do so, we must create a compound
-    // substitution by combining trait_to_impl_substs and
-    // impl_to_skol_substs, and also adding a mapping for the method
-    // type parameters. We extend the mapping to also include
-    // the method parameters.
-    //
-    //     trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
-    //
-    // Applying this to the trait method type yields:
-    //
-    //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
-    //
-    // This type is also the same but the name of the bound region ('a
-    // vs 'b).  However, the normal subtyping rules on fn types handle
-    // this kind of equivalency just fine.
-
-    // Create mapping from impl to skolemized.
-    let impl_param_env = ty::construct_parameter_environment(tcx, &impl_m.generics, impl_m_body_id);
-    let impl_to_skol_substs = &impl_param_env.free_substs;
-
-    // Create mapping from trait to skolemized.
-    let trait_to_skol_substs =
-        trait_to_impl_substs
-        .subst(tcx, impl_to_skol_substs)
-        .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
-                     impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
-
-    // Check region bounds.
-    if !check_region_bounds_on_impl_method(tcx,
-                                           impl_m_span,
-                                           impl_m,
-                                           &trait_m.generics,
-                                           &impl_m.generics,
-                                           &trait_to_skol_substs,
-                                           impl_to_skol_substs) {
-        return;
-    }
-
-    // Check bounds. Note that the bounds from the impl may reference
-    // late-bound regions declared on the impl, so liberate those.
-    // This requires two artificial binding scopes -- one for the impl,
-    // and one for the method.
-    //
-    // An example would be:
-    //
-    //     trait Foo<T> { fn method<U:Bound<T>>() { ... } }
-    //
-    //     impl<'a> Foo<&'a T> for &'a U {
-    //         fn method<U:Bound<&'a T>>() { ... }
-    //     }
-    //
-    // Here, the region parameter `'a` is late-bound, so in the bound
-    // `Bound<&'a T>`, the lifetime `'a` will be late-bound with a
-    // depth of 3 (it is nested within 3 binders: the impl, method,
-    // and trait-ref itself). So when we do the liberation, we have
-    // two introduce two `ty::Binder` scopes, one for the impl and one
-    // the method.
-    //
-    // The only late-bounded regions that can possibly appear here are
-    // from the impl, not the method. This is because region
-    // parameters declared on the method which appear in a type bound
-    // would be early bound. On the trait side, there can be no
-    // late-bound lifetimes because trait definitions do not introduce
-    // a late region binder.
-    let trait_bounds =
-        trait_m.generics.types.get_slice(subst::FnSpace).iter()
-        .map(|trait_param_def| &trait_param_def.bounds);
-    let impl_bounds =
-        impl_m.generics.types.get_slice(subst::FnSpace).iter()
-        .map(|impl_param_def| &impl_param_def.bounds);
-    for (i, (trait_param_bounds, impl_param_bounds)) in
-        trait_bounds.zip(impl_bounds).enumerate()
-    {
-        // Check that the impl does not require any builtin-bounds
-        // that the trait does not guarantee:
-        let extra_bounds =
-            impl_param_bounds.builtin_bounds -
-            trait_param_bounds.builtin_bounds;
-        if !extra_bounds.is_empty() {
-            span_err!(tcx.sess, impl_m_span, E0051,
-                "in method `{}`, type parameter {} requires `{}`, \
-                 which is not required by the corresponding type parameter \
-                 in the trait declaration",
-                token::get_name(trait_m.name),
-                i,
-                extra_bounds.user_string(tcx));
-           return;
-        }
-
-        // Check that the trait bounds of the trait imply the bounds of its
-        // implementation.
-        //
-        // FIXME(pcwalton): We could be laxer here regarding sub- and super-
-        // traits, but I doubt that'll be wanted often, so meh.
-        for impl_trait_bound in impl_param_bounds.trait_bounds.iter() {
-            debug!("compare_impl_method(): impl-trait-bound subst");
-            let impl_trait_bound =
-                impl_trait_bound.subst(tcx, impl_to_skol_substs);
-
-            // There may be late-bound regions from the impl in the
-            // impl's bound, so "liberate" those. Note that the
-            // trait_to_skol_substs is derived from the impl's
-            // trait-ref, and the late-bound regions appearing there
-            // have already been liberated, so the result should match
-            // up.
-
-            let found_match_in_trait =
-                trait_param_bounds.trait_bounds.iter().any(|trait_bound| {
-                    debug!("compare_impl_method(): trait-bound subst");
-                    let trait_bound =
-                        trait_bound.subst(tcx, &trait_to_skol_substs);
-                    infer::mk_sub_poly_trait_refs(&infcx,
-                                                  true,
-                                                  infer::Misc(impl_m_span),
-                                                  trait_bound,
-                                                  impl_trait_bound.clone()).is_ok()
-                });
-
-            if !found_match_in_trait {
-                span_err!(tcx.sess, impl_m_span, E0052,
-                          "in method `{}`, type parameter {} requires bound `{}`, which is not \
-                           required by the corresponding type parameter in the trait declaration",
-                          token::get_name(trait_m.name),
-                          i,
-                          impl_trait_bound.user_string(tcx));
-            }
-        }
-    }
-
-    // We now need to check that the signature of the impl method is
-    // compatible with that of the trait method. We do this by
-    // checking that `impl_fty <: trait_fty`.
-    //
-    // FIXME. Unfortunately, this doesn't quite work right now because
-    // associated type normalization is not integrated into subtype
-    // checks. For the comparison to be valid, we need to
-    // normalize the associated types in the impl/trait methods
-    // first. However, because function types bind regions, just
-    // calling `normalize_associated_types_in` would have no effect on
-    // any associated types appearing in the fn arguments or return
-    // type.
-
-
-    // Compute skolemized form of impl and trait method tys.
-    let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone()));
-    let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs);
-    let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone()));
-    let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
-
-    let err = infcx.try(|snapshot| {
-        let origin = infer::MethodCompatCheck(impl_m_span);
-
-        let (impl_sig, _) =
-            infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
-                                                            infer::HigherRankedType,
-                                                            &impl_m.fty.sig);
-        let impl_sig =
-            impl_sig.subst(tcx, impl_to_skol_substs);
-        let impl_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
-                                                 &mut fulfillment_cx,
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &impl_sig);
-        let impl_fty =
-            ty::mk_bare_fn(tcx,
-                           None,
-                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety,
-                                                         abi: impl_m.fty.abi,
-                                                         sig: ty::Binder(impl_sig) }));
-        debug!("compare_impl_method: impl_fty={}",
-               impl_fty.repr(tcx));
-
-        let (trait_sig, skol_map) =
-            infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot);
-        let trait_sig =
-            trait_sig.subst(tcx, &trait_to_skol_substs);
-        let trait_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
-                                                 &mut fulfillment_cx,
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &trait_sig);
-        let trait_fty =
-            ty::mk_bare_fn(tcx,
-                           None,
-                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: trait_m.fty.unsafety,
-                                                         abi: trait_m.fty.abi,
-                                                         sig: ty::Binder(trait_sig) }));
-
-        debug!("compare_impl_method: trait_fty={}",
-               trait_fty.repr(tcx));
-
-        try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty));
-
-        infcx.leak_check(&skol_map, snapshot)
-    });
-
-    match err {
-        Ok(()) => { }
-        Err(terr) => {
-            debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
-                   impl_fty.repr(tcx),
-                   trait_fty.repr(tcx));
-            span_err!(tcx.sess, impl_m_span, E0053,
-                      "method `{}` has an incompatible type for trait: {}",
-                      token::get_name(trait_m.name),
-                      ty::type_err_to_str(tcx, &terr));
-            return;
-        }
-    }
-
-    // Run the fulfillment context to completion to accommodate any
-    // associated type normalizations that may have occurred.
-    match fulfillment_cx.select_all_or_error(&infcx, &impl_param_env) {
-        Ok(()) => { }
-        Err(errors) => {
-            traits::report_fulfillment_errors(&infcx, &errors);
-        }
-    }
-
-    // Finally, resolve all regions. This catches wily misuses of lifetime
-    // parameters.
-    infcx.resolve_regions_and_report_errors(impl_m_body_id);
-
-    /// Check that region bounds on impl method are the same as those on the trait. In principle,
-    /// it could be ok for there to be fewer region bounds on the impl method, but this leads to an
-    /// annoying corner case that is painful to handle (described below), so for now we can just
-    /// forbid it.
-    ///
-    /// Example (see `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
-    ///
-    /// ```
-    /// trait Foo<'a> {
-    ///     fn method1<'b>();
-    ///     fn method2<'b:'a>();
-    /// }
-    ///
-    /// impl<'a> Foo<'a> for ... {
-    ///     fn method1<'b:'a>() { .. case 1, definitely bad .. }
-    ///     fn method2<'b>() { .. case 2, could be ok .. }
-    /// }
-    /// ```
-    ///
-    /// The "definitely bad" case is case #1. Here, the impl adds an extra constraint not present
-    /// in the trait.
-    ///
-    /// The "maybe bad" case is case #2. Here, the impl adds an extra constraint not present in the
-    /// trait. We could in principle allow this, but it interacts in a complex way with early/late
-    /// bound resolution of lifetimes. Basically the presence or absence of a lifetime bound
-    /// affects whether the lifetime is early/late bound, and right now the code breaks if the
-    /// trait has an early bound lifetime parameter and the method does not.
-    fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                                span: Span,
-                                                impl_m: &ty::Method<'tcx>,
-                                                trait_generics: &ty::Generics<'tcx>,
-                                                impl_generics: &ty::Generics<'tcx>,
-                                                trait_to_skol_substs: &Substs<'tcx>,
-                                                impl_to_skol_substs: &Substs<'tcx>)
-                                                -> bool
-    {
-
-        let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
-        let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
-
-        debug!("check_region_bounds_on_impl_method: \
-               trait_generics={} \
-               impl_generics={} \
-               trait_to_skol_substs={} \
-               impl_to_skol_substs={}",
-               trait_generics.repr(tcx),
-               impl_generics.repr(tcx),
-               trait_to_skol_substs.repr(tcx),
-               impl_to_skol_substs.repr(tcx));
-
-        // Must have same number of early-bound lifetime parameters.
-        // Unfortunately, if the user screws up the bounds, then this
-        // will change classification between early and late.  E.g.,
-        // if in trait we have `<'a,'b:'a>`, and in impl we just have
-        // `<'a,'b>`, then we have 2 early-bound lifetime parameters
-        // in trait but 0 in the impl. But if we report "expected 2
-        // but found 0" it's confusing, because it looks like there
-        // are zero. Since I don't quite know how to phrase things at
-        // the moment, give a kind of vague error message.
-        if trait_params.len() != impl_params.len() {
-            tcx.sess.span_err(
-                span,
-                &format!("lifetime parameters or bounds on method `{}` do \
-                         not match the trait declaration",
-                        token::get_name(impl_m.name))[]);
-            return false;
-        }
-
-        // Each parameter `'a:'b+'c+'d` in trait should have the same
-        // set of bounds in the impl, after subst.
-        for (trait_param, impl_param) in
-            trait_params.iter().zip(
-                impl_params.iter())
-        {
-            let trait_bounds =
-                trait_param.bounds.subst(tcx, trait_to_skol_substs);
-            let impl_bounds =
-                impl_param.bounds.subst(tcx, impl_to_skol_substs);
-
-            debug!("check_region_bounds_on_impl_method: \
-                   trait_param={} \
-                   impl_param={} \
-                   trait_bounds={} \
-                   impl_bounds={}",
-                   trait_param.repr(tcx),
-                   impl_param.repr(tcx),
-                   trait_bounds.repr(tcx),
-                   impl_bounds.repr(tcx));
-
-            // Collect the set of bounds present in trait but not in
-            // impl.
-            let missing: Vec<ty::Region> =
-                trait_bounds.iter()
-                .filter(|&b| !impl_bounds.contains(b))
-                .map(|&b| b)
-                .collect();
-
-            // Collect set present in impl but not in trait.
-            let extra: Vec<ty::Region> =
-                impl_bounds.iter()
-                .filter(|&b| !trait_bounds.contains(b))
-                .map(|&b| b)
-                .collect();
-
-            debug!("missing={} extra={}",
-                   missing.repr(tcx), extra.repr(tcx));
-
-            let err = if missing.len() != 0 || extra.len() != 0 {
-                tcx.sess.span_err(
-                    span,
-                    &format!(
-                        "the lifetime parameter `{}` declared in the impl \
-                         has a distinct set of bounds \
-                         from its counterpart `{}` \
-                         declared in the trait",
-                        impl_param.name.user_string(tcx),
-                        trait_param.name.user_string(tcx))[]);
-                true
-            } else {
-                false
-            };
-
-            if missing.len() != 0 {
-                tcx.sess.span_note(
-                    span,
-                    &format!("the impl is missing the following bounds: `{}`",
-                            missing.user_string(tcx))[]);
-            }
-
-            if extra.len() != 0 {
-                tcx.sess.span_note(
-                    span,
-                    &format!("the impl has the following extra bounds: `{}`",
-                            extra.user_string(tcx))[]);
-            }
-
-            if err {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
-
 fn check_cast(fcx: &FnCtxt,
               cast_expr: &ast::Expr,
               e: &ast::Expr,
@@ -2044,7 +1597,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     {
         debug!("register_predicate({})",
                obligation.repr(self.tcx()));
-
         self.inh.fulfillment_cx
             .borrow_mut()
             .register_predicate_obligation(self.infcx(), obligation);
@@ -2097,6 +1649,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
         match self.inh.node_types.borrow().get(&id) {
             Some(&t) => t,
+            None if self.err_count_since_creation() != 0 => self.tcx().types.err,
             None => {
                 self.tcx().sess.bug(
                     &format!("no type for node {}: {} in fcx {}",
@@ -2239,6 +1792,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         obligations.map_move(|o| self.register_predicate(o));
     }
+
+    // Only for fields! Returns <none> for methods>
+    // Indifferent to privacy flags
+    pub fn lookup_field_ty(&self,
+                           span: Span,
+                           class_id: ast::DefId,
+                           items: &[ty::field_ty],
+                           fieldname: ast::Name,
+                           substs: &subst::Substs<'tcx>)
+                           -> Option<Ty<'tcx>>
+    {
+        let o_field = items.iter().find(|f| f.name == fieldname);
+        o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
+               .map(|t| self.normalize_associated_types_in(span, &t))
+    }
+
+    pub fn lookup_tup_field_ty(&self,
+                               span: Span,
+                               class_id: ast::DefId,
+                               items: &[ty::field_ty],
+                               idx: uint,
+                               substs: &subst::Substs<'tcx>)
+                               -> Option<Ty<'tcx>>
+    {
+        let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
+        o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
+               .map(|t| self.normalize_associated_types_in(span, &t))
+    }
 }
 
 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
@@ -2558,7 +2139,8 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                   iterator_expr,
                                                   &[],
                                                   AutorefArgs::No,
-                                                  DontTupleArguments);
+                                                  DontTupleArguments,
+                                                  NoExpectation);
 
     match method {
         Some(method) => {
@@ -2598,9 +2180,10 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          sp: Span,
                                          method_fn_ty: Ty<'tcx>,
                                          callee_expr: &ast::Expr,
-                                         args_no_rcvr: &[&P<ast::Expr>],
+                                         args_no_rcvr: &[P<ast::Expr>],
                                          autoref_args: AutorefArgs,
-                                         tuple_arguments: TupleArgumentsFlag)
+                                         tuple_arguments: TupleArgumentsFlag,
+                                         expected: Expectation<'tcx>)
                                          -> ty::FnOutput<'tcx> {
     if ty::type_is_error(method_fn_ty) {
         let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
@@ -2613,6 +2196,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         check_argument_types(fcx,
                              sp,
                              &err_inputs[],
+                             &[],
                              args_no_rcvr,
                              autoref_args,
                              false,
@@ -2622,9 +2206,15 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         match method_fn_ty.sty {
             ty::ty_bare_fn(_, ref fty) => {
                 // HACK(eddyb) ignore self in the definition (see above).
+                let expected_arg_tys = expected_types_for_fn_args(fcx,
+                                                                  sp,
+                                                                  expected,
+                                                                  fty.sig.0.output,
+                                                                  &fty.sig.0.inputs[1..]);
                 check_argument_types(fcx,
                                      sp,
-                                     fty.sig.0.inputs.slice_from(1),
+                                     &fty.sig.0.inputs[1..],
+                                     &expected_arg_tys[],
                                      args_no_rcvr,
                                      autoref_args,
                                      fty.sig.0.variadic,
@@ -2644,7 +2234,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   sp: Span,
                                   fn_inputs: &[Ty<'tcx>],
-                                  args: &[&P<ast::Expr>],
+                                  expected_arg_tys: &[Ty<'tcx>],
+                                  args: &[P<ast::Expr>],
                                   autoref_args: AutorefArgs,
                                   variadic: bool,
                                   tuple_arguments: TupleArgumentsFlag) {
@@ -2658,6 +2249,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         1
     };
 
+    let mut expected_arg_tys = expected_arg_tys;
     let expected_arg_count = fn_inputs.len();
     let formal_tys = if tuple_arguments == TupleArguments {
         let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
@@ -2670,8 +2262,16 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         if arg_types.len() == 1 {""} else {"s"},
                         args.len(),
                         if args.len() == 1 {" was"} else {"s were"});
+                    expected_arg_tys = &[][];
                     err_args(fcx.tcx(), args.len())
                 } else {
+                    expected_arg_tys = match expected_arg_tys.get(0) {
+                        Some(&ty) => match ty.sty {
+                            ty::ty_tup(ref tys) => &**tys,
+                            _ => &[]
+                        },
+                        None => &[]
+                    };
                     (*arg_types).clone()
                 }
             }
@@ -2679,14 +2279,15 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 span_err!(tcx.sess, sp, E0059,
                     "cannot use call notation; the first type parameter \
                      for the function trait is neither a tuple nor unit");
+                expected_arg_tys = &[][];
                 err_args(fcx.tcx(), args.len())
             }
         }
     } else if expected_arg_count == supplied_arg_count {
-        fn_inputs.iter().map(|a| *a).collect()
+        fn_inputs.to_vec()
     } else if variadic {
         if supplied_arg_count >= expected_arg_count {
-            fn_inputs.iter().map(|a| *a).collect()
+            fn_inputs.to_vec()
         } else {
             span_err!(tcx.sess, sp, E0060,
                 "this function takes at least {} parameter{} \
@@ -2695,6 +2296,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 if expected_arg_count == 1 {""} else {"s"},
                 supplied_arg_count,
                 if supplied_arg_count == 1 {" was"} else {"s were"});
+            expected_arg_tys = &[][];
             err_args(fcx.tcx(), supplied_arg_count)
         }
     } else {
@@ -2704,6 +2306,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             if expected_arg_count == 1 {""} else {"s"},
             supplied_arg_count,
             if supplied_arg_count == 1 {" was"} else {"s were"});
+        expected_arg_tys = &[][];
         err_args(fcx.tcx(), supplied_arg_count)
     };
 
@@ -2767,7 +2370,25 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     AutorefArgs::No => {}
                 }
 
-                check_expr_coercable_to_type(fcx, &***arg, formal_ty);
+                // The special-cased logic below has three functions:
+                // 1. Provide as good of an expected type as possible.
+                let expected = expected_arg_tys.get(i).map(|&ty| {
+                    Expectation::rvalue_hint(ty)
+                });
+
+                check_expr_with_unifier(fcx, &**arg,
+                                        expected.unwrap_or(ExpectHasType(formal_ty)),
+                                        NoPreference, || {
+                    // 2. Coerce to the most detailed type that could be coerced
+                    //    to, which is `expected_ty` if `rvalue_hint` returns an
+                    //    `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
+                    let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
+                    demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
+
+                    // 3. Relate the expected type and the formal one,
+                    //    if the expected type was used for the coercion.
+                    coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
+                });
             }
         }
     }
@@ -2776,12 +2397,12 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // arguments which we skipped above.
     if variadic {
         for arg in args.iter().skip(expected_arg_count) {
-            check_expr(fcx, &***arg);
+            check_expr(fcx, &**arg);
 
             // There are a few types which get autopromoted when passed via varargs
             // in C but we just error out instead and require explicit casts.
             let arg_ty = structurally_resolved_type(fcx, arg.span,
-                                                    fcx.expr_ty(&***arg));
+                                                    fcx.expr_ty(&**arg));
             match arg_ty.sty {
                 ty::ty_float(ast::TyF32) => {
                     fcx.type_error_message(arg.span,
@@ -2844,7 +2465,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
         ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
         ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
-            let opt_ty = expected.map_to_option(fcx, |ty| {
+            let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
                     ty::ty_char => Some(tcx.types.u8),
@@ -2858,7 +2479,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
         ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
         ast::LitFloatUnsuffixed(_) => {
-            let opt_ty = expected.map_to_option(fcx, |ty| {
+            let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::ty_float(_) => Some(ty),
                     _ => None
@@ -2953,30 +2574,6 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     TypeAndSubsts { substs: substs, ty: substd_ty }
 }
 
-// Only for fields! Returns <none> for methods>
-// Indifferent to privacy flags
-pub fn lookup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
-                             class_id: ast::DefId,
-                             items: &[ty::field_ty],
-                             fieldname: ast::Name,
-                             substs: &subst::Substs<'tcx>)
-                             -> Option<Ty<'tcx>> {
-
-    let o_field = items.iter().find(|f| f.name == fieldname);
-    o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
-}
-
-pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                 class_id: ast::DefId,
-                                 items: &[ty::field_ty],
-                                 idx: uint,
-                                 substs: &subst::Substs<'tcx>)
-                                 -> Option<Ty<'tcx>> {
-
-    let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
-    o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
-}
-
 // Controls whether the arguments are automatically referenced. This is useful
 // for overloaded binary and unary operators.
 #[derive(Copy, PartialEq)]
@@ -3007,6 +2604,45 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
+/// Unifies the return type with the expected type early, for more coercions
+/// and forward type information on the argument expressions.
+fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                        call_span: Span,
+                                        expected_ret: Expectation<'tcx>,
+                                        formal_ret: ty::FnOutput<'tcx>,
+                                        formal_args: &[Ty<'tcx>])
+                                        -> Vec<Ty<'tcx>> {
+    let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
+        if let ty::FnConverging(formal_ret_ty) = formal_ret {
+            fcx.infcx().commit_regions_if_ok(|| {
+                // Attempt to apply a subtyping relationship between the formal
+                // return type (likely containing type variables if the function
+                // is polymorphic) and the expected return type.
+                // No argument expectations are produced if unification fails.
+                let origin = infer::Misc(call_span);
+                let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
+                // FIXME(#15760) can't use try! here, FromError doesn't default
+                // to identity so the resulting type is not constrained.
+                if let Err(e) = ures {
+                    return Err(e);
+                }
+
+                // Record all the argument types, with the substitutions
+                // produced from the above subtyping unification.
+                Ok(formal_args.iter().map(|ty| {
+                    fcx.infcx().resolve_type_vars_if_possible(ty)
+                }).collect())
+            }).ok()
+        } else {
+            None
+        }
+    }).unwrap_or(vec![]);
+    debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
+           formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
+           expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
+    expected_args
+}
+
 /// Invariant:
 /// If an expression has any sub-expressions that result in a type error,
 /// inspecting that expression's type with `ty::type_is_error` will return
@@ -3028,12 +2664,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
            expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
 
     // Checks a method call.
-    fn check_method_call(fcx: &FnCtxt,
-                         expr: &ast::Expr,
-                         method_name: ast::SpannedIdent,
-                         args: &[P<ast::Expr>],
-                         tps: &[P<ast::Ty>],
-                         lvalue_pref: LvaluePreference) {
+    fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                   expr: &ast::Expr,
+                                   method_name: ast::SpannedIdent,
+                                   args: &[P<ast::Expr>],
+                                   tps: &[P<ast::Ty>],
+                                   expected: Expectation<'tcx>,
+                                   lvalue_pref: LvaluePreference) {
         let rcvr = &*args[0];
         check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
 
@@ -3064,14 +2701,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         };
 
         // Call the generic checker.
-        let args: Vec<_> = args[1..].iter().map(|x| x).collect();
         let ret_ty = check_method_argument_types(fcx,
                                                  method_name.span,
                                                  fn_ty,
                                                  expr,
-                                                 args.as_slice(),
+                                                 &args[1..],
                                                  AutorefArgs::No,
-                                                 DontTupleArguments);
+                                                 DontTupleArguments,
+                                                 expected);
 
         write_call(fcx, expr, ret_ty);
     }
@@ -3167,8 +2804,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             None => None
         };
         let args = match rhs {
-            Some(rhs) => vec![rhs],
-            None => vec![]
+            Some(rhs) => slice::ref_slice(rhs),
+            None => &[][]
         };
         match method {
             Some(method) => {
@@ -3177,12 +2814,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
                 match check_method_argument_types(fcx,
-                                            op_ex.span,
-                                            method_ty,
-                                            op_ex,
-                                            args.as_slice(),
-                                            autoref_args,
-                                            DontTupleArguments) {
+                                                  op_ex.span,
+                                                  method_ty,
+                                                  op_ex,
+                                                  args,
+                                                  autoref_args,
+                                                  DontTupleArguments,
+                                                  NoExpectation) {
                     ty::FnConverging(result_type) => result_type,
                     ty::FnDiverging => fcx.tcx().types.err
                 }
@@ -3196,9 +2834,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                             op_ex.span,
                                             expected_ty,
                                             op_ex,
-                                            args.as_slice(),
+                                            args,
                                             autoref_args,
-                                            DontTupleArguments);
+                                            DontTupleArguments,
+                                            NoExpectation);
                 fcx.tcx().types.err
             }
         }
@@ -3398,8 +3037,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                     ty::ty_struct(base_id, substs) => {
                         debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
                         let fields = ty::lookup_struct_fields(tcx, base_id);
-                        lookup_field_ty(tcx, base_id, &fields[],
-                                        field.node.name, &(*substs))
+                        fcx.lookup_field_ty(expr.span, base_id, &fields[],
+                                            field.node.name, &(*substs))
                     }
                     _ => None
                 }
@@ -3461,8 +3100,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                         if tuple_like {
                             debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
                             let fields = ty::lookup_struct_fields(tcx, base_id);
-                            lookup_tup_field_ty(tcx, base_id, &fields[],
-                                                idx.node, &(*substs))
+                            fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
+                                                    idx.node, &(*substs))
                         } else {
                             None
                         }
@@ -3761,7 +3400,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
       }
       ast::ExprUnary(unop, ref oprnd) => {
-        let expected_inner = expected.map(fcx, |ty| {
+        let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
             match unop {
                 ast::UnUniq => match ty.sty {
                     ty::ty_uniq(ty) => {
@@ -3851,8 +3490,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         fcx.write_ty(id, oprnd_t);
       }
       ast::ExprAddrOf(mutbl, ref oprnd) => {
-        let expected = expected.only_has_type();
-        let hint = expected.map(fcx, |ty| {
+        let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
             match ty.sty {
                 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
                     if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
@@ -3914,10 +3552,25 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         };
         fcx.write_ty(id, oprnd_t);
       }
-      ast::ExprPath(ref pth) => {
-          let defn = lookup_def(fcx, pth.span, id);
+      ast::ExprPath(ref path) => {
+          let defn = lookup_def(fcx, path.span, id);
+          let pty = type_scheme_for_def(fcx, expr.span, defn);
+          instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
+
+          // We always require that the type provided as the value for
+          // a type parameter outlives the moment of instantiation.
+          constrain_path_type_parameters(fcx, expr);
+      }
+      ast::ExprQPath(ref qpath) => {
+          // Require explicit type params for the trait.
+          let self_ty = fcx.to_ty(&*qpath.self_type);
+          astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
+
+          let defn = lookup_def(fcx, expr.span, id);
           let pty = type_scheme_for_def(fcx, expr.span, defn);
-          instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
+          let mut path = qpath.trait_ref.path.clone();
+          path.segments.push(qpath.item_path.clone());
+          instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
 
           // We always require that the type provided as the value for
           // a type parameter outlives the moment of instantiation.
@@ -4046,10 +3699,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         fcx.write_ty(id, fcx.node_ty(b.id));
       }
       ast::ExprCall(ref callee, ref args) => {
-          callee::check_call(fcx, expr, &**callee, args.as_slice());
+          callee::check_call(fcx, expr, &**callee, &args[], expected);
       }
       ast::ExprMethodCall(ident, ref tps, ref args) => {
-        check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice(), lvalue_pref);
+        check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
         let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
         let  args_err = arg_tys.fold(false,
              |rest_err, a| {
@@ -4065,7 +3718,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         check_cast(fcx, expr, &**e, &**t);
       }
       ast::ExprVec(ref args) => {
-        let uty = expected.map_to_option(fcx, |uty| {
+        let uty = expected.to_option(fcx).and_then(|uty| {
             match uty.sty {
                 ty::ty_vec(ty, _) => Some(ty),
                 _ => None
@@ -4134,8 +3787,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
       }
       ast::ExprTup(ref elts) => {
-        let expected = expected.only_has_type();
-        let flds = expected.map_to_option(fcx, |ty| {
+        let flds = expected.only_has_type(fcx).and_then(|ty| {
             match ty.sty {
                 ty::ty_tup(ref flds) => Some(&flds[]),
                 _ => None
@@ -4428,13 +4080,6 @@ impl<'tcx> Expectation<'tcx> {
         }
     }
 
-    fn only_has_type(self) -> Expectation<'tcx> {
-        match self {
-            ExpectHasType(t) => ExpectHasType(t),
-            _ => NoExpectation
-        }
-    }
-
     // Resolves `expected` by a single level if it is a variable. If
     // there is no expected type or resolution is not possible (e.g.,
     // no constraints yet present), just returns `None`.
@@ -4458,25 +4103,19 @@ impl<'tcx> Expectation<'tcx> {
         }
     }
 
-    fn map<'a, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Expectation<'tcx> where
-        F: FnOnce(Ty<'tcx>) -> Expectation<'tcx>
-    {
+    fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
-            NoExpectation => NoExpectation,
+            NoExpectation => None,
             ExpectCastableToType(ty) |
             ExpectHasType(ty) |
-            ExpectRvalueLikeUnsized(ty) => unpack(ty),
+            ExpectRvalueLikeUnsized(ty) => Some(ty),
         }
     }
 
-    fn map_to_option<'a, O, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Option<O> where
-        F: FnOnce(Ty<'tcx>) -> Option<O>,
-    {
+    fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
-            NoExpectation => None,
-            ExpectCastableToType(ty) |
-            ExpectHasType(ty) |
-            ExpectRvalueLikeUnsized(ty) => unpack(ty),
+            ExpectHasType(ty) => Some(ty),
+            _ => None
         }
     }
 }
@@ -4994,6 +4633,7 @@ pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   path: &ast::Path,
                                   type_scheme: TypeScheme<'tcx>,
+                                  opt_self_ty: Option<Ty<'tcx>>,
                                   def: def::Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
@@ -5151,6 +4791,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
         }
     }
+    if let Some(self_ty) = opt_self_ty {
+        // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
+        assert_eq!(type_defs.len(subst::SelfSpace), 1);
+        substs.types.push(subst::SelfSpace, self_ty);
+    }
 
     // Now we have to compare the types that the user *actually*
     // provided against the types that were *expected*. If the user
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 89de1ea80fc..e6390212c60 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -56,9 +56,38 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                ty::item_path_str(ccx.tcx, local_def(item.id)));
 
         match item.node {
-            ast::ItemImpl(..) => {
+            /// Right now we check that every default trait implementation
+            /// has an implementation of itself. Basically, a case like:
+            ///
+            /// `impl Trait for T {}`
+            ///
+            /// has a requirement of `T: Trait` which was required for default
+            /// method implementations. Although this could be improved now that
+            /// there's a better infrastructure in place for this, it's being left
+            /// for a follow-up work.
+            ///
+            /// Since there's such a requirement, we need to check *just* positive
+            /// implementations, otherwise things like:
+            ///
+            /// impl !Send for T {}
+            ///
+            /// won't be allowed unless there's an *explicit* implementation of `Send`
+            /// for `T`
+            ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
                 self.check_impl(item);
             }
+            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => {
+                let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id);
+                match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
+                    Some(ty::BoundSend) | Some(ty::BoundSync) => {}
+                    Some(_) | None => {
+                        ccx.tcx.sess.span_err(
+                            item.span,
+                            format!("negative impls are currently \
+                                     allowed just for `Send` and `Sync`").as_slice())
+                    }
+                }
+            }
             ast::ItemFn(..) => {
                 self.check_item_type(item);
             }
diff --git a/src/librustc_typeck/coherence/impls.rs b/src/librustc_typeck/coherence/impls.rs
new file mode 100644
index 00000000000..2719a09f4f5
--- /dev/null
+++ b/src/librustc_typeck/coherence/impls.rs
@@ -0,0 +1,48 @@
+// 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.
+
+//! Implementations checker: builtin traits and default impls are allowed just
+//! for structs and enums.
+
+use middle::ty;
+use syntax::ast::{Item, ItemImpl};
+use syntax::ast;
+use syntax::visit;
+
+pub fn check(tcx: &ty::ctxt) {
+    let mut impls = ImplsChecker { tcx: tcx };
+    visit::walk_crate(&mut impls, tcx.map.krate());
+}
+
+struct ImplsChecker<'cx, 'tcx:'cx> {
+    tcx: &'cx ty::ctxt<'tcx>
+}
+
+impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
+    fn visit_item(&mut self, item: &'v ast::Item) {
+        match item.node {
+            ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => {
+                let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id);
+                if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
+                    match trait_ref.self_ty().sty {
+                        ty::ty_struct(..) | ty::ty_enum(..) => {}
+                        _ => {
+                            self.tcx.sess.span_err(
+                                item.span,
+                                &format!("builtin traits can only be \
+                                          implemented on structs or enums")[]);
+                        }
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+}
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 9d4aa23960d..a7ef4c1e9f2 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -49,6 +49,7 @@ use syntax::visit;
 use util::nodemap::{DefIdMap, FnvHashMap};
 use util::ppaux::Repr;
 
+mod impls;
 mod orphan;
 mod overlap;
 mod unsafety;
@@ -596,6 +597,7 @@ pub fn check_coherence(crate_context: &CrateCtxt) {
         inference_context: new_infer_ctxt(crate_context.tcx),
         inherent_impls: RefCell::new(FnvHashMap::new()),
     }.check(crate_context.tcx.map.krate());
+    impls::check(crate_context.tcx);
     unsafety::check(crate_context.tcx);
     orphan::check(crate_context.tcx);
     overlap::check(crate_context.tcx);
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index f618a79e27d..ce7ba9ac11e 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -38,36 +38,34 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
         // check_for_overlapping_impls_of_trait() check, since that
         // check can populate this table further with impls from other
         // crates.
-        let trait_def_ids: Vec<ast::DefId> =
-            self.tcx.trait_impls.borrow().keys().map(|&d| d).collect();
-
-        for trait_def_id in trait_def_ids.iter() {
-            self.check_for_overlapping_impls_of_trait(*trait_def_id);
+        let trait_def_ids: Vec<(ast::DefId, Vec<ast::DefId>)> =
+            self.tcx.trait_impls.borrow().iter().map(|(&k, v)| {
+                // FIXME -- it seems like this method actually pushes
+                // duplicate impls onto the list
+                ty::populate_implementations_for_trait_if_necessary(self.tcx, k);
+                (k, v.borrow().clone())
+            }).collect();
+
+        for &(trait_def_id, ref impls) in trait_def_ids.iter() {
+            self.check_for_overlapping_impls_of_trait(trait_def_id, impls);
         }
     }
 
     fn check_for_overlapping_impls_of_trait(&self,
-                                            trait_def_id: ast::DefId)
+                                            trait_def_id: ast::DefId,
+                                            trait_impls: &Vec<ast::DefId>)
     {
         debug!("check_for_overlapping_impls_of_trait(trait_def_id={})",
                trait_def_id.repr(self.tcx));
 
-        // FIXME -- it seems like this method actually pushes
-        // duplicate impls onto the list
-        ty::populate_implementations_for_trait_if_necessary(self.tcx,
-                                                            trait_def_id);
-
-        let mut impls = Vec::new();
-        self.push_impls_of_trait(trait_def_id, &mut impls);
-
-        for (i, &impl1_def_id) in impls.iter().enumerate() {
+        for (i, &impl1_def_id) in trait_impls.iter().enumerate() {
             if impl1_def_id.krate != ast::LOCAL_CRATE {
                 // we don't need to check impls if both are external;
                 // that's the other crate's job.
                 continue;
             }
 
-            for &impl2_def_id in impls.slice_from(i+1).iter() {
+            for &impl2_def_id in trait_impls.slice_from(i+1).iter() {
                 self.check_if_impls_overlap(trait_def_id,
                                             impl1_def_id,
                                             impl2_def_id);
@@ -108,15 +106,6 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
         }
     }
 
-    fn push_impls_of_trait(&self,
-                           trait_def_id: ast::DefId,
-                           out: &mut Vec<ast::DefId>) {
-        match self.tcx.trait_impls.borrow().get(&trait_def_id) {
-            Some(impls) => { out.push_all(impls.borrow().as_slice()); }
-            None => { /* no impls */ }
-        }
-    }
-
     fn span_of_impl(&self, impl_did: ast::DefId) -> Span {
         assert_eq!(impl_did.krate, ast::LOCAL_CRATE);
         self.tcx.map.span(impl_did.node)
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index 1acea6fd581..e30d0a29938 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -30,7 +30,7 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         match item.node {
-            ast::ItemImpl(unsafety, _, _, _, _, _) => {
+            ast::ItemImpl(unsafety, polarity, _, _, _, _) => {
                 match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
                     None => {
                         // Inherent impl.
@@ -46,23 +46,34 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
 
                     Some(trait_ref) => {
                         let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
-                        match (trait_def.unsafety, unsafety) {
-                            (ast::Unsafety::Normal, ast::Unsafety::Unsafe) => {
+                        match (trait_def.unsafety, unsafety, polarity) {
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
+                                self.tcx.sess.span_err(
+                                    item.span,
+                                    format!("negative implementations are not unsafe").as_slice());
+                            }
+
+                            (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
                                 self.tcx.sess.span_err(
                                     item.span,
                                     format!("implementing the trait `{}` is not unsafe",
                                             trait_ref.user_string(self.tcx)).as_slice());
                             }
 
-                            (ast::Unsafety::Unsafe, ast::Unsafety::Normal) => {
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
                                 self.tcx.sess.span_err(
                                     item.span,
                                     format!("the trait `{}` requires an `unsafe impl` declaration",
                                             trait_ref.user_string(self.tcx)).as_slice());
                             }
 
-                            (ast::Unsafety::Unsafe, ast::Unsafety::Unsafe) |
-                            (ast::Unsafety::Normal, ast::Unsafety::Normal) => {
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Normal, ast::ImplPolarity::Negative) |
+                            (ast::Unsafety::Unsafe,
+                             ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) |
+                            (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => {
                                 /* OK */
                             }
                         }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index f15d53290e7..47b5cd4b11e 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -79,11 +79,13 @@ This API is completely unstable and subject to change.
 #![feature(rustc_diagnostic_macros)]
 #![allow(unknown_features)] #![feature(int_uint)]
 #![allow(non_camel_case_types)]
+#![allow(unstable)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 
 extern crate arena;
+extern crate fmt_macros;
 extern crate rustc;
 
 pub use rustc::lint;
@@ -107,6 +109,8 @@ use syntax::print::pprust::*;
 use syntax::{ast, ast_map, abi};
 use syntax::ast_util::local_def;
 
+use std::cell::RefCell;
+
 mod check;
 mod rscope;
 mod astconv;
@@ -122,6 +126,11 @@ struct TypeAndSubsts<'tcx> {
 struct CrateCtxt<'a, 'tcx: 'a> {
     // A mapping from method call sites to traits that have that method.
     trait_map: ty::TraitMap,
+    /// A vector of every trait accessible in the whole crate
+    /// (i.e. including those from subcrates). This is used only for
+    /// error reporting, and so is lazily initialised and generally
+    /// shouldn't taint the common path (hence the RefCell).
+    all_traits: RefCell<Option<check::method::AllTraitsVec>>,
     tcx: &'a ty::ctxt<'tcx>,
 }
 
@@ -319,6 +328,7 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
     let time_passes = tcx.sess.time_passes();
     let ccx = CrateCtxt {
         trait_map: trait_map,
+        all_traits: RefCell::new(None),
         tcx: tcx
     };
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 3e2474468ad..ccaefadc1fc 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -126,13 +126,8 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
 
 pub fn load_attrs(cx: &DocContext, tcx: &ty::ctxt,
                   did: ast::DefId) -> Vec<clean::Attribute> {
-    let mut attrs = Vec::new();
-    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
-        attrs.extend(v.into_iter().map(|a| {
-            a.clean(cx)
-        }));
-    });
-    attrs
+    let attrs = csearch::get_item_attrs(&tcx.sess.cstore, did);
+    attrs.into_iter().map(|a| a.clean(cx)).collect()
 }
 
 /// Record an external fully qualified name in the external_paths cache.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a44c73e8c41..8dc3adad3b2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -104,6 +104,12 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
     }
 }
 
+impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
+    fn clean(&self, cx: &DocContext) -> U {
+        self.0.clean(cx)
+    }
+}
+
 impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
     fn clean(&self, cx: &DocContext) -> Vec<U> {
         self.iter().map(|x| x.clean(cx)).collect()
@@ -498,22 +504,28 @@ impl Clean<TyParamBound> for ast::TyParamBound {
     }
 }
 
-impl<'tcx> Clean<Vec<TyParamBound>> for ty::ExistentialBounds<'tcx> {
-    fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
-        let mut vec = vec![];
-        self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b)));
+impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> {
+    fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) {
+        let mut tp_bounds = vec![];
+        self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b)));
         for bb in self.builtin_bounds.iter() {
-            vec.push(bb.clean(cx));
+            tp_bounds.push(bb.clean(cx));
         }
 
-        // FIXME(#20299) -- should do something with projection bounds
+        let mut bindings = vec![];
+        for &ty::Binder(ref pb) in self.projection_bounds.iter() {
+            bindings.push(TypeBinding {
+                name: pb.projection_ty.item_name.clean(cx),
+                ty: pb.ty.clean(cx)
+            });
+        }
 
-        vec
+        (tp_bounds, bindings)
     }
 }
 
 fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
-                        substs: &subst::Substs) -> PathParameters {
+                        bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
     use rustc::middle::ty::sty;
     let lifetimes = substs.regions().get_slice(subst::TypeSpace)
                     .iter()
@@ -531,7 +543,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
                     return PathParameters::AngleBracketed {
                         lifetimes: lifetimes,
                         types: types.clean(cx),
-                        bindings: vec![]
+                        bindings: bindings
                     }
                 }
             };
@@ -548,7 +560,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
             PathParameters::AngleBracketed {
                 lifetimes: lifetimes,
                 types: types.clean(cx),
-                bindings: vec![] // FIXME(#20646)
+                bindings: bindings
             }
         }
     }
@@ -557,12 +569,12 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
 // from Fn<(A, B,), C> to Fn(A, B) -> C
 fn external_path(cx: &DocContext, name: &str, trait_did: Option<ast::DefId>,
-                 substs: &subst::Substs) -> Path {
+                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
     Path {
         global: false,
         segments: vec![PathSegment {
             name: name.to_string(),
-            params: external_path_params(cx, trait_did, substs)
+            params: external_path_params(cx, trait_did, bindings, substs)
         }],
     }
 }
@@ -577,16 +589,16 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
         let (did, path) = match *self {
             ty::BoundSend =>
                 (tcx.lang_items.send_trait().unwrap(),
-                 external_path(cx, "Send", None, &empty)),
+                 external_path(cx, "Send", None, vec![], &empty)),
             ty::BoundSized =>
                 (tcx.lang_items.sized_trait().unwrap(),
-                 external_path(cx, "Sized", None, &empty)),
+                 external_path(cx, "Sized", None, vec![], &empty)),
             ty::BoundCopy =>
                 (tcx.lang_items.copy_trait().unwrap(),
-                 external_path(cx, "Copy", None, &empty)),
+                 external_path(cx, "Copy", None, vec![], &empty)),
             ty::BoundSync =>
                 (tcx.lang_items.sync_trait().unwrap(),
-                 external_path(cx, "Sync", None, &empty)),
+                 external_path(cx, "Sync", None, vec![], &empty)),
         };
         let fqn = csearch::get_item_path(tcx, did);
         let fqn = fqn.into_iter().map(|i| i.to_string()).collect();
@@ -603,12 +615,6 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
     }
 }
 
-impl<'tcx> Clean<TyParamBound> for ty::PolyTraitRef<'tcx> {
-    fn clean(&self, cx: &DocContext) -> TyParamBound {
-        self.0.clean(cx)
-    }
-}
-
 impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         let tcx = match cx.tcx_opt() {
@@ -619,7 +625,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         let fqn = fqn.into_iter().map(|i| i.to_string())
                      .collect::<Vec<String>>();
         let path = external_path(cx, fqn.last().unwrap().as_slice(),
-                                 Some(self.def_id), self.substs);
+                                 Some(self.def_id), vec![], self.substs);
         cx.external_paths.borrow_mut().as_mut().unwrap().insert(self.def_id,
                                                             (fqn, TypeTrait));
 
@@ -730,8 +736,7 @@ impl Clean<Option<Lifetime>> for ty::Region {
 pub enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
     RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
-    // FIXME (#20041)
-    EqPredicate
+    EqPredicate { lhs: Type, rhs: Type }
 }
 
 impl Clean<WherePredicate> for ast::WherePredicate {
@@ -752,12 +757,89 @@ impl Clean<WherePredicate> for ast::WherePredicate {
             }
 
             ast::WherePredicate::EqPredicate(_) => {
-                WherePredicate::EqPredicate
+                unimplemented!() // FIXME(#20041)
             }
         }
     }
 }
 
+impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        use rustc::middle::ty::Predicate;
+
+        match *self {
+            Predicate::Trait(ref pred) => pred.clean(cx),
+            Predicate::Equate(ref pred) => pred.clean(cx),
+            Predicate::RegionOutlives(ref pred) => pred.clean(cx),
+            Predicate::TypeOutlives(ref pred) => pred.clean(cx),
+            Predicate::Projection(ref pred) => pred.clean(cx)
+        }
+    }
+}
+
+impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        WherePredicate::BoundPredicate {
+            ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(),
+            bounds: vec![self.trait_ref.clean(cx)]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::EquatePredicate(ref lhs, ref rhs) = *self;
+        WherePredicate::EqPredicate {
+            lhs: lhs.clean(cx),
+            rhs: rhs.clean(cx)
+        }
+    }
+}
+
+impl Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region, ty::Region> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::OutlivesPredicate(ref a, ref b) = *self;
+        WherePredicate::RegionPredicate {
+            lifetime: a.clean(cx).unwrap(),
+            bounds: vec![b.clean(cx).unwrap()]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Ty<'tcx>, ty::Region> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::OutlivesPredicate(ref ty, ref lt) = *self;
+
+        WherePredicate::BoundPredicate {
+            ty: ty.clean(cx),
+            bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        WherePredicate::EqPredicate {
+            lhs: self.projection_ty.clean(cx),
+            rhs: self.ty.clean(cx)
+        }
+    }
+}
+
+impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
+    fn clean(&self, cx: &DocContext) -> Type {
+        let trait_ = match self.trait_ref.clean(cx) {
+            TyParamBound::TraitBound(t, _) => t.trait_,
+            TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"),
+        };
+        Type::QPath {
+            name: self.item_name.clean(cx),
+            self_type: box self.trait_ref.self_ty().clean(cx),
+            trait_: box trait_
+        }
+    }
+}
+
 // maybe use a Generic enum and use ~[Generic]?
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
 pub struct Generics {
@@ -778,11 +860,80 @@ impl Clean<Generics> for ast::Generics {
 
 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, subst::ParamSpace) {
     fn clean(&self, cx: &DocContext) -> Generics {
-        let (me, space) = *self;
+        use std::collections::HashSet;
+        use syntax::ast::TraitBoundModifier as TBM;
+        use self::WherePredicate as WP;
+
+        fn has_sized_bound(bounds: &[TyParamBound], cx: &DocContext) -> bool {
+            if let Some(tcx) = cx.tcx_opt() {
+                let sized_did = match tcx.lang_items.sized_trait() {
+                    Some(did) => did,
+                    None => return false
+                };
+                for bound in bounds.iter() {
+                    if let TyParamBound::TraitBound(PolyTrait {
+                        trait_: Type::ResolvedPath { did, .. }, ..
+                    }, TBM::None) = *bound {
+                        if did == sized_did {
+                            return true
+                        }
+                    }
+                }
+            }
+            false
+        }
+
+        let (gens, space) = *self;
+        // Bounds in the type_params and lifetimes fields are repeated in the predicates
+        // field (see rustc_typeck::collect::ty_generics), so remove them.
+        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
+            let mut stp = tp.clone();
+            stp.bounds = ty::ParamBounds::empty();
+            stp.clean(cx)
+        }).collect::<Vec<_>>();
+        let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
+            let mut srp = rp.clone();
+            srp.bounds = Vec::new();
+            srp.clean(cx)
+        }).collect::<Vec<_>>();
+
+        let where_predicates = gens.predicates.get_slice(space).to_vec().clean(cx);
+        // Type parameters have a Sized bound by default unless removed with ?Sized.
+        // Scan through the predicates and mark any type parameter with a Sized
+        // bound, removing the bounds as we find them.
+        let mut sized_params = HashSet::new();
+        let mut where_predicates = where_predicates.into_iter().filter_map(|pred| {
+            if let WP::BoundPredicate { ty: Type::Generic(ref g), ref bounds } = pred {
+                if has_sized_bound(&**bounds, cx) {
+                    sized_params.insert(g.clone());
+                    return None
+                }
+            }
+            Some(pred)
+        }).collect::<Vec<_>>();
+        // Finally, run through the type parameters again and insert a ?Sized unbound for
+        // any we didn't find to be Sized.
+        for tp in stripped_typarams.iter() {
+            if !sized_params.contains(&tp.name) {
+                let mut sized_bound = ty::BuiltinBound::BoundSized.clean(cx);
+                if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
+                    *tbm = TBM::Maybe
+                };
+                where_predicates.push(WP::BoundPredicate {
+                    ty: Type::Generic(tp.name.clone()),
+                    bounds: vec![sized_bound]
+                })
+            }
+        }
+
+        // It would be nice to collect all of the bounds on a type and recombine
+        // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
+        // and instead see `where T: Foo + Bar + Sized + 'a`
+
         Generics {
-            type_params: me.types.get_slice(space).to_vec().clean(cx),
-            lifetimes: me.regions.get_slice(space).to_vec().clean(cx),
-            where_predicates: vec![]
+            type_params: stripped_typarams,
+            lifetimes: stripped_lifetimes,
+            where_predicates: where_predicates
         }
     }
 }
@@ -911,27 +1062,6 @@ impl Clean<Item> for doctree::Function {
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
-pub struct ClosureDecl {
-    pub lifetimes: Vec<Lifetime>,
-    pub decl: FnDecl,
-    pub onceness: ast::Onceness,
-    pub unsafety: ast::Unsafety,
-    pub bounds: Vec<TyParamBound>,
-}
-
-impl Clean<ClosureDecl> for ast::ClosureTy {
-    fn clean(&self, cx: &DocContext) -> ClosureDecl {
-        ClosureDecl {
-            lifetimes: self.lifetimes.clean(cx),
-            decl: self.decl.clean(cx),
-            onceness: self.onceness,
-            unsafety: self.unsafety,
-            bounds: self.bounds.clean(cx)
-        }
-    }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
 pub struct FnDecl {
     pub inputs: Arguments,
     pub output: FunctionRetTy,
@@ -1207,8 +1337,6 @@ pub enum Type {
     Generic(String),
     /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
     Primitive(PrimitiveType),
-    Closure(Box<ClosureDecl>),
-    Proc(Box<ClosureDecl>),
     /// extern "ABI" fn
     BareFunction(Box<BareFunctionDecl>),
     Tuple(Vec<Type>),
@@ -1436,7 +1564,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     _ => TypeEnum,
                 };
                 let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
-                                         None, substs);
+                                         None, vec![], substs);
                 cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, kind));
                 ResolvedPath {
                     path: path,
@@ -1448,12 +1576,13 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 let did = principal.def_id();
                 let fqn = csearch::get_item_path(cx.tcx(), did);
                 let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
+                let (typarams, bindings) = bounds.clean(cx);
                 let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
-                                         Some(did), principal.substs());
+                                         Some(did), bindings, principal.substs());
                 cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, TypeTrait));
                 ResolvedPath {
                     path: path,
-                    typarams: Some(bounds.clean(cx)),
+                    typarams: Some(typarams),
                     did: did,
                 }
             }
@@ -1485,7 +1614,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
 impl Clean<Type> for ast::QPath {
     fn clean(&self, cx: &DocContext) -> Type {
         Type::QPath {
-            name: self.item_name.clean(cx),
+            name: self.item_path.identifier.clean(cx),
             self_type: box self.self_type.clean(cx),
             trait_: box self.trait_ref.clean(cx)
         }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 4885bd373eb..5bef0195874 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -16,6 +16,7 @@ use rustc::session::search_paths::SearchPaths;
 use rustc::middle::{privacy, ty};
 use rustc::lint;
 use rustc_trans::back::link;
+use rustc_resolve as resolve;
 
 use syntax::{ast, ast_map, codemap, diagnostic};
 
@@ -126,7 +127,11 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
     let arenas = ty::CtxtArenas::new();
     let ty::CrateAnalysis {
         exported_items, public_items, ty_cx, ..
-    } = driver::phase_3_run_analysis_passes(sess, ast_map, &arenas, name);
+    } = driver::phase_3_run_analysis_passes(sess,
+                                            ast_map,
+                                            &arenas,
+                                            name,
+                                            resolve::MakeGlobMap::No);
 
     let ctxt = DocContext {
         krate: ty_cx.map.krate(),
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 00f7c570b5d..d13936b2168 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -153,8 +153,8 @@ impl<'a> fmt::String for WhereClause<'a> {
                         try!(write!(f, "{}", lifetime));
                     }
                 }
-                &clean::WherePredicate::EqPredicate => {
-                    unimplemented!()
+                &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
+                    try!(write!(f, "{} == {}", lhs, rhs));
                 }
             }
         }
@@ -332,7 +332,7 @@ fn path<F, G>(w: &mut fmt::Formatter,
         match rel_root {
             Some(root) => {
                 let mut root = String::from_str(root.as_slice());
-                for seg in path.segments[0..amt].iter() {
+                for seg in path.segments[..amt].iter() {
                     if "super" == seg.name ||
                             "self" == seg.name {
                         try!(write!(w, "{}::", seg.name));
@@ -347,7 +347,7 @@ fn path<F, G>(w: &mut fmt::Formatter,
                 }
             }
             None => {
-                for seg in path.segments[0..amt].iter() {
+                for seg in path.segments[..amt].iter() {
                     try!(write!(w, "{}::", seg.name));
                 }
             }
@@ -465,61 +465,6 @@ impl fmt::String for clean::Type {
             }
             clean::Infer => write!(f, "_"),
             clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()),
-            clean::Closure(ref decl) => {
-                write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}",
-                       style = UnsafetySpace(decl.unsafety),
-                       lifetimes = if decl.lifetimes.len() == 0 {
-                           "".to_string()
-                       } else {
-                           format!("for &lt;{}&gt;",
-                                   CommaSep(decl.lifetimes.as_slice()))
-                       },
-                       args = decl.decl.inputs,
-                       arrow = decl.decl.output,
-                       bounds = {
-                           let mut ret = String::new();
-                           for bound in decl.bounds.iter() {
-                                match *bound {
-                                    clean::RegionBound(..) => {}
-                                    clean::TraitBound(ref t, modifier) => {
-                                        if ret.len() == 0 {
-                                            ret.push_str(": ");
-                                        } else {
-                                            ret.push_str(" + ");
-                                        }
-                                        if modifier == ast::TraitBoundModifier::Maybe {
-                                            ret.push_str("?");
-                                        }
-                                        ret.push_str(format!("{}",
-                                                             *t).as_slice());
-                                    }
-                                }
-                           }
-                           ret
-                       })
-            }
-            clean::Proc(ref decl) => {
-                write!(f, "{style}{lifetimes}proc({args}){bounds}{arrow}",
-                       style = UnsafetySpace(decl.unsafety),
-                       lifetimes = if decl.lifetimes.len() == 0 {
-                           "".to_string()
-                       } else {
-                           format!("for &lt;{}&gt;",
-                                   CommaSep(decl.lifetimes.as_slice()))
-                       },
-                       args = decl.decl.inputs,
-                       bounds = if decl.bounds.len() == 0 {
-                           "".to_string()
-                       } else {
-                           let m = decl.bounds
-                                           .iter()
-                                           .map(|s| s.to_string());
-                           format!(
-                               ": {}",
-                               m.collect::<Vec<String>>().connect(" + "))
-                       },
-                       arrow = decl.decl.output)
-            }
             clean::BareFunction(ref decl) => {
                 write!(f, "{}{}fn{}{}",
                        UnsafetySpace(decl.unsafety),
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index a063191a12f..0dbd13b4616 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -30,7 +30,7 @@
 use libc;
 use std::ascii::AsciiExt;
 use std::ffi::CString;
-use std::cell::{RefCell, Cell};
+use std::cell::RefCell;
 use std::collections::HashMap;
 use std::fmt;
 use std::slice;
@@ -155,7 +155,6 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
 thread_local!(static USED_HEADER_MAP: RefCell<HashMap<String, uint>> = {
     RefCell::new(HashMap::new())
 });
-thread_local!(static TEST_IDX: Cell<uint> = Cell::new(0));
 
 thread_local!(pub static PLAYGROUND_KRATE: RefCell<Option<Option<String>>> = {
     RefCell::new(None)
@@ -195,26 +194,19 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
             if rendered { return }
             PLAYGROUND_KRATE.with(|krate| {
                 let mut s = String::new();
-                let id = krate.borrow().as_ref().map(|krate| {
-                    let idx = TEST_IDX.with(|slot| {
-                        let i = slot.get();
-                        slot.set(i + 1);
-                        i
-                    });
-
+                krate.borrow().as_ref().map(|krate| {
                     let test = origtext.lines().map(|l| {
                         stripped_filtered_line(l).unwrap_or(l)
                     }).collect::<Vec<&str>>().connect("\n");
                     let krate = krate.as_ref().map(|s| s.as_slice());
                     let test = test::maketest(test.as_slice(), krate, false, false);
-                    s.push_str(format!("<span id='rust-example-raw-{}' \
-                                         class='rusttest'>{}</span>",
-                                       idx, Escape(test.as_slice())).as_slice());
-                    format!("rust-example-rendered-{}", idx)
+                    s.push_str(format!("<span class='rusttest'>{}</span>",
+                                         Escape(test.as_slice())).as_slice());
                 });
-                let id = id.as_ref().map(|a| a.as_slice());
-                s.push_str(highlight::highlight(text.as_slice(), None, id)
-                                     .as_slice());
+                s.push_str(highlight::highlight(text.as_slice(),
+                                                None,
+                                                Some("rust-example-rendered"))
+                             .as_slice());
                 let output = CString::from_vec(s.into_bytes());
                 hoedown_buffer_puts(ob, output.as_ptr());
             })
@@ -432,7 +424,6 @@ impl LangString {
 /// previous state (if any).
 pub fn reset_headers() {
     USED_HEADER_MAP.with(|s| s.borrow_mut().clear());
-    TEST_IDX.with(|s| s.set(0));
 }
 
 impl<'a> fmt::String for Markdown<'a> {
diff --git a/src/librustdoc/html/static/playpen.js b/src/librustdoc/html/static/playpen.js
index 473a20086ed..687f764f020 100644
--- a/src/librustdoc/html/static/playpen.js
+++ b/src/librustdoc/html/static/playpen.js
@@ -14,9 +14,8 @@
 (function() {
     if (window.playgroundUrl) {
         $('pre.rust').hover(function() {
-            var id = '#' + $(this).attr('id').replace('rendered', 'raw');
             var a = $('<a>').text('⇱').attr('class', 'test-arrow');
-            var code = $(id).text();
+            var code = $(this).siblings(".rusttest").text();
             a.attr('href', window.playgroundUrl + '?code=' +
                            encodeURIComponent(code));
             a.attr('target', '_blank');
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 6d5df3d777d..71bd53009af 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -20,6 +20,7 @@
 #![feature(slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate arena;
 extern crate getopts;
@@ -27,6 +28,7 @@ extern crate libc;
 extern crate rustc;
 extern crate rustc_trans;
 extern crate rustc_driver;
+extern crate rustc_resolve;
 extern crate serialize;
 extern crate syntax;
 extern crate "test" as testing;
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index ab9c4ef9422..dc98a56eb1a 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -91,6 +91,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches,
 <html lang="en">
 <head>
     <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="generator" content="rustdoc">
     <title>{title}</title>
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 38ce7389546..9b8d220acc3 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -123,7 +123,6 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
         search_paths: libs,
         crate_types: vec!(config::CrateTypeExecutable),
         output_types: vec!(config::OutputTypeExe),
-        no_trans: no_run,
         externs: externs,
         cg: config::CodegenOptions {
             prefer_dynamic: true,
@@ -170,14 +169,18 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
     let sess = session::build_session_(sessopts,
-                                      None,
-                                      span_diagnostic_handler);
+                                       None,
+                                       span_diagnostic_handler);
 
     let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
     let out = Some(outdir.path().clone());
     let cfg = config::build_configuration(&sess);
     let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
-    driver::compile_input(sess, cfg, &input, &out, &None, None);
+    let mut control = driver::CompileController::basic();
+    if no_run {
+        control.after_analysis.stop = true;
+    }
+    driver::compile_input(sess, cfg, &input, &out, &None, None, control);
 
     if no_run { return }
 
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index 62acef2ca1c..41499b5ae0e 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -401,7 +401,7 @@ fn escape_str(wr: &mut fmt::Writer, v: &str) -> fmt::Result {
 fn escape_char(writer: &mut fmt::Writer, v: char) -> fmt::Result {
     let mut buf = [0; 4];
     let n = v.encode_utf8(&mut buf).unwrap();
-    let buf = unsafe { str::from_utf8_unchecked(&buf[0..n]) };
+    let buf = unsafe { str::from_utf8_unchecked(&buf[..n]) };
     escape_str(writer, buf)
 }
 
@@ -414,7 +414,7 @@ fn spaces(wr: &mut fmt::Writer, mut n: uint) -> fmt::Result {
     }
 
     if n > 0 {
-        wr.write_str(&BUF[0..n])
+        wr.write_str(&BUF[..n])
     } else {
         Ok(())
     }
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index 942a8cfa2c5..b24e1bd685f 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -24,11 +24,11 @@ Core encoding and decoding interfaces.
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![allow(unknown_features)]
-#![cfg_attr(stage0, allow(unused_attributes))]
 #![feature(box_syntax)]
 #![feature(old_impl_check)]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 // test harness access
 #[cfg(test)] extern crate test;
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index c3bdfbb12d8..80ae3076df3 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -20,7 +20,7 @@ use cmp::{max, Eq, PartialEq};
 use default::Default;
 use fmt::{self, Show};
 use hash::{self, Hash, SipHasher};
-use iter::{self, Iterator, IteratorExt, FromIterator, Extend, Map};
+use iter::{self, Iterator, ExactSizeIterator, IteratorExt, FromIterator, Extend, Map};
 use marker::Sized;
 use mem::{self, replace};
 use num::{Int, UnsignedInt};
@@ -1384,7 +1384,11 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
 
     #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1392,7 +1396,11 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
 
     #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1400,7 +1408,11 @@ impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (K, V);
 
     #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1408,7 +1420,11 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
 
     #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1416,21 +1432,23 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
     type Item = &'a V;
 
     #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
-impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> {
+impl<'a, K, V> Iterator for Drain<'a, K, V> {
     type Item = (K, V);
 
-    #[inline]
-    fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        self.inner.size_hint()
-    }
+    #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
@@ -2136,6 +2154,19 @@ mod test_map {
     }
 
     #[test]
+    fn test_iter_len() {
+        let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+        let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+        let mut iter = map.iter();
+
+        for _ in iter.by_ref().take(3) {}
+
+        assert_eq!(iter.len(), 3);
+    }
+
+    #[test]
     fn test_mut_size_hint() {
         let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
 
@@ -2149,6 +2180,19 @@ mod test_map {
     }
 
     #[test]
+    fn test_iter_mut_len() {
+        let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+        let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+        let mut iter = map.iter_mut();
+
+        for _ in iter.by_ref().take(3) {}
+
+        assert_eq!(iter.len(), 3);
+    }
+
+    #[test]
     fn test_index() {
         let mut map: HashMap<int, int> = HashMap::new();
 
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 4003d3addf1..1293f45161d 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -18,7 +18,7 @@ use default::Default;
 use fmt::Show;
 use fmt;
 use hash::{self, Hash};
-use iter::{Iterator, IteratorExt, FromIterator, Map, Chain, Extend};
+use iter::{Iterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend};
 use ops::{BitOr, BitAnd, BitXor, Sub};
 use option::Option::{Some, None, self};
 
@@ -837,7 +837,11 @@ impl<'a, K> Iterator for Iter<'a, K> {
     type Item = &'a K;
 
     fn next(&mut self) -> Option<&'a K> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable]
+impl<'a, K> ExactSizeIterator for Iter<'a, K> {
+    fn len(&self) -> usize { self.iter.len() }
 }
 
 #[stable]
@@ -845,15 +849,23 @@ impl<K> Iterator for IntoIter<K> {
     type Item = K;
 
     fn next(&mut self) -> Option<K> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable]
+impl<K> ExactSizeIterator for IntoIter<K> {
+    fn len(&self) -> usize { self.iter.len() }
 }
 
 #[stable]
-impl<'a, K: 'a> Iterator for Drain<'a, K> {
+impl<'a, K> Iterator for Drain<'a, K> {
     type Item = K;
 
     fn next(&mut self) -> Option<K> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable]
+impl<'a, K> ExactSizeIterator for Drain<'a, K> {
+    fn len(&self) -> usize { self.iter.len() }
 }
 
 #[stable]
@@ -875,7 +887,7 @@ impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
         }
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper)
     }
@@ -900,7 +912,7 @@ impl<'a, T, S, H> Iterator for Difference<'a, T, S>
         }
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper)
     }
@@ -915,7 +927,7 @@ impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
 #[stable]
@@ -927,7 +939,7 @@ impl<'a, T, S, H> Iterator for Union<'a, T, S>
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
 #[cfg(test)]
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 456f3763b39..f28b95dbe95 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -15,7 +15,7 @@ use self::BucketState::*;
 use clone::Clone;
 use cmp;
 use hash::{Hash, Hasher};
-use iter::{Iterator, count};
+use iter::{Iterator, ExactSizeIterator, count};
 use marker::{Copy, Sized, self};
 use mem::{min_align_of, size_of};
 use mem;
@@ -838,10 +838,13 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         (self.elems_left, Some(self.elems_left))
     }
 }
+impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
+    fn len(&self) -> usize { self.elems_left }
+}
 
 impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
@@ -856,10 +859,13 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         (self.elems_left, Some(self.elems_left))
     }
 }
+impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
+    fn len(&self) -> usize { self.elems_left }
+}
 
 impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (SafeHash, K, V);
@@ -879,13 +885,16 @@ impl<K, V> Iterator for IntoIter<K, V> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let size = self.table.size();
         (size, Some(size))
     }
 }
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+    fn len(&self) -> usize { self.table.size() }
+}
 
-impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> {
+impl<'a, K, V> Iterator for Drain<'a, K, V> {
     type Item = (SafeHash, K, V);
 
     #[inline]
@@ -904,11 +913,14 @@ impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let size = self.table.size();
         (size, Some(size))
     }
 }
+impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
+    fn len(&self) -> usize { self.table.size() }
+}
 
 #[unsafe_destructor]
 impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs
index 907925e93d3..36afa0956d2 100644
--- a/src/libstd/fmt.rs
+++ b/src/libstd/fmt.rs
@@ -26,15 +26,13 @@
 //!
 //! Some examples of the `format!` extension are:
 //!
-//! ```rust
-//! # fn main() {
+//! ```
 //! format!("Hello");                  // => "Hello"
 //! format!("Hello, {}!", "world");    // => "Hello, world!"
 //! format!("The number is {}", 1i);   // => "The number is 1"
 //! format!("{:?}", (3i, 4i));         // => "(3i, 4i)"
 //! format!("{value}", value=4i);      // => "4"
 //! format!("{} {}", 1i, 2u);          // => "1 2"
-//! # }
 //! ```
 //!
 //! From these, you can see that the first argument is a format string. It is
@@ -83,12 +81,10 @@
 //!
 //! For example, the following `format!` expressions all use named argument:
 //!
-//! ```rust
-//! # fn main() {
+//! ```
 //! format!("{argument}", argument = "test");   // => "test"
 //! format!("{name} {}", 1i, name = 2i);        // => "2 1"
 //! format!("{a} {c} {b}", a="a", b='b', c=3i);  // => "a 3 b"
-//! # }
 //! ```
 //!
 //! It is illegal to put positional parameters (those without names) after
@@ -288,8 +284,6 @@
 //! use std::fmt;
 //! use std::io;
 //!
-//! # #[allow(unused_must_use)]
-//! # fn main() {
 //! fmt::format(format_args!("this returns {}", "String"));
 //!
 //! let some_writer: &mut io::Writer = &mut io::stdout();
@@ -299,7 +293,6 @@
 //!     write!(&mut io::stdout(), "{}", args);
 //! }
 //! my_fmt_fn(format_args!("or a {} too", "function"));
-//! # }
 //! ```
 //!
 //! The result of the `format_args!` macro is a value of type `fmt::Arguments`.
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index ba13bd05dc5..8c38bc009cc 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -13,8 +13,9 @@
 //! Buffering wrappers for I/O traits
 
 use cmp;
+use fmt;
 use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
-use iter::{IteratorExt, ExactSizeIterator};
+use iter::{IteratorExt, ExactSizeIterator, repeat};
 use ops::Drop;
 use option::Option;
 use option::Option::{Some, None};
@@ -51,20 +52,21 @@ pub struct BufferedReader<R> {
     cap: uint,
 }
 
+impl<R> fmt::Show for BufferedReader<R> where R: fmt::Show {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "BufferedReader {{ reader: {:?}, buffer: {}/{} }}",
+               self.inner, self.cap - self.pos, self.buf.len())
+    }
+}
+
 impl<R: Reader> BufferedReader<R> {
     /// Creates a new `BufferedReader` with the specified buffer capacity
     pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> {
-        // It's *much* faster to create an uninitialized buffer than it is to
-        // fill everything in with 0. This buffer is entirely an implementation
-        // detail and is never exposed, so we're safe to not initialize
-        // everything up-front. This allows creation of BufferedReader instances
-        // to be very cheap (large mallocs are not nearly as expensive as large
-        // callocs).
-        let mut buf = Vec::with_capacity(cap);
-        unsafe { buf.set_len(cap); }
         BufferedReader {
             inner: inner,
-            buf: buf,
+            // We can't use the same trick here as we do for BufferedWriter,
+            // since this memory is visible to the inner Reader.
+            buf: repeat(0).take(cap).collect(),
             pos: 0,
             cap: 0,
         }
@@ -114,7 +116,7 @@ impl<R: Reader> Reader for BufferedReader<R> {
         let nread = {
             let available = try!(self.fill_buf());
             let nread = cmp::min(available.len(), buf.len());
-            slice::bytes::copy_memory(buf, &available[0..nread]);
+            slice::bytes::copy_memory(buf, &available[..nread]);
             nread
         };
         self.pos += nread;
@@ -148,10 +150,22 @@ pub struct BufferedWriter<W> {
     pos: uint
 }
 
+impl<W> fmt::Show for BufferedWriter<W> where W: fmt::Show {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
+               self.inner.as_ref().unwrap(), self.pos, self.buf.len())
+    }
+}
+
 impl<W: Writer> BufferedWriter<W> {
     /// Creates a new `BufferedWriter` with the specified buffer capacity
     pub fn with_capacity(cap: uint, inner: W) -> BufferedWriter<W> {
-        // See comments in BufferedReader for why this uses unsafe code.
+        // It's *much* faster to create an uninitialized buffer than it is to
+        // fill everything in with 0. This buffer is entirely an implementation
+        // detail and is never exposed, so we're safe to not initialize
+        // everything up-front. This allows creation of BufferedWriter instances
+        // to be very cheap (large mallocs are not nearly as expensive as large
+        // callocs).
         let mut buf = Vec::with_capacity(cap);
         unsafe { buf.set_len(cap); }
         BufferedWriter {
@@ -168,7 +182,7 @@ impl<W: Writer> BufferedWriter<W> {
 
     fn flush_buf(&mut self) -> IoResult<()> {
         if self.pos != 0 {
-            let ret = self.inner.as_mut().unwrap().write(&self.buf[0..self.pos]);
+            let ret = self.inner.as_mut().unwrap().write(&self.buf[..self.pos]);
             self.pos = 0;
             ret
         } else {
@@ -235,6 +249,13 @@ pub struct LineBufferedWriter<W> {
     inner: BufferedWriter<W>,
 }
 
+impl<W> fmt::Show for LineBufferedWriter<W> where W: fmt::Show {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
+               self.inner.inner, self.inner.pos, self.inner.buf.len())
+    }
+}
+
 impl<W: Writer> LineBufferedWriter<W> {
     /// Creates a new `LineBufferedWriter`
     pub fn new(inner: W) -> LineBufferedWriter<W> {
@@ -260,7 +281,7 @@ impl<W: Writer> Writer for LineBufferedWriter<W> {
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         match buf.iter().rposition(|&b| b == b'\n') {
             Some(i) => {
-                try!(self.inner.write(&buf[0..(i + 1)]));
+                try!(self.inner.write(&buf[..(i + 1)]));
                 try!(self.inner.flush());
                 try!(self.inner.write(&buf[(i + 1)..]));
                 Ok(())
@@ -318,6 +339,17 @@ pub struct BufferedStream<S> {
     inner: BufferedReader<InternalBufferedWriter<S>>
 }
 
+impl<S> fmt::Show for BufferedStream<S> where S: fmt::Show {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        let reader = &self.inner;
+        let writer = &self.inner.inner.0;
+        write!(fmt, "BufferedStream {{ stream: {:?}, write_buffer: {}/{}, read_buffer: {}/{} }}",
+               writer.inner,
+               writer.pos, writer.buf.len(),
+               reader.cap - reader.pos, reader.buf.len())
+    }
+}
+
 impl<S: Stream> BufferedStream<S> {
     /// Creates a new buffered stream with explicitly listed capacities for the
     /// reader/writer buffer.
diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs
index b578f4d5adc..4b0014c68f7 100644
--- a/src/libstd/io/comm_adapters.rs
+++ b/src/libstd/io/comm_adapters.rs
@@ -90,7 +90,7 @@ impl Reader for ChanReader {
                 Some(src) => {
                     let dst = buf.slice_from_mut(num_read);
                     let count = cmp::min(src.len(), dst.len());
-                    bytes::copy_memory(dst, &src[0..count]);
+                    bytes::copy_memory(dst, &src[..count]);
                     count
                 },
                 None => 0,
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index dbccc81c4cc..64406d88253 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -889,7 +889,7 @@ mod test {
             let mut read_buf = [0; 1028];
             let read_str = match check!(read_stream.read(&mut read_buf)) {
                 -1|0 => panic!("shouldn't happen"),
-                n => str::from_utf8(&read_buf[0..n]).unwrap().to_string()
+                n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
             };
             assert_eq!(read_str.as_slice(), message);
         }
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index c5e289398e0..ee05a9e5596 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -204,7 +204,7 @@ impl<'a> Reader for &'a [u8] {
 
         let write_len = min(buf.len(), self.len());
         {
-            let input = &self[0..write_len];
+            let input = &self[..write_len];
             let output = buf.slice_to_mut(write_len);
             slice::bytes::copy_memory(output, input);
         }
@@ -286,7 +286,7 @@ impl<'a> Writer for BufWriter<'a> {
 
             Ok(())
         } else {
-            slice::bytes::copy_memory(dst, &src[0..dst_len]);
+            slice::bytes::copy_memory(dst, &src[..dst_len]);
 
             self.pos += dst_len;
 
@@ -498,7 +498,7 @@ mod test {
         assert_eq!(buf, b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[0..3], b);
+        assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
         assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
@@ -524,7 +524,7 @@ mod test {
         assert_eq!(buf.as_slice(), b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[0..3], b);
+        assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = &mut in_buf.as_slice();
         assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
@@ -551,7 +551,7 @@ mod test {
         assert_eq!(buf, b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[0..3], b);
+        assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = BufReader::new(in_buf.as_slice());
         assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 3968dda2a82..e2b71cd43af 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -934,16 +934,15 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
 /// A `RefReader` is a struct implementing `Reader` which contains a reference
 /// to another reader. This is often useful when composing streams.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
-/// # fn main() {}
-/// # fn process_input<R: Reader>(r: R) {}
-/// # fn foo() {
 /// use std::io;
 /// use std::io::ByRefReader;
 /// use std::io::util::LimitReader;
 ///
+/// fn process_input<R: Reader>(r: R) {}
+///
 /// let mut stream = io::stdin();
 ///
 /// // Only allow the function to process at most one kilobyte of input
@@ -953,8 +952,6 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
 /// }
 ///
 /// // 'stream' is still available for use here
-///
-/// # }
 /// ```
 pub struct RefReader<'a, R:'a> {
     /// The underlying reader which this is referencing
@@ -1069,7 +1066,7 @@ pub trait Writer {
     fn write_char(&mut self, c: char) -> IoResult<()> {
         let mut buf = [0u8; 4];
         let n = c.encode_utf8(buf.as_mut_slice()).unwrap_or(0);
-        self.write(&buf[0..n])
+        self.write(&buf[..n])
     }
 
     /// Write the result of passing n through `int::to_str_bytes`.
@@ -1269,12 +1266,11 @@ impl<'a> Writer for &'a mut (Writer+'a) {
 /// # Example
 ///
 /// ```
-/// # fn main() {}
-/// # fn process_input<R: Reader>(r: R) {}
-/// # fn foo () {
 /// use std::io::util::TeeReader;
 /// use std::io::{stdin, ByRefWriter};
 ///
+/// fn process_input<R: Reader>(r: R) {}
+///
 /// let mut output = Vec::new();
 ///
 /// {
@@ -1285,7 +1281,6 @@ impl<'a> Writer for &'a mut (Writer+'a) {
 /// }
 ///
 /// println!("input processed: {:?}", output);
-/// # }
 /// ```
 pub struct RefWriter<'a, W:'a> {
     /// The underlying writer which this is referencing
@@ -1454,7 +1449,7 @@ pub trait Buffer: Reader {
                 };
                 match available.iter().position(|&b| b == byte) {
                     Some(i) => {
-                        res.push_all(&available[0..(i + 1)]);
+                        res.push_all(&available[..(i + 1)]);
                         used = i + 1;
                         break
                     }
@@ -1493,7 +1488,7 @@ pub trait Buffer: Reader {
                 }
             }
         }
-        match str::from_utf8(&buf[0..width]).ok() {
+        match str::from_utf8(&buf[..width]).ok() {
             Some(s) => Ok(s.char_at(0)),
             None => Err(standard_error(InvalidInput))
         }
@@ -1705,19 +1700,19 @@ pub enum FileType {
 /// A structure used to describe metadata information about a file. This
 /// structure is created through the `stat` method on a `Path`.
 ///
-/// # Example
+/// # Examples
+///
+/// ```no_run
+/// # #![allow(unstable)]
+///
+/// use std::io::fs::PathExtensions;
 ///
-/// ```
-/// # use std::io::fs::PathExtensions;
-/// # fn main() {}
-/// # fn foo() {
 /// let info = match Path::new("foo.txt").stat() {
 ///     Ok(stat) => stat,
 ///     Err(e) => panic!("couldn't read foo.txt: {}", e),
 /// };
 ///
 /// println!("byte size: {}", info.size);
-/// # }
 /// ```
 #[derive(Copy, Hash)]
 pub struct FileStat {
diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs
index d09afea94dc..adc122ff447 100644
--- a/src/libstd/io/net/ip.rs
+++ b/src/libstd/io/net/ip.rs
@@ -313,7 +313,7 @@ impl<'a> Parser<'a> {
 
         let mut tail = [0u16; 8];
         let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
-        Some(ipv6_addr_from_head_tail(&head[0..head_size], &tail[0..tail_size]))
+        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
     }
 
     fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs
index 42d9fff6d15..61d164d21e3 100644
--- a/src/libstd/io/net/pipe.rs
+++ b/src/libstd/io/net/pipe.rs
@@ -168,9 +168,7 @@ impl UnixListener {
     /// # Example
     ///
     /// ```
-    /// # fn main() {}
     /// # fn foo() {
-    /// # #![allow(unused_must_use)]
     /// use std::io::net::pipe::UnixListener;
     /// use std::io::{Listener, Acceptor};
     ///
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
index 6a3f5fcb2c6..4978085fa4f 100644
--- a/src/libstd/io/net/tcp.rs
+++ b/src/libstd/io/net/tcp.rs
@@ -272,12 +272,10 @@ impl sys_common::AsInner<TcpStreamImp> for TcpStream {
 /// A structure representing a socket server. This listener is used to create a
 /// `TcpAcceptor` which can be used to accept sockets on a local port.
 ///
-/// # Example
+/// # Examples
 ///
-/// ```rust
-/// # fn main() { }
+/// ```
 /// # fn foo() {
-/// # #![allow(dead_code)]
 /// use std::io::{TcpListener, TcpStream};
 /// use std::io::{Acceptor, Listener};
 /// use std::thread::Thread;
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
index a093e748d57..43ca7b13145 100644
--- a/src/libstd/io/process.rs
+++ b/src/libstd/io/process.rs
@@ -21,6 +21,8 @@ use prelude::v1::*;
 use collections::HashMap;
 use ffi::CString;
 use fmt;
+// NOTE(stage0) remove import after a snapshot
+#[cfg(stage0)]
 use hash::Hash;
 use io::pipe::{PipeStream, PipePair};
 use io::{IoResult, IoError};
diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs
index 67c14dc2dc1..6de466eb20b 100644
--- a/src/libstd/io/test.rs
+++ b/src/libstd/io/test.rs
@@ -15,18 +15,18 @@ use prelude::v1::*;
 use libc;
 use os;
 use std::io::net::ip::*;
-use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
 /// Get a port number, starting at 9600, for use in tests
 pub fn next_test_port() -> u16 {
-    static NEXT_OFFSET: AtomicUint = ATOMIC_UINT_INIT;
+    static NEXT_OFFSET: AtomicUsize = ATOMIC_USIZE_INIT;
     base_port() + NEXT_OFFSET.fetch_add(1, Ordering::Relaxed) as u16
 }
 
 // iOS has a pretty long tmpdir path which causes pipe creation
 // to like: invalid argument: path must be smaller than SUN_LEN
 fn next_test_unix_socket() -> String {
-    static COUNT: AtomicUint = ATOMIC_UINT_INIT;
+    static COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
     // base port and pid are an attempt to be unique between multiple
     // test-runners of different configurations running on one
     // buildbot, the count is to be unique within this executable.
diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs
index 8a0445be471..844a97dea2d 100644
--- a/src/libstd/io/timer.rs
+++ b/src/libstd/io/timer.rs
@@ -27,10 +27,9 @@ use sys::timer::Timer as TimerImp;
 /// period of time. Handles to this timer can also be created in the form of
 /// receivers which will receive notifications over time.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
-/// # fn main() {}
 /// # fn foo() {
 /// use std::io::Timer;
 /// use std::time::Duration;
@@ -54,7 +53,6 @@ use sys::timer::Timer as TimerImp;
 /// the `io::timer` module.
 ///
 /// ```
-/// # fn main() {}
 /// # fn foo() {
 /// use std::io::timer;
 /// use std::time::Duration;
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index 5a7219495f5..adfd88644cc 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -16,6 +16,7 @@ use io;
 use slice::bytes::MutableByteVector;
 
 /// Wraps a `Reader`, limiting the number of bytes that can be read from it.
+#[derive(Show)]
 pub struct LimitReader<R> {
     limit: uint,
     inner: R
@@ -59,7 +60,7 @@ impl<R: Reader> Reader for LimitReader<R> {
 impl<R: Buffer> Buffer for LimitReader<R> {
     fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
         let amt = try!(self.inner.fill_buf());
-        let buf = &amt[0..cmp::min(amt.len(), self.limit)];
+        let buf = &amt[..cmp::min(amt.len(), self.limit)];
         if buf.len() == 0 {
             Err(io::standard_error(io::EndOfFile))
         } else {
@@ -77,7 +78,7 @@ impl<R: Buffer> Buffer for LimitReader<R> {
 }
 
 /// A `Writer` which ignores bytes written to it, like /dev/null.
-#[derive(Copy)]
+#[derive(Copy, Show)]
 pub struct NullWriter;
 
 impl Writer for NullWriter {
@@ -86,7 +87,7 @@ impl Writer for NullWriter {
 }
 
 /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
-#[derive(Copy)]
+#[derive(Copy, Show)]
 pub struct ZeroReader;
 
 impl Reader for ZeroReader {
@@ -107,7 +108,7 @@ impl Buffer for ZeroReader {
 }
 
 /// A `Reader` which is always at EOF, like /dev/null.
-#[derive(Copy)]
+#[derive(Copy, Show)]
 pub struct NullReader;
 
 impl Reader for NullReader {
@@ -128,18 +129,19 @@ impl Buffer for NullReader {
 ///
 /// The `Writer`s are delegated to in order. If any `Writer` returns an error,
 /// that error is returned immediately and remaining `Writer`s are not called.
-pub struct MultiWriter {
-    writers: Vec<Box<Writer+'static>>
+#[derive(Show)]
+pub struct MultiWriter<W> {
+    writers: Vec<W>
 }
 
-impl MultiWriter {
+impl<W> MultiWriter<W> where W: Writer {
     /// Creates a new `MultiWriter`
-    pub fn new(writers: Vec<Box<Writer+'static>>) -> MultiWriter {
+    pub fn new(writers: Vec<W>) -> MultiWriter<W> {
         MultiWriter { writers: writers }
     }
 }
 
-impl Writer for MultiWriter {
+impl<W> Writer for MultiWriter<W> where W: Writer {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
         for writer in self.writers.iter_mut() {
@@ -159,7 +161,7 @@ impl Writer for MultiWriter {
 
 /// A `Reader` which chains input from multiple `Reader`s, reading each to
 /// completion before moving onto the next.
-#[derive(Clone)]
+#[derive(Clone, Show)]
 pub struct ChainedReader<I, R> {
     readers: I,
     cur_reader: Option<R>,
@@ -198,6 +200,7 @@ impl<R: Reader, I: Iterator<Item=R>> Reader for ChainedReader<I, R> {
 
 /// A `Reader` which forwards input from another `Reader`, passing it along to
 /// a `Writer` as well. Similar to the `tee(1)` command.
+#[derive(Show)]
 pub struct TeeReader<R, W> {
     reader: R,
     writer: W,
@@ -220,7 +223,7 @@ impl<R: Reader, W: Writer> TeeReader<R, W> {
 impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
     fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
         self.reader.read(buf).and_then(|len| {
-            self.writer.write(&mut buf[0..len]).map(|()| len)
+            self.writer.write(&mut buf[..len]).map(|()| len)
         })
     }
 }
@@ -234,12 +237,12 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
             Err(ref e) if e.kind == io::EndOfFile => return Ok(()),
             Err(e) => return Err(e),
         };
-        try!(w.write(&buf[0..len]));
+        try!(w.write(&buf[..len]));
     }
 }
 
 /// An adaptor converting an `Iterator<u8>` to a `Reader`.
-#[derive(Clone)]
+#[derive(Clone, Show)]
 pub struct IterReader<T> {
     iter: T,
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index e15e611adc0..ddb8129630f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -73,7 +73,7 @@
 //!
 //! ## Concurrency, I/O, and the runtime
 //!
-//! The [`task`](task/index.html) module contains Rust's threading abstractions,
+//! The [`thread`](thread/index.html) module contains Rust's threading abstractions,
 //! while [`comm`](comm/index.html) contains the channel types for message
 //! passing. [`sync`](sync/index.html) contains further, primitive, shared
 //! memory types, including [`atomic`](sync/atomic/index.html).
@@ -110,7 +110,10 @@
 #![feature(slicing_syntax, unboxed_closures)]
 #![feature(box_syntax)]
 #![feature(old_impl_check)]
-#![allow(unknown_features)] #![feature(int_uint)]
+#![feature(optin_builtin_traits)]
+#![feature(int_uint)]
+#![feature(int_uint)]
+#![allow(unstable)]
 
 // Don't link to std. We are std.
 #![no_std]
@@ -135,6 +138,8 @@ extern crate alloc;
 extern crate unicode;
 extern crate libc;
 
+#[macro_use] #[no_link] extern crate rustc_bitflags;
+
 // Make std testable by not duplicating lang items. See #2912
 #[cfg(test)] extern crate "std" as realstd;
 #[cfg(test)] pub use realstd::marker;
@@ -180,9 +185,6 @@ pub use unicode::char;
 #[macro_use]
 mod macros;
 
-#[macro_use]
-pub mod bitflags;
-
 mod rtdeps;
 
 /* The Prelude. */
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index a420c841d25..8a8d14c4f3a 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -122,16 +122,18 @@ macro_rules! try {
 /// receivers. It places no restrictions on the types of receivers given to
 /// this macro, this can be viewed as a heterogeneous select.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::thread::Thread;
-/// use std::sync::mpsc::channel;
+/// use std::sync::mpsc;
+///
+/// // two placeholder functions for now
+/// fn long_running_task() {}
+/// fn calculate_the_answer() -> u32 { 42 }
 ///
-/// let (tx1, rx1) = channel();
-/// let (tx2, rx2) = channel();
-/// # fn long_running_task() {}
-/// # fn calculate_the_answer() -> int { 42i }
+/// let (tx1, rx1) = mpsc::channel();
+/// let (tx2, rx2) = mpsc::channel();
 ///
 /// Thread::spawn(move|| { long_running_task(); tx1.send(()).unwrap(); });
 /// Thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
@@ -251,13 +253,13 @@ pub mod builtin {
     /// statement or expression position, meaning this macro may be difficult to
     /// use in some situations.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// #![feature(concat_idents)]
     ///
     /// # fn main() {
-    /// fn foobar() -> int { 23 }
+    /// fn foobar() -> u32 { 23 }
     ///
     /// let f = concat_idents!(foo, bar);
     /// println!("{}", f());
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index e804408b4d0..3432767d6cd 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -424,14 +424,12 @@ mod tests {
         assert_eq!(int::MIN.to_u32(),  None);
         assert_eq!(int::MIN.to_u64(),  None);
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
             assert_eq!(int::MIN.to_i32(), Some(int::MIN as i32));
         }
 
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
             assert_eq!(int::MIN.to_i32(), None);
         }
@@ -494,14 +492,12 @@ mod tests {
         assert_eq!(i64::MIN.to_u32(),  None);
         assert_eq!(i64::MIN.to_u64(),  None);
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
             assert_eq!(i64::MIN.to_int(), None);
         }
 
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
             assert_eq!(i64::MIN.to_int(), Some(i64::MIN as int));
         }
@@ -521,15 +517,13 @@ mod tests {
         // int::MAX.to_u32() is word-size specific
         assert_eq!(int::MAX.to_u64(),  Some(int::MAX as u64));
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
             assert_eq!(int::MAX.to_i32(), Some(int::MAX as i32));
             assert_eq!(int::MAX.to_u32(), Some(int::MAX as u32));
         }
 
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
             assert_eq!(int::MAX.to_i32(), None);
             assert_eq!(int::MAX.to_u32(), None);
@@ -593,15 +587,13 @@ mod tests {
         assert_eq!(i64::MAX.to_u32(),  None);
         assert_eq!(i64::MAX.to_u64(),  Some(i64::MAX as u64));
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
             assert_eq!(i64::MAX.to_int(),  None);
             assert_eq!(i64::MAX.to_uint(), None);
         }
 
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
             assert_eq!(i64::MAX.to_int(),  Some(i64::MAX as int));
             assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as uint));
@@ -692,15 +684,13 @@ mod tests {
         // uint::MAX.to_u32() is word-size specific
         assert_eq!(uint::MAX.to_u64(),  Some(uint::MAX as u64));
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
             assert_eq!(uint::MAX.to_u32(), Some(uint::MAX as u32));
             assert_eq!(uint::MAX.to_i64(), Some(uint::MAX as i64));
         }
 
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
             assert_eq!(uint::MAX.to_u32(), None);
             assert_eq!(uint::MAX.to_i64(), None);
@@ -750,14 +740,12 @@ mod tests {
         assert_eq!(u32::MAX.to_u32(),  Some(u32::MAX as u32));
         assert_eq!(u32::MAX.to_u64(),  Some(u32::MAX as u64));
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
             assert_eq!(u32::MAX.to_int(),  None);
         }
 
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
             assert_eq!(u32::MAX.to_int(),  Some(u32::MAX as int));
         }
@@ -778,14 +766,12 @@ mod tests {
         assert_eq!(u64::MAX.to_u32(),  None);
         assert_eq!(u64::MAX.to_u64(),  Some(u64::MAX as u64));
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
             assert_eq!(u64::MAX.to_uint(), None);
         }
 
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
             assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as uint));
         }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 6e3949b9e22..fc0c838a3f1 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -54,7 +54,7 @@ use result::Result::{Err, Ok};
 use slice::{AsSlice, SliceExt};
 use str::{Str, StrExt};
 use string::{String, ToString};
-use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, Ordering};
+use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
 use vec::Vec;
 
 #[cfg(unix)] use ffi::{self, CString};
@@ -590,7 +590,7 @@ pub fn last_os_error() -> String {
     error_string(errno() as uint)
 }
 
-static EXIT_STATUS: AtomicInt = ATOMIC_INT_INIT;
+static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
 
 /// Sets the process exit code
 ///
@@ -1422,6 +1422,11 @@ mod arch_consts {
     pub const ARCH: &'static str = "mipsel";
 }
 
+#[cfg(target_arch = "powerpc")]
+mod arch_consts {
+    pub const ARCH: &'static str = "powerpc";
+}
+
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
index 1ec7b6b3edc..541f1e77140 100644
--- a/src/libstd/path/mod.rs
+++ b/src/libstd/path/mod.rs
@@ -352,7 +352,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
                 match name.rposition_elem(&dot) {
                     None | Some(0) => name,
                     Some(1) if name == b".." => name,
-                    Some(pos) => &name[0..pos]
+                    Some(pos) => &name[..pos]
                 }
             })
         }
@@ -475,7 +475,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
             let extlen = extension.container_as_bytes().len();
             match (name.rposition_elem(&dot), extlen) {
                 (None, 0) | (Some(0), 0) => None,
-                (Some(idx), 0) => Some(name[0..idx].to_vec()),
+                (Some(idx), 0) => Some(name[..idx].to_vec()),
                 (idx, extlen) => {
                     let idx = match idx {
                         None | Some(0) => name.len(),
@@ -484,7 +484,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
 
                     let mut v;
                     v = Vec::with_capacity(idx + extlen + 1);
-                    v.push_all(&name[0..idx]);
+                    v.push_all(&name[..idx]);
                     v.push(dot);
                     v.push_all(extension.container_as_bytes());
                     Some(v)
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 293696d5cca..aab64639ab5 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -136,7 +136,7 @@ impl GenericPathUnsafe for Path {
             }
             Some(idx) => {
                 let mut v = Vec::with_capacity(idx + 1 + filename.len());
-                v.push_all(&self.repr[0..(idx+1)]);
+                v.push_all(&self.repr[..(idx+1)]);
                 v.push_all(filename);
                 // FIXME: this is slow
                 self.repr = Path::normalize(v.as_slice());
@@ -177,9 +177,9 @@ impl GenericPath for Path {
         match self.sepidx {
             None if b".." == self.repr => self.repr.as_slice(),
             None => dot_static,
-            Some(0) => &self.repr[0..1],
+            Some(0) => &self.repr[..1],
             Some(idx) if &self.repr[(idx+1)..] == b".." => self.repr.as_slice(),
-            Some(idx) => &self.repr[0..idx]
+            Some(idx) => &self.repr[..idx]
         }
     }
 
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 2a1f1794e49..3cff1c67be3 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -180,20 +180,20 @@ impl GenericPathUnsafe for Path {
             }
             Some((_,idxa,end)) if &self.repr[idxa..end] == ".." => {
                 let mut s = String::with_capacity(end + 1 + filename.len());
-                s.push_str(&self.repr[0..end]);
+                s.push_str(&self.repr[..end]);
                 s.push(SEP);
                 s.push_str(filename);
                 self.update_normalized(&s[]);
             }
             Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => {
                 let mut s = String::with_capacity(idxb + filename.len());
-                s.push_str(&self.repr[0..idxb]);
+                s.push_str(&self.repr[..idxb]);
                 s.push_str(filename);
                 self.update_normalized(&s[]);
             }
             Some((idxb,_,_)) => {
                 let mut s = String::with_capacity(idxb + 1 + filename.len());
-                s.push_str(&self.repr[0..idxb]);
+                s.push_str(&self.repr[..idxb]);
                 s.push(SEP);
                 s.push_str(filename);
                 self.update_normalized(&s[]);
@@ -350,13 +350,13 @@ impl GenericPath for Path {
             Some((idxb,_,end)) if &self.repr[idxb..end] == "\\" => {
                 &self.repr[]
             }
-            Some((0,idxa,_)) => &self.repr[0..idxa],
+            Some((0,idxa,_)) => &self.repr[..idxa],
             Some((idxb,idxa,_)) => {
                 match self.prefix {
                     Some(DiskPrefix) | Some(VerbatimDiskPrefix) if idxb == self.prefix_len() => {
-                        &self.repr[0..idxa]
+                        &self.repr[..idxa]
                     }
-                    _ => &self.repr[0..idxb]
+                    _ => &self.repr[..idxb]
                 }
             }
         })
@@ -428,15 +428,15 @@ impl GenericPath for Path {
         if self.prefix.is_some() {
             Some(Path::new(match self.prefix {
                 Some(DiskPrefix) if self.is_absolute() => {
-                    &self.repr[0..(self.prefix_len()+1)]
+                    &self.repr[..(self.prefix_len()+1)]
                 }
                 Some(VerbatimDiskPrefix) => {
-                    &self.repr[0..(self.prefix_len()+1)]
+                    &self.repr[..(self.prefix_len()+1)]
                 }
-                _ => &self.repr[0..self.prefix_len()]
+                _ => &self.repr[..self.prefix_len()]
             }))
         } else if is_vol_relative(self) {
-            Some(Path::new(&self.repr[0..1]))
+            Some(Path::new(&self.repr[..1]))
         } else {
             None
         }
@@ -683,7 +683,7 @@ impl Path {
             }
             (None, None) => true,
             (a, b) if a == b => {
-                &s_repr[0..self.prefix_len()] == &o_repr[0..other.prefix_len()]
+                &s_repr[..self.prefix_len()] == &o_repr[..other.prefix_len()]
             }
             _ => false
         }
@@ -737,7 +737,7 @@ impl Path {
                         match prefix.unwrap() {
                             DiskPrefix => {
                                 let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(&s[0..len]);
+                                let mut s = String::from_str(&s[..len]);
                                 unsafe {
                                     let v = s.as_mut_vec();
                                     v[0] = (*v)[0].to_ascii_uppercase();
@@ -752,7 +752,7 @@ impl Path {
                             }
                             VerbatimDiskPrefix => {
                                 let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(&s[0..len]);
+                                let mut s = String::from_str(&s[..len]);
                                 unsafe {
                                     let v = s.as_mut_vec();
                                     v[4] = (*v)[4].to_ascii_uppercase();
@@ -762,14 +762,14 @@ impl Path {
                             _ => {
                                 let plen = prefix_len(prefix);
                                 if s.len() > plen {
-                                    Some(String::from_str(&s[0..plen]))
+                                    Some(String::from_str(&s[..plen]))
                                 } else { None }
                             }
                         }
                     } else if is_abs && comps.is_empty() {
                         Some(repeat(SEP).take(1).collect())
                     } else {
-                        let prefix_ = &s[0..prefix_len(prefix)];
+                        let prefix_ = &s[..prefix_len(prefix)];
                         let n = prefix_.len() +
                                 if is_abs { comps.len() } else { comps.len() - 1} +
                                 comps.iter().map(|v| v.len()).sum();
@@ -780,7 +780,7 @@ impl Path {
                                 s.push(':');
                             }
                             Some(VerbatimDiskPrefix) => {
-                                s.push_str(&prefix_[0..4]);
+                                s.push_str(&prefix_[..4]);
                                 s.push(prefix_.as_bytes()[4].to_ascii_uppercase() as char);
                                 s.push_str(&prefix_[5..]);
                             }
@@ -813,7 +813,7 @@ impl Path {
 
     fn update_sepidx(&mut self) {
         let s = if self.has_nonsemantic_trailing_slash() {
-                    &self.repr[0..(self.repr.len()-1)]
+                    &self.repr[..(self.repr.len()-1)]
                 } else { &self.repr[] };
         let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) {
             is_sep
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 60d490982db..23387d29553 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -230,9 +230,9 @@ use rc::Rc;
 use result::Result::{Ok, Err};
 use vec::Vec;
 
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 use core_rand::IsaacRng as IsaacWordRng;
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 use core_rand::Isaac64Rng as IsaacWordRng;
 
 pub use core_rand::{Rand, Rng, SeedableRng, Open01, Closed01};
@@ -374,9 +374,13 @@ impl Rng for ThreadRng {
 /// `random()` can generate various types of random things, and so may require
 /// type hinting to generate the specific type you want.
 ///
+/// This function uses the thread local random number generator. This means
+/// that if you're calling `random()` in a loop, caching the generator can
+/// increase performance. An example is shown below.
+///
 /// # Examples
 ///
-/// ```rust
+/// ```
 /// use std::rand;
 ///
 /// let x = rand::random();
@@ -389,6 +393,27 @@ impl Rng for ThreadRng {
 ///     println!("Better lucky than good!");
 /// }
 /// ```
+///
+/// Caching the thread local random number generator:
+///
+/// ```
+/// use std::rand;
+/// use std::rand::Rng;
+///
+/// let mut v = vec![1, 2, 3];
+///
+/// for x in v.iter_mut() {
+///     *x = rand::random()
+/// }
+///
+/// // would be faster as
+///
+/// let mut rng = rand::thread_rng();
+///
+/// for x in v.iter_mut() {
+///     *x = rng.gen();
+/// }
+/// ```
 #[inline]
 pub fn random<T: Rand>() -> T {
     thread_rng().gen()
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 18d40ecd3eb..68ba7e1dd29 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -32,7 +32,8 @@ mod imp {
               any(target_arch = "x86_64",
                   target_arch = "x86",
                   target_arch = "arm",
-                  target_arch = "aarch64")))]
+                  target_arch = "aarch64",
+                  target_arch = "powerpc")))]
     fn getrandom(buf: &mut [u8]) -> libc::c_long {
         extern "C" {
             fn syscall(number: libc::c_long, ...) -> libc::c_long;
@@ -44,6 +45,8 @@ mod imp {
         const NR_GETRANDOM: libc::c_long = 355;
         #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
         const NR_GETRANDOM: libc::c_long = 384;
+        #[cfg(target_arch = "powerpc")]
+        const NR_GETRANDOM: libc::c_long = 384;
 
         unsafe {
             syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
@@ -54,7 +57,8 @@ mod imp {
                   any(target_arch = "x86_64",
                       target_arch = "x86",
                       target_arch = "arm",
-                      target_arch = "aarch64"))))]
+                      target_arch = "aarch64",
+                      target_arch = "powerpc"))))]
     fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
 
     fn getrandom_fill_bytes(v: &mut [u8]) {
@@ -91,7 +95,8 @@ mod imp {
               any(target_arch = "x86_64",
                   target_arch = "x86",
                   target_arch = "arm",
-                  target_arch = "aarch64")))]
+                  target_arch = "aarch64",
+                  target_arch = "powerpc")))]
     fn is_getrandom_available() -> bool {
         use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
 
@@ -119,7 +124,8 @@ mod imp {
                   any(target_arch = "x86_64",
                       target_arch = "x86",
                       target_arch = "arm",
-                      target_arch = "aarch64"))))]
+                      target_arch = "aarch64",
+                      target_arch = "powerpc"))))]
     fn is_getrandom_available() -> bool { false }
 
     /// A random number generator that retrieves randomness straight from
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index bb0b6fe804b..f2d66e1a4d7 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -22,7 +22,7 @@ pub use sys::backtrace::write;
 // For now logging is turned off by default, and this function checks to see
 // whether the magical environment variable is present to see if it's turned on.
 pub fn log_enabled() -> bool {
-    static ENABLED: atomic::AtomicInt = atomic::ATOMIC_INT_INIT;
+    static ENABLED: atomic::AtomicIsize = atomic::ATOMIC_ISIZE_INIT;
     match ENABLED.load(Ordering::SeqCst) {
         1 => return false,
         2 => return true,
diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs
index 7cc39d7d972..dd9923307d6 100644
--- a/src/libstd/rt/libunwind.rs
+++ b/src/libstd/rt/libunwind.rs
@@ -81,6 +81,9 @@ pub const unwinder_private_data_size: uint = 2;
 #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
 pub const unwinder_private_data_size: uint = 2;
 
+#[cfg(target_arch = "powerpc")]
+pub const unwinder_private_data_size: uint = 2;
+
 #[repr(C)]
 pub struct _Unwind_Exception {
     pub exception_class: _Unwind_Exception_Class,
diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs
index 4cd0b29688a..73b8f104c23 100644
--- a/src/libstd/rt/unwind.rs
+++ b/src/libstd/rt/unwind.rs
@@ -83,16 +83,16 @@ pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
 //
 // For more information, see below.
 const MAX_CALLBACKS: uint = 16;
-static CALLBACKS: [atomic::AtomicUint; MAX_CALLBACKS] =
-        [atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT];
-static CALLBACK_CNT: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+static CALLBACKS: [atomic::AtomicUsize; MAX_CALLBACKS] =
+        [atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT];
+static CALLBACK_CNT: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
 
 thread_local! { static PANICKING: Cell<bool> = Cell::new(false) }
 
@@ -544,7 +544,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
     // MAX_CALLBACKS, so we're sure to clamp it as necessary.
     let callbacks = {
         let amt = CALLBACK_CNT.load(Ordering::SeqCst);
-        &CALLBACKS[0..cmp::min(amt, MAX_CALLBACKS)]
+        &CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)]
     };
     for cb in callbacks.iter() {
         match cb.load(Ordering::SeqCst) {
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index c076f0a7c6c..235cedcda52 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -46,7 +46,7 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
 }
 
 pub fn min_stack() -> uint {
-    static MIN: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+    static MIN: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
     match MIN.load(Ordering::SeqCst) {
         0 => {}
         n => return n - 1,
@@ -131,7 +131,7 @@ pub fn abort(args: fmt::Arguments) -> ! {
     impl<'a> fmt::Writer for BufWriter<'a> {
         fn write_str(&mut self, bytes: &str) -> fmt::Result {
             let left = self.buf.slice_from_mut(self.pos);
-            let to_write = &bytes.as_bytes()[0..cmp::min(bytes.len(), left.len())];
+            let to_write = &bytes.as_bytes()[..cmp::min(bytes.len(), left.len())];
             slice::bytes::copy_memory(left, to_write);
             self.pos += to_write.len();
             Ok(())
@@ -142,58 +142,8 @@ pub fn abort(args: fmt::Arguments) -> ! {
     let mut msg = [0u8; 512];
     let mut w = BufWriter { buf: &mut msg, pos: 0 };
     let _ = write!(&mut w, "{}", args);
-    let msg = str::from_utf8(&w.buf[0..w.pos]).unwrap_or("aborted");
+    let msg = str::from_utf8(&w.buf[..w.pos]).unwrap_or("aborted");
     let msg = if msg.is_empty() {"aborted"} else {msg};
-
-    // Give some context to the message
-    let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) );
-    let quote = match hash % 10 {
-        0 => "
-It was from the artists and poets that the pertinent answers came, and I
-know that panic would have broken loose had they been able to compare notes.
-As it was, lacking their original letters, I half suspected the compiler of
-having asked leading questions, or of having edited the correspondence in
-corroboration of what he had latently resolved to see.",
-        1 => "
-There are not many persons who know what wonders are opened to them in the
-stories and visions of their youth; for when as children we listen and dream,
-we think but half-formed thoughts, and when as men we try to remember, we are
-dulled and prosaic with the poison of life. But some of us awake in the night
-with strange phantasms of enchanted hills and gardens, of fountains that sing
-in the sun, of golden cliffs overhanging murmuring seas, of plains that stretch
-down to sleeping cities of bronze and stone, and of shadowy companies of heroes
-that ride caparisoned white horses along the edges of thick forests; and then
-we know that we have looked back through the ivory gates into that world of
-wonder which was ours before we were wise and unhappy.",
-        2 => "
-Instead of the poems I had hoped for, there came only a shuddering blackness
-and ineffable loneliness; and I saw at last a fearful truth which no one had
-ever dared to breathe before — the unwhisperable secret of secrets — The fact
-that this city of stone and stridor is not a sentient perpetuation of Old New
-York as London is of Old London and Paris of Old Paris, but that it is in fact
-quite dead, its sprawling body imperfectly embalmed and infested with queer
-animate things which have nothing to do with it as it was in life.",
-        3 => "
-The ocean ate the last of the land and poured into the smoking gulf, thereby
-giving up all it had ever conquered. From the new-flooded lands it flowed
-again, uncovering death and decay; and from its ancient and immemorial bed it
-trickled loathsomely, uncovering nighted secrets of the years when Time was
-young and the gods unborn. Above the waves rose weedy remembered spires. The
-moon laid pale lilies of light on dead London, and Paris stood up from its damp
-grave to be sanctified with star-dust. Then rose spires and monoliths that were
-weedy but not remembered; terrible spires and monoliths of lands that men never
-knew were lands...",
-        4 => "
-There was a night when winds from unknown spaces whirled us irresistibly into
-limitless vacuum beyond all thought and entity. Perceptions of the most
-maddeningly untransmissible sort thronged upon us; perceptions of infinity
-which at the time convulsed us with joy, yet which are now partly lost to my
-memory and partly incapable of presentation to others.",
-        _ => "You've met with a terrible fate, haven't you?"
-    };
-    rterrln!("{}", "");
-    rterrln!("{}", quote);
-    rterrln!("{}", "");
     rterrln!("fatal runtime error: {}", msg);
     unsafe { intrinsics::abort(); }
 }
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 3c0ae71255d..a81a4504323 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -10,8 +10,9 @@
 
 use prelude::v1::*;
 
-use sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
+use sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 use sync::poison::{self, LockResult};
+use sys::time::SteadyTime;
 use sys_common::condvar as sys;
 use sys_common::mutex as sys_mutex;
 use time::Duration;
@@ -78,7 +79,7 @@ unsafe impl Sync for Condvar {}
 #[unstable = "may be merged with Condvar in the future"]
 pub struct StaticCondvar {
     inner: sys::Condvar,
-    mutex: AtomicUint,
+    mutex: AtomicUsize,
 }
 
 unsafe impl Send for StaticCondvar {}
@@ -88,7 +89,7 @@ unsafe impl Sync for StaticCondvar {}
 #[unstable = "may be merged with Condvar in the future"]
 pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
     inner: sys::CONDVAR_INIT,
-    mutex: ATOMIC_UINT_INIT,
+    mutex: ATOMIC_USIZE_INIT,
 };
 
 impl Condvar {
@@ -99,7 +100,7 @@ impl Condvar {
         Condvar {
             inner: box StaticCondvar {
                 inner: unsafe { sys::Condvar::new() },
-                mutex: AtomicUint::new(0),
+                mutex: AtomicUsize::new(0),
             }
         }
     }
@@ -153,13 +154,8 @@ impl Condvar {
     ///
     /// Like `wait`, the lock specified will be re-acquired when this function
     /// returns, regardless of whether the timeout elapsed or not.
-    // Note that this method is *not* public, and this is quite intentional
-    // because we're not quite sure about the semantics of relative vs absolute
-    // durations or how the timing guarantees play into what the system APIs
-    // provide. There are also additional concerns about the unix-specific
-    // implementation which may need to be addressed.
-    #[allow(dead_code)]
-    fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
+    #[unstable]
+    pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
                            -> LockResult<(MutexGuard<'a, T>, bool)> {
         unsafe {
             let me: &'static Condvar = &*(self as *const _);
@@ -167,13 +163,32 @@ impl Condvar {
         }
     }
 
+    /// Wait on this condition variable for a notification, timing out after a
+    /// specified duration.
+    ///
+    /// The semantics of this function are equivalent to `wait_timeout` except
+    /// that the implementation will repeatedly wait while the duration has not
+    /// passed and the provided function returns `false`.
+    #[unstable]
+    pub fn wait_timeout_with<'a, T, F>(&self,
+                                       guard: MutexGuard<'a, T>,
+                                       dur: Duration,
+                                       f: F)
+                                       -> LockResult<(MutexGuard<'a, T>, bool)>
+            where F: FnMut(LockResult<&mut T>) -> bool {
+        unsafe {
+            let me: &'static Condvar = &*(self as *const _);
+            me.inner.wait_timeout_with(guard, dur, f)
+        }
+    }
+
     /// Wake up one blocked thread on this condvar.
     ///
     /// If there is a blocked thread on this condition variable, then it will
     /// be woken up from its call to `wait` or `wait_timeout`. Calls to
     /// `notify_one` are not buffered in any way.
     ///
-    /// To wake up all threads, see `notify_one()`.
+    /// To wake up all threads, see `notify_all()`.
     #[stable]
     pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } }
 
@@ -220,9 +235,9 @@ impl StaticCondvar {
     /// specified duration.
     ///
     /// See `Condvar::wait_timeout`.
-    #[allow(dead_code)] // may want to stabilize this later, see wait_timeout above
-    fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration)
-                           -> LockResult<(MutexGuard<'a, T>, bool)> {
+    #[unstable = "may be merged with Condvar in the future"]
+    pub fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration)
+                               -> LockResult<(MutexGuard<'a, T>, bool)> {
         let (poisoned, success) = unsafe {
             let lock = mutex::guard_lock(&guard);
             self.verify(lock);
@@ -236,6 +251,50 @@ impl StaticCondvar {
         }
     }
 
+    /// Wait on this condition variable for a notification, timing out after a
+    /// specified duration.
+    ///
+    /// The implementation will repeatedly wait while the duration has not
+    /// passed and the function returns `false`.
+    ///
+    /// See `Condvar::wait_timeout_with`.
+    #[unstable = "may be merged with Condvar in the future"]
+    pub fn wait_timeout_with<'a, T, F>(&'static self,
+                                       guard: MutexGuard<'a, T>,
+                                       dur: Duration,
+                                       mut f: F)
+                                       -> LockResult<(MutexGuard<'a, T>, bool)>
+            where F: FnMut(LockResult<&mut T>) -> bool {
+        // This could be made more efficient by pushing the implementation into sys::condvar
+        let start = SteadyTime::now();
+        let mut guard_result: LockResult<MutexGuard<'a, T>> = Ok(guard);
+        while !f(guard_result
+                    .as_mut()
+                    .map(|g| &mut **g)
+                    .map_err(|e| poison::new_poison_error(&mut **e.get_mut()))) {
+            let now = SteadyTime::now();
+            let consumed = &now - &start;
+            let guard = guard_result.unwrap_or_else(|e| e.into_inner());
+            let (new_guard_result, no_timeout) = match self.wait_timeout(guard, dur - consumed) {
+                Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout),
+                Err(err) => {
+                    let (new_guard, no_timeout) = err.into_inner();
+                    (Err(poison::new_poison_error(new_guard)), no_timeout)
+                }
+            };
+            guard_result = new_guard_result;
+            if !no_timeout {
+                let result = f(guard_result
+                                    .as_mut()
+                                    .map(|g| &mut **g)
+                                    .map_err(|e| poison::new_poison_error(&mut **e.get_mut())));
+                return poison::map_result(guard_result, |g| (g, result));
+            }
+        }
+
+        poison::map_result(guard_result, |g| (g, true))
+    }
+
     /// Wake up one blocked thread on this condvar.
     ///
     /// See `Condvar::notify_one`.
@@ -285,6 +344,7 @@ mod tests {
     use super::{StaticCondvar, CONDVAR_INIT};
     use sync::mpsc::channel;
     use sync::{StaticMutex, MUTEX_INIT, Condvar, Mutex, Arc};
+    use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
     use thread::Thread;
     use time::Duration;
 
@@ -373,6 +433,49 @@ mod tests {
     }
 
     #[test]
+    fn wait_timeout_with() {
+        static C: StaticCondvar = CONDVAR_INIT;
+        static M: StaticMutex = MUTEX_INIT;
+        static S: AtomicUsize = ATOMIC_USIZE_INIT;
+
+        let g = M.lock().unwrap();
+        let (g, success) = C.wait_timeout_with(g, Duration::nanoseconds(1000), |_| false).unwrap();
+        assert!(!success);
+
+        let (tx, rx) = channel();
+        let _t = Thread::scoped(move || {
+            rx.recv().unwrap();
+            let g = M.lock().unwrap();
+            S.store(1, Ordering::SeqCst);
+            C.notify_one();
+            drop(g);
+
+            rx.recv().unwrap();
+            let g = M.lock().unwrap();
+            S.store(2, Ordering::SeqCst);
+            C.notify_one();
+            drop(g);
+
+            rx.recv().unwrap();
+            let _g = M.lock().unwrap();
+            S.store(3, Ordering::SeqCst);
+            C.notify_one();
+        });
+
+        let mut state = 0;
+        let (_g, success) = C.wait_timeout_with(g, Duration::days(1), |_| {
+            assert_eq!(state, S.load(Ordering::SeqCst));
+            tx.send(()).unwrap();
+            state += 1;
+            match state {
+                1|2 => false,
+                _ => true,
+            }
+        }).unwrap();
+        assert!(success);
+    }
+
+    #[test]
     #[should_fail]
     fn two_mutexes() {
         static M1: StaticMutex = MUTEX_INIT;
diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs
index 568c24446e7..36bbc5ff5b4 100644
--- a/src/libstd/sync/future.rs
+++ b/src/libstd/sync/future.rs
@@ -11,14 +11,18 @@
 //! A type representing values that may be computed concurrently and operations
 //! for working with them.
 //!
-//! # Example
+//! # Examples
 //!
-//! ```rust
+//! ```
 //! use std::sync::Future;
-//! # fn fib(n: uint) -> uint {42};
-//! # fn make_a_sandwich() {};
-//! let mut delayed_fib = Future::spawn(move|| { fib(5000) });
-//! make_a_sandwich();
+//!
+//! // a fake, for now
+//! fn fib(n: u32) -> u32 { 42 };
+//!
+//! let mut delayed_fib = Future::spawn(move || fib(5000));
+//!
+//! // do stuff...
+//!
 //! println!("fib(5000) = {}", delayed_fib.get())
 //! ```
 
diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs
index f174771a3e0..17e690e9540 100644
--- a/src/libstd/sync/mpsc/blocking.rs
+++ b/src/libstd/sync/mpsc/blocking.rs
@@ -14,6 +14,7 @@ use thread::Thread;
 use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
 use sync::Arc;
 use marker::{Sync, Send};
+#[cfg(stage0)] // NOTE remove use after next snapshot
 use marker::{NoSend, NoSync};
 use mem;
 use clone::Clone;
@@ -31,12 +32,25 @@ pub struct SignalToken {
     inner: Arc<Inner>,
 }
 
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct WaitToken {
     inner: Arc<Inner>,
     no_send: NoSend,
     no_sync: NoSync,
 }
 
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct WaitToken {
+    inner: Arc<Inner>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl !Send for WaitToken {}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl !Sync for WaitToken {}
+
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub fn tokens() -> (WaitToken, SignalToken) {
     let inner = Arc::new(Inner {
         thread: Thread::current(),
@@ -53,6 +67,21 @@ pub fn tokens() -> (WaitToken, SignalToken) {
     (wait_token, signal_token)
 }
 
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub fn tokens() -> (WaitToken, SignalToken) {
+    let inner = Arc::new(Inner {
+        thread: Thread::current(),
+        woken: ATOMIC_BOOL_INIT,
+    });
+    let wait_token = WaitToken {
+        inner: inner.clone(),
+    };
+    let signal_token = SignalToken {
+        inner: inner
+    };
+    (wait_token, signal_token)
+}
+
 impl SignalToken {
     pub fn signal(&self) -> bool {
         let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index eca7d3155b1..0ba19b70617 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -370,12 +370,24 @@ unsafe impl<T:Send> Send for Sender<T> { }
 /// The sending-half of Rust's synchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct SyncSender<T> {
     inner: Arc<RacyCell<sync::Packet<T>>>,
     // can't share in an arc
     _marker: marker::NoSync,
 }
 
+/// The sending-half of Rust's synchronous channel type. This half can only be
+/// owned by one task, but it can be cloned to send to other tasks.
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct SyncSender<T> {
+    inner: Arc<RacyCell<sync::Packet<T>>>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<T> !marker::Sync for SyncSender<T> {}
+
 /// An error returned from the `send` function on channels.
 ///
 /// A `send` operation can only fail if the receiving end of a channel is
@@ -677,10 +689,16 @@ impl<T: Send> Drop for Sender<T> {
 ////////////////////////////////////////////////////////////////////////////////
 
 impl<T: Send> SyncSender<T> {
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
         SyncSender { inner: inner, _marker: marker::NoSync }
     }
 
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
+        SyncSender { inner: inner }
+    }
+
     /// Sends a value on this synchronous channel.
     ///
     /// This function will *block* until space in the internal buffer becomes
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index 5c2331d0f2e..ca667e65e30 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -42,7 +42,7 @@ use core::prelude::*;
 use sync::mpsc::Receiver;
 use sync::mpsc::blocking::{self, SignalToken};
 use core::mem;
-use sync::atomic::{AtomicUint, Ordering};
+use sync::atomic::{AtomicUsize, Ordering};
 
 // Various states you can find a port in.
 const EMPTY: uint = 0;          // initial state: no data, no blocked reciever
@@ -56,7 +56,7 @@ const DISCONNECTED: uint = 2;   // channel is disconnected OR upgraded
 
 pub struct Packet<T> {
     // Internal state of the chan/port pair (stores the blocked task as well)
-    state: AtomicUint,
+    state: AtomicUsize,
     // One-shot data slot location
     data: Option<T>,
     // when used for the second time, a oneshot channel must be upgraded, and
@@ -93,7 +93,7 @@ impl<T: Send> Packet<T> {
         Packet {
             data: None,
             upgrade: NothingSent,
-            state: AtomicUint::new(EMPTY),
+            state: AtomicUsize::new(EMPTY),
         }
     }
 
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
index 0da458a51f1..62a7b823ec8 100644
--- a/src/libstd/sync/mpsc/select.rs
+++ b/src/libstd/sync/mpsc/select.rs
@@ -66,6 +66,7 @@ use sync::mpsc::blocking::{self, SignalToken};
 
 /// The "receiver set" of the select interface. This structure is used to manage
 /// a set of receivers which are being selected over.
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct Select {
     head: *mut Handle<'static, ()>,
     tail: *mut Handle<'static, ()>,
@@ -73,6 +74,18 @@ pub struct Select {
     marker1: marker::NoSend,
 }
 
+/// The "receiver set" of the select interface. This structure is used to manage
+/// a set of receivers which are being selected over.
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct Select {
+    head: *mut Handle<'static, ()>,
+    tail: *mut Handle<'static, ()>,
+    next_id: Cell<uint>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl !marker::Send for Select {}
+
 /// A handle to a receiver which is currently a member of a `Select` set of
 /// receivers.  This handle is used to keep the receiver in the set as well as
 /// interact with the underlying receiver.
@@ -113,6 +126,7 @@ impl Select {
     ///
     /// Usage of this struct directly can sometimes be burdensome, and usage is
     /// rather much easier through the `select!` macro.
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     pub fn new() -> Select {
         Select {
             marker1: marker::NoSend,
@@ -122,6 +136,20 @@ impl Select {
         }
     }
 
+    /// Creates a new selection structure. This set is initially empty and
+    /// `wait` will panic!() if called.
+    ///
+    /// Usage of this struct directly can sometimes be burdensome, and usage is
+    /// rather much easier through the `select!` macro.
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    pub fn new() -> Select {
+        Select {
+            head: 0 as *mut Handle<'static, ()>,
+            tail: 0 as *mut Handle<'static, ()>,
+            next_id: Cell::new(1),
+        }
+    }
+
     /// Creates a new handle into this receiver set for a new receiver. Note
     /// that this does *not* add the receiver to the receiver set, for that you
     /// must call the `add` method on the handle itself.
diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs
index 4295d116aed..c97af4c6bca 100644
--- a/src/libstd/sync/mpsc/shared.rs
+++ b/src/libstd/sync/mpsc/shared.rs
@@ -25,7 +25,7 @@ use core::prelude::*;
 use core::cmp;
 use core::int;
 
-use sync::atomic::{AtomicUint, AtomicInt, AtomicBool, Ordering};
+use sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
 use sync::mpsc::blocking::{self, SignalToken};
 use sync::mpsc::mpsc_queue as mpsc;
 use sync::mpsc::select::StartResult::*;
@@ -42,17 +42,17 @@ const MAX_STEALS: int = 1 << 20;
 
 pub struct Packet<T> {
     queue: mpsc::Queue<T>,
-    cnt: AtomicInt, // How many items are on this channel
+    cnt: AtomicIsize, // How many items are on this channel
     steals: int, // How many times has a port received without blocking?
-    to_wake: AtomicUint, // SignalToken for wake up
+    to_wake: AtomicUsize, // SignalToken for wake up
 
     // The number of channels which are currently using this packet.
-    channels: AtomicInt,
+    channels: AtomicIsize,
 
     // See the discussion in Port::drop and the channel send methods for what
     // these are used for
     port_dropped: AtomicBool,
-    sender_drain: AtomicInt,
+    sender_drain: AtomicIsize,
 
     // this lock protects various portions of this implementation during
     // select()
@@ -70,12 +70,12 @@ impl<T: Send> Packet<T> {
     pub fn new() -> Packet<T> {
         let p = Packet {
             queue: mpsc::Queue::new(),
-            cnt: AtomicInt::new(0),
+            cnt: AtomicIsize::new(0),
             steals: 0,
-            to_wake: AtomicUint::new(0),
-            channels: AtomicInt::new(2),
+            to_wake: AtomicUsize::new(0),
+            channels: AtomicIsize::new(2),
             port_dropped: AtomicBool::new(false),
-            sender_drain: AtomicInt::new(0),
+            sender_drain: AtomicIsize::new(0),
             select_lock: Mutex::new(()),
         };
         return p;
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
index 46c69f6f547..34fd6bb70dc 100644
--- a/src/libstd/sync/mpsc/spsc_queue.rs
+++ b/src/libstd/sync/mpsc/spsc_queue.rs
@@ -41,7 +41,7 @@ use alloc::boxed::Box;
 use core::mem;
 use core::cell::UnsafeCell;
 
-use sync::atomic::{AtomicPtr, AtomicUint, Ordering};
+use sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
 
 // Node within the linked list queue of messages to send
 struct Node<T> {
@@ -69,8 +69,8 @@ pub struct Queue<T> {
     // Cache maintenance fields. Additions and subtractions are stored
     // separately in order to allow them to use nonatomic addition/subtraction.
     cache_bound: uint,
-    cache_additions: AtomicUint,
-    cache_subtractions: AtomicUint,
+    cache_additions: AtomicUsize,
+    cache_subtractions: AtomicUsize,
 }
 
 unsafe impl<T: Send> Send for Queue<T> { }
@@ -117,8 +117,8 @@ impl<T: Send> Queue<T> {
             first: UnsafeCell::new(n1),
             tail_copy: UnsafeCell::new(n1),
             cache_bound: bound,
-            cache_additions: AtomicUint::new(0),
-            cache_subtractions: AtomicUint::new(0),
+            cache_additions: AtomicUsize::new(0),
+            cache_subtractions: AtomicUsize::new(0),
         }
     }
 
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index f4b20c7b742..a03add8c532 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -28,7 +28,7 @@ use core::cmp;
 use core::int;
 use thread::Thread;
 
-use sync::atomic::{AtomicInt, AtomicUint, Ordering, AtomicBool};
+use sync::atomic::{AtomicIsize, AtomicUsize, Ordering, AtomicBool};
 use sync::mpsc::Receiver;
 use sync::mpsc::blocking::{self, SignalToken};
 use sync::mpsc::spsc_queue as spsc;
@@ -42,9 +42,9 @@ const MAX_STEALS: int = 1 << 20;
 pub struct Packet<T> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
-    cnt: AtomicInt, // How many items are on this channel
+    cnt: AtomicIsize, // How many items are on this channel
     steals: int, // How many times has a port received without blocking?
-    to_wake: AtomicUint, // SignalToken for the blocked thread to wake up
+    to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up
 
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
 }
@@ -79,9 +79,9 @@ impl<T: Send> Packet<T> {
         Packet {
             queue: unsafe { spsc::Queue::new(128) },
 
-            cnt: AtomicInt::new(0),
+            cnt: AtomicIsize::new(0),
             steals: 0,
-            to_wake: AtomicUint::new(0),
+            to_wake: AtomicUsize::new(0),
 
             port_dropped: AtomicBool::new(false),
         }
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index b2cc807eb11..30304dffb75 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -41,7 +41,7 @@ use self::Blocker::*;
 use vec::Vec;
 use core::mem;
 
-use sync::atomic::{Ordering, AtomicUint};
+use sync::atomic::{Ordering, AtomicUsize};
 use sync::mpsc::blocking::{self, WaitToken, SignalToken};
 use sync::mpsc::select::StartResult::{self, Installed, Abort};
 use sync::{Mutex, MutexGuard};
@@ -49,7 +49,7 @@ use sync::{Mutex, MutexGuard};
 pub struct Packet<T> {
     /// Only field outside of the mutex. Just done for kicks, but mainly because
     /// the other shared channel already had the code implemented
-    channels: AtomicUint,
+    channels: AtomicUsize,
 
     lock: Mutex<State<T>>,
 }
@@ -138,7 +138,7 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
 impl<T: Send> Packet<T> {
     pub fn new(cap: uint) -> Packet<T> {
         Packet {
-            channels: AtomicUint::new(1),
+            channels: AtomicUsize::new(1),
             lock: Mutex::new(State {
                 disconnected: false,
                 blocker: NoneBlocked,
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index c1b55c6ff78..73d5332d16f 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -160,6 +160,7 @@ unsafe impl Sync for StaticMutex {}
 /// Deref and DerefMut implementations
 #[must_use]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct MutexGuard<'a, T: 'a> {
     // funny underscores due to how Deref/DerefMut currently work (they
     // disregard field privacy).
@@ -169,6 +170,25 @@ pub struct MutexGuard<'a, T: 'a> {
     __marker: marker::NoSend,
 }
 
+/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
+/// dropped (falls out of scope), the lock will be unlocked.
+///
+/// The data protected by the mutex can be access through this guard via its
+/// Deref and DerefMut implementations
+#[must_use]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct MutexGuard<'a, T: 'a> {
+    // funny underscores due to how Deref/DerefMut currently work (they
+    // disregard field privacy).
+    __lock: &'a StaticMutex,
+    __data: &'a UnsafeCell<T>,
+    __poison: poison::Guard,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
+
 /// Static initialization of a mutex. This constant can be used to initialize
 /// other mutex constants.
 #[unstable = "may be merged with Mutex in the future"]
@@ -279,6 +299,7 @@ impl StaticMutex {
 }
 
 impl<'mutex, T> MutexGuard<'mutex, T> {
+    #[cfg(stage0)] // NOTE remove afte next snapshot
     fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
            -> LockResult<MutexGuard<'mutex, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
@@ -290,6 +311,18 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
             }
         })
     }
+
+    #[cfg(not(stage0))] // NOTE remove cfg afte next snapshot
+    fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
+           -> LockResult<MutexGuard<'mutex, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            MutexGuard {
+                __lock: lock,
+                __data: data,
+                __poison: guard,
+            }
+        })
+    }
 }
 
 #[stable]
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 3bf2ae277e0..6231a91833d 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -17,7 +17,7 @@ use int;
 use marker::Sync;
 use mem::drop;
 use ops::FnOnce;
-use sync::atomic::{AtomicInt, Ordering, ATOMIC_INT_INIT};
+use sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
 use sync::{StaticMutex, MUTEX_INIT};
 
 /// A synchronization primitive which can be used to run a one-time global
@@ -39,8 +39,8 @@ use sync::{StaticMutex, MUTEX_INIT};
 #[stable]
 pub struct Once {
     mutex: StaticMutex,
-    cnt: AtomicInt,
-    lock_cnt: AtomicInt,
+    cnt: AtomicIsize,
+    lock_cnt: AtomicIsize,
 }
 
 unsafe impl Sync for Once {}
@@ -49,8 +49,8 @@ unsafe impl Sync for Once {}
 #[stable]
 pub const ONCE_INIT: Once = Once {
     mutex: MUTEX_INIT,
-    cnt: ATOMIC_INT_INIT,
-    lock_cnt: ATOMIC_INT_INIT,
+    cnt: ATOMIC_ISIZE_INIT,
+    lock_cnt: ATOMIC_ISIZE_INIT,
 };
 
 impl Once {
diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs
index 385df45b400..cc8c331ef39 100644
--- a/src/libstd/sync/poison.rs
+++ b/src/libstd/sync/poison.rs
@@ -99,8 +99,23 @@ impl<T> fmt::Show for PoisonError<T> {
 impl<T> PoisonError<T> {
     /// Consumes this error indicating that a lock is poisoned, returning the
     /// underlying guard to allow access regardless.
-    #[stable]
+    #[deprecated="renamed to into_inner"]
     pub fn into_guard(self) -> T { self.guard }
+
+    /// Consumes this error indicating that a lock is poisoned, returning the
+    /// underlying guard to allow access regardless.
+    #[unstable]
+    pub fn into_inner(self) -> T { self.guard }
+
+    /// Reaches into this error indicating that a lock is poisoned, returning a
+    /// reference to the underlying guard to allow access regardless.
+    #[unstable]
+    pub fn get_ref(&self) -> &T { &self.guard }
+
+    /// Reaches into this error indicating that a lock is poisoned, returning a
+    /// mutable reference to the underlying guard to allow access regardless.
+    #[unstable]
+    pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
 }
 
 impl<T> FromError<PoisonError<T>> for TryLockError<T> {
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 7db2111cc46..237f6d08a95 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -110,16 +110,31 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
 /// dropped.
 #[must_use]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct RwLockReadGuard<'a, T: 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
     __marker: marker::NoSend,
 }
 
+/// RAII structure used to release the shared read access of a lock when
+/// dropped.
+#[must_use]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct RwLockReadGuard<'a, T: 'a> {
+    __lock: &'a StaticRwLock,
+    __data: &'a UnsafeCell<T>,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<'a, T> !marker::Send for RwLockReadGuard<'a, T> {}
+
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
 #[must_use]
 #[stable]
+#[cfg(stage0)] // NOTE remove impl after next snapshot
 pub struct RwLockWriteGuard<'a, T: 'a> {
     __lock: &'a StaticRwLock,
     __data: &'a UnsafeCell<T>,
@@ -127,6 +142,20 @@ pub struct RwLockWriteGuard<'a, T: 'a> {
     __marker: marker::NoSend,
 }
 
+/// RAII structure used to release the exclusive write access of a lock when
+/// dropped.
+#[must_use]
+#[stable]
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+pub struct RwLockWriteGuard<'a, T: 'a> {
+    __lock: &'a StaticRwLock,
+    __data: &'a UnsafeCell<T>,
+    __poison: poison::Guard,
+}
+
+#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {}
+
 impl<T: Send + Sync> RwLock<T> {
     /// Creates a new instance of an RwLock which is unlocked and read to go.
     #[stable]
@@ -303,6 +332,7 @@ impl StaticRwLock {
 }
 
 impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
            -> LockResult<RwLockReadGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |_| {
@@ -313,8 +343,20 @@ impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
             }
         })
     }
+
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
+           -> LockResult<RwLockReadGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |_| {
+            RwLockReadGuard {
+                __lock: lock,
+                __data: data,
+            }
+        })
+    }
 }
 impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
+    #[cfg(stage0)] // NOTE remove impl after next snapshot
     fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
            -> LockResult<RwLockWriteGuard<'rwlock, T>> {
         poison::map_result(lock.poison.borrow(), |guard| {
@@ -326,6 +368,18 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
             }
         })
     }
+
+    #[cfg(not(stage0))] // NOTE remove cfg after next snapshot
+    fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
+           -> LockResult<RwLockWriteGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |guard| {
+            RwLockWriteGuard {
+                __lock: lock,
+                __data: data,
+                __poison: guard,
+            }
+        })
+    }
 }
 
 #[stable]
diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs
index f6161ec193d..d8b85987236 100644
--- a/src/libstd/sys/common/backtrace.rs
+++ b/src/libstd/sys/common/backtrace.rs
@@ -12,10 +12,10 @@ use prelude::v1::*;
 
 use io::IoResult;
 
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 pub const HEX_WIDTH: uint = 18;
 
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 pub const HEX_WIDTH: uint = 10;
 
 // All rust symbols are in theory lists of "::"-separated identifiers. Some
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
index ce5ab67ae61..88bb9395cf1 100644
--- a/src/libstd/sys/common/stack.rs
+++ b/src/libstd/sys/common/stack.rs
@@ -231,6 +231,12 @@ pub unsafe fn record_sp_limit(limit: uint) {
     unsafe fn target_record_sp_limit(_: uint) {
     }
 
+    // powerpc - FIXME(POWERPC): missing...
+    #[cfg(target_arch = "powerpc")]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+
+
     // iOS segmented stack is disabled for now, see related notes
     #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
     unsafe fn target_record_sp_limit(_: uint) {
@@ -326,6 +332,12 @@ pub unsafe fn get_sp_limit() -> uint {
         1024
     }
 
+    // powepc - FIXME(POWERPC): missing...
+    #[cfg(target_arch = "powerpc")]
+    unsafe fn target_get_sp_limit() -> uint {
+        1024
+    }
+
     // iOS doesn't support segmented stacks yet. This function might
     // be called by runtime though so it is unsafe to mark it as
     // unreachable, let's return a fixed constant.
diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs
index e9af796c674..edd16e0c062 100644
--- a/src/libstd/sys/common/thread_local.rs
+++ b/src/libstd/sys/common/thread_local.rs
@@ -58,7 +58,7 @@
 
 use prelude::v1::*;
 
-use sync::atomic::{self, AtomicUint, Ordering};
+use sync::atomic::{self, AtomicUsize, Ordering};
 use sync::{Mutex, Once, ONCE_INIT};
 
 use sys::thread_local as imp;
@@ -97,7 +97,7 @@ pub struct StaticKey {
 
 /// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
 pub struct StaticKeyInner {
-    key: AtomicUint,
+    key: AtomicUsize,
 }
 
 /// A type for a safely managed OS-based TLS slot.
@@ -137,7 +137,7 @@ pub const INIT: StaticKey = StaticKey {
 ///
 /// This value allows specific configuration of the destructor for a TLS key.
 pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
-    key: atomic::ATOMIC_UINT_INIT,
+    key: atomic::ATOMIC_USIZE_INIT,
 };
 
 static INIT_KEYS: Once = ONCE_INIT;
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index 1d523ed6edd..9016d1a2c99 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -33,7 +33,9 @@ pub const FIONBIO: libc::c_ulong = 0x8004667e;
           target_os = "android"))]
 pub const FIONBIO: libc::c_ulong = 0x5421;
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 pub const FIONBIO: libc::c_ulong = 0x667e;
 
 #[cfg(any(target_os = "macos",
@@ -49,7 +51,9 @@ pub const FIOCLEX: libc::c_ulong = 0x20006601;
           target_os = "android"))]
 pub const FIOCLEX: libc::c_ulong = 0x5451;
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 pub const FIOCLEX: libc::c_ulong = 0x6601;
 
 #[cfg(any(target_os = "macos",
@@ -169,20 +173,22 @@ mod signal {
     unsafe impl ::marker::Sync for sigaction { }
 
     #[repr(C)]
-    #[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+    #[cfg(target_pointer_width = "32")]
     pub struct sigset_t {
         __val: [libc::c_ulong; 32],
     }
 
     #[repr(C)]
-    #[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+    #[cfg(target_pointer_width = "64")]
     pub struct sigset_t {
         __val: [libc::c_ulong; 16],
     }
 }
 
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 mod signal {
     use libc;
 
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index 52dd261824f..85a65bbef50 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -10,9 +10,12 @@
 
 use cell::UnsafeCell;
 use libc;
+use std::option::Option::{Some, None};
 use sys::mutex::{self, Mutex};
+use sys::time;
 use sys::sync as ffi;
 use time::Duration;
+use num::{Int, NumCast};
 
 pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
 
@@ -46,33 +49,46 @@ impl Condvar {
         debug_assert_eq!(r, 0);
     }
 
+    // This implementation is modeled after libcxx's condition_variable
+    // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
+    // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        assert!(dur >= Duration::nanoseconds(0));
+        if dur <= Duration::zero() {
+            return false;
+        }
 
-        // First, figure out what time it currently is
-        let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 };
-        let r = ffi::gettimeofday(&mut tv, 0 as *mut _);
+        // First, figure out what time it currently is, in both system and stable time.
+        // pthread_cond_timedwait uses system time, but we want to report timeout based on stable
+        // time.
+        let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
+        let stable_now = time::SteadyTime::now();
+        let r = ffi::gettimeofday(&mut sys_now, 0 as *mut _);
         debug_assert_eq!(r, 0);
 
-        // Offset that time with the specified duration
-        let abs = Duration::seconds(tv.tv_sec as i64) +
-                  Duration::microseconds(tv.tv_usec as i64) +
-                  dur;
-        let ns = abs.num_nanoseconds().unwrap() as u64;
-        let timeout = libc::timespec {
-            tv_sec: (ns / 1000000000) as libc::time_t,
-            tv_nsec: (ns % 1000000000) as libc::c_long,
+        let seconds = NumCast::from(dur.num_seconds());
+        let timeout = match seconds.and_then(|s| sys_now.tv_sec.checked_add(s)) {
+            Some(sec) => {
+                libc::timespec {
+                    tv_sec: sec,
+                    tv_nsec: (dur - Duration::seconds(dur.num_seconds()))
+                        .num_nanoseconds().unwrap() as libc::c_long,
+                }
+            }
+            None => {
+                libc::timespec {
+                    tv_sec: Int::max_value(),
+                    tv_nsec: 1_000_000_000 - 1,
+                }
+            }
         };
 
         // And wait!
-        let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
-                                            &timeout);
-        if r != 0 {
-            debug_assert_eq!(r as int, libc::ETIMEDOUT as int);
-            false
-        } else {
-            true
-        }
+        let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), &timeout);
+        debug_assert!(r == libc::ETIMEDOUT || r == 0);
+
+        // ETIMEDOUT is not a totally reliable method of determining timeout due to clock shifts,
+        // so do the check ourselves
+        &time::SteadyTime::now() - &stable_now < dur
     }
 
     #[inline]
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 6a408aa60f0..bb98d1e052a 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -52,6 +52,7 @@ pub mod sync;
 pub mod tcp;
 pub mod thread;
 pub mod thread_local;
+pub mod time;
 pub mod timer;
 pub mod tty;
 pub mod udp;
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 48a51813ba4..2b5ced5085b 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -150,6 +150,7 @@ mod imp {
               all(target_os = "linux", target_arch = "aarch64"),
               all(target_os = "linux", target_arch = "mips"), // may not match
               all(target_os = "linux", target_arch = "mipsel"), // may not match
+              all(target_os = "linux", target_arch = "powerpc"), // may not match
               target_os = "android"))] // may not match
     mod signal {
         use libc;
@@ -182,14 +183,12 @@ mod imp {
             sa_restorer: *mut libc::c_void,
         }
 
-        #[cfg(any(all(stage0, target_word_size = "32"),
-                  all(not(stage0), target_pointer_width = "32")))]
+        #[cfg(target_pointer_width = "32")]
         #[repr(C)]
         pub struct sigset_t {
             __val: [libc::c_ulong; 32],
         }
-        #[cfg(any(all(stage0, target_word_size = "64"),
-                  all(not(stage0), target_pointer_width = "64")))]
+        #[cfg(target_pointer_width = "64")]
         #[repr(C)]
         pub struct sigset_t {
             __val: [libc::c_ulong; 16],
diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs
index fbbdee1009d..c1e3fc88794 100644
--- a/src/libstd/sys/unix/sync.rs
+++ b/src/libstd/sys/unix/sync.rs
@@ -126,7 +126,8 @@ mod os {
     #[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
     #[cfg(target_arch = "aarch64")]
     const __SIZEOF_PTHREAD_MUTEX_T: uint = 48 - 8;
@@ -136,7 +137,8 @@ mod os {
               target_arch = "arm",
               target_arch = "aarch64",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
 
     #[cfg(any(target_arch = "x86_64",
@@ -146,7 +148,8 @@ mod os {
     #[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_RWLOCK_T: uint = 32 - 8;
 
     #[repr(C)]
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 2416b64f98f..ac51b68795f 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -93,7 +93,19 @@ pub mod guard {
 
         PAGE_SIZE = psize as uint;
 
-        let stackaddr = get_stack_start();
+        let mut stackaddr = get_stack_start();
+
+        // Ensure stackaddr is page aligned! A parent process might
+        // have reset RLIMIT_STACK to be non-page aligned. The
+        // pthread_attr_getstack() reports the usable stack area
+        // stackaddr < stackaddr + stacksize, so if stackaddr is not
+        // page-aligned, calculate the fix such that stackaddr <
+        // new_page_aligned_stackaddr < stackaddr + stacksize
+        let remainder = (stackaddr as usize) % (PAGE_SIZE as usize);
+        if remainder != 0 {
+            stackaddr = ((stackaddr as usize) + (PAGE_SIZE as usize) - remainder)
+                as *mut libc::c_void;
+        }
 
         // Rellocate the last page of the stack.
         // This ensures SIGBUS will be raised on
diff --git a/src/libstd/sys/unix/time.rs b/src/libstd/sys/unix/time.rs
new file mode 100644
index 00000000000..cc1e23fbca9
--- /dev/null
+++ b/src/libstd/sys/unix/time.rs
@@ -0,0 +1,124 @@
+// 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.
+
+pub use self::inner::SteadyTime;
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+mod inner {
+    use libc;
+    use time::Duration;
+    use ops::Sub;
+    use sync::{Once, ONCE_INIT};
+
+    pub struct SteadyTime {
+        t: u64
+    }
+
+    extern {
+        pub fn mach_absolute_time() -> u64;
+        pub fn mach_timebase_info(info: *mut libc::mach_timebase_info) -> libc::c_int;
+    }
+
+    impl SteadyTime {
+        pub fn now() -> SteadyTime {
+            SteadyTime {
+                t: unsafe { mach_absolute_time() },
+            }
+        }
+
+        pub fn ns(&self) -> u64 {
+            let info = info();
+            self.t * info.numer as u64 / info.denom as u64
+        }
+    }
+
+    fn info() -> &'static libc::mach_timebase_info {
+        static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
+            numer: 0,
+            denom: 0,
+        };
+        static ONCE: Once = ONCE_INIT;
+
+        unsafe {
+            ONCE.call_once(|| {
+                mach_timebase_info(&mut INFO);
+            });
+            &INFO
+        }
+    }
+
+    impl<'a> Sub for &'a SteadyTime {
+        type Output = Duration;
+
+        fn sub(self, other: &SteadyTime) -> Duration {
+            unsafe {
+                let info = info();
+                let diff = self.t as i64 - other.t as i64;
+                Duration::nanoseconds(diff * info.numer as i64 / info.denom as i64)
+            }
+        }
+    }
+}
+
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+mod inner {
+    use libc;
+    use time::Duration;
+    use ops::Sub;
+
+    const NSEC_PER_SEC: i64 = 1_000_000_000;
+
+    pub struct SteadyTime {
+        t: libc::timespec,
+    }
+
+    // Apparently android provides this in some other library?
+    #[cfg(not(target_os = "android"))]
+    #[link(name = "rt")]
+    extern {}
+
+    extern {
+        fn clock_gettime(clk_id: libc::c_int, tp: *mut libc::timespec) -> libc::c_int;
+    }
+
+    impl SteadyTime {
+        pub fn now() -> SteadyTime {
+            let mut t = SteadyTime {
+                t: libc::timespec {
+                    tv_sec: 0,
+                    tv_nsec: 0,
+                }
+            };
+            unsafe {
+                assert_eq!(0, clock_gettime(libc::CLOCK_MONOTONIC, &mut t.t));
+            }
+            t
+        }
+
+        pub fn ns(&self) -> u64 {
+            self.t.tv_sec as u64 * NSEC_PER_SEC as u64 + self.t.tv_nsec as u64
+        }
+    }
+
+    impl<'a> Sub for &'a SteadyTime {
+        type Output = Duration;
+
+        fn sub(self, other: &SteadyTime) -> Duration {
+            if self.t.tv_nsec >= other.t.tv_nsec {
+                Duration::seconds(self.t.tv_sec as i64 - other.t.tv_sec as i64) +
+                    Duration::nanoseconds(self.t.tv_nsec as i64 - other.t.tv_nsec as i64)
+            } else {
+                Duration::seconds(self.t.tv_sec as i64 - 1 - other.t.tv_sec as i64) +
+                    Duration::nanoseconds(self.t.tv_nsec as i64 + NSEC_PER_SEC -
+                                          other.t.tv_nsec as i64)
+            }
+        }
+    }
+}
diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs
index 62f3242a206..c0c231a9e73 100644
--- a/src/libstd/sys/unix/timer.rs
+++ b/src/libstd/sys/unix/timer.rs
@@ -211,7 +211,7 @@ impl Timer {
         // instead of ()
         HELPER.boot(|| {}, helper);
 
-        static ID: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+        static ID: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
         let id = ID.fetch_add(1, Ordering::Relaxed);
         Ok(Timer {
             id: id,
diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs
index 291a8024cfc..db8038006fd 100644
--- a/src/libstd/sys/windows/condvar.rs
+++ b/src/libstd/sys/windows/condvar.rs
@@ -27,16 +27,18 @@ impl Condvar {
 
     #[inline]
     pub unsafe fn wait(&self, mutex: &Mutex) {
-        let r = ffi::SleepConditionVariableCS(self.inner.get(),
-                                              mutex::raw(mutex),
-                                              libc::INFINITE);
+        let r = ffi::SleepConditionVariableSRW(self.inner.get(),
+                                               mutex::raw(mutex),
+                                               libc::INFINITE,
+                                               0);
         debug_assert!(r != 0);
     }
 
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        let r = ffi::SleepConditionVariableCS(self.inner.get(),
-                                              mutex::raw(mutex),
-                                              dur.num_milliseconds() as DWORD);
+        let r = ffi::SleepConditionVariableSRW(self.inner.get(),
+                                               mutex::raw(mutex),
+                                               dur.num_milliseconds() as DWORD,
+                                               0);
         if r == 0 {
             const ERROR_TIMEOUT: DWORD = 0x5B4;
             debug_assert_eq!(os::errno() as uint, ERROR_TIMEOUT as uint);
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 0e706c3cc6a..72fc2f8700d 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -50,6 +50,7 @@ pub mod rwlock;
 pub mod sync;
 pub mod stack_overflow;
 pub mod tcp;
+pub mod time;
 pub mod thread;
 pub mod thread_local;
 pub mod timer;
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
index 1def99a3741..828ad795ed3 100644
--- a/src/libstd/sys/windows/mutex.rs
+++ b/src/libstd/sys/windows/mutex.rs
@@ -8,73 +8,51 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use prelude::v1::*;
-
-use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
-use alloc::{self, heap};
-
-use libc::DWORD;
+use marker::Sync;
+use cell::UnsafeCell;
 use sys::sync as ffi;
 
-const SPIN_COUNT: DWORD = 4000;
+pub struct Mutex { inner: UnsafeCell<ffi::SRWLOCK> }
 
-pub struct Mutex { inner: AtomicUint }
-
-pub const MUTEX_INIT: Mutex = Mutex { inner: ATOMIC_UINT_INIT };
+pub const MUTEX_INIT: Mutex = Mutex {
+    inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
+};
 
 unsafe impl Sync for Mutex {}
 
 #[inline]
-pub unsafe fn raw(m: &Mutex) -> ffi::LPCRITICAL_SECTION {
-    m.get()
+pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
+    m.inner.get()
 }
 
+// So you might be asking why we're using SRWLock instead of CriticalSection?
+//
+// 1. SRWLock is several times faster than CriticalSection according to benchmarks performed on both
+// Windows 8 and Windows 7.
+//
+// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix implementation
+// deadlocks so consistency is preferred. See #19962 for more details.
+//
+// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy is there there are
+// no guarantees of fairness.
+
 impl Mutex {
     #[inline]
-    pub unsafe fn new() -> Mutex {
-        Mutex { inner: AtomicUint::new(init_lock() as uint) }
-    }
+    pub unsafe fn new() -> Mutex { MUTEX_INIT }
     #[inline]
     pub unsafe fn lock(&self) {
-        ffi::EnterCriticalSection(self.get())
+        ffi::AcquireSRWLockExclusive(self.inner.get())
     }
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        ffi::TryEnterCriticalSection(self.get()) != 0
+        ffi::TryAcquireSRWLockExclusive(self.inner.get()) != 0
     }
     #[inline]
     pub unsafe fn unlock(&self) {
-        ffi::LeaveCriticalSection(self.get())
+        ffi::ReleaseSRWLockExclusive(self.inner.get())
     }
+    #[inline]
     pub unsafe fn destroy(&self) {
-        let lock = self.inner.swap(0, Ordering::SeqCst);
-        if lock != 0 { free_lock(lock as ffi::LPCRITICAL_SECTION) }
-    }
-
-    unsafe fn get(&self) -> ffi::LPCRITICAL_SECTION {
-        match self.inner.load(Ordering::SeqCst) {
-            0 => {}
-            n => return n as ffi::LPCRITICAL_SECTION
-        }
-        let lock = init_lock();
-        match self.inner.compare_and_swap(0, lock as uint, Ordering::SeqCst) {
-            0 => return lock as ffi::LPCRITICAL_SECTION,
-            _ => {}
-        }
-        free_lock(lock);
-        return self.inner.load(Ordering::SeqCst) as ffi::LPCRITICAL_SECTION;
+        // ...
     }
 }
-
-unsafe fn init_lock() -> ffi::LPCRITICAL_SECTION {
-    let block = heap::allocate(ffi::CRITICAL_SECTION_SIZE, 8)
-                        as ffi::LPCRITICAL_SECTION;
-    if block.is_null() { alloc::oom() }
-    ffi::InitializeCriticalSectionAndSpinCount(block, SPIN_COUNT);
-    return block;
-}
-
-unsafe fn free_lock(h: ffi::LPCRITICAL_SECTION) {
-    ffi::DeleteCriticalSection(h);
-    heap::deallocate(h as *mut _, ffi::CRITICAL_SECTION_SIZE, 8);
-}
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index 064633f321c..4540068133b 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -36,7 +36,7 @@ const BUF_BYTES : uint = 2048u;
 pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
     match v.iter().position(|c| *c == 0) {
         // don't include the 0
-        Some(i) => &v[0..i],
+        Some(i) => &v[..i],
         None => v
     }
 }
diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs
index cbca47912b5..d60646b7db9 100644
--- a/src/libstd/sys/windows/sync.rs
+++ b/src/libstd/sys/windows/sync.rs
@@ -8,17 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc::{BOOL, DWORD, c_void, LPVOID};
+use libc::{BOOL, DWORD, c_void, LPVOID, c_ulong};
 use libc::types::os::arch::extra::BOOLEAN;
 
-pub type LPCRITICAL_SECTION = *mut c_void;
-pub type LPCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
-pub type LPSRWLOCK = *mut SRWLOCK;
-
-#[cfg(target_arch = "x86")]
-pub const CRITICAL_SECTION_SIZE: uint = 24;
-#[cfg(target_arch = "x86_64")]
-pub const CRITICAL_SECTION_SIZE: uint = 40;
+pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
+pub type PSRWLOCK = *mut SRWLOCK;
+pub type ULONG = c_ulong;
 
 #[repr(C)]
 pub struct CONDITION_VARIABLE { pub ptr: LPVOID }
@@ -31,28 +26,19 @@ pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE {
 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: 0 as *mut _ };
 
 extern "system" {
-    // critical sections
-    pub fn InitializeCriticalSectionAndSpinCount(
-                    lpCriticalSection: LPCRITICAL_SECTION,
-                    dwSpinCount: DWORD) -> BOOL;
-    pub fn DeleteCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
-    pub fn EnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
-    pub fn LeaveCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
-    pub fn TryEnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION) -> BOOL;
-
     // condition variables
-    pub fn SleepConditionVariableCS(ConditionVariable: LPCONDITION_VARIABLE,
-                                    CriticalSection: LPCRITICAL_SECTION,
-                                    dwMilliseconds: DWORD) -> BOOL;
-    pub fn WakeConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
-    pub fn WakeAllConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
+    pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
+                                     SRWLock: PSRWLOCK,
+                                     dwMilliseconds: DWORD,
+                                     Flags: ULONG) -> BOOL;
+    pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
+    pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
 
     // slim rwlocks
-    pub fn AcquireSRWLockExclusive(SRWLock: LPSRWLOCK);
-    pub fn AcquireSRWLockShared(SRWLock: LPSRWLOCK);
-    pub fn ReleaseSRWLockExclusive(SRWLock: LPSRWLOCK);
-    pub fn ReleaseSRWLockShared(SRWLock: LPSRWLOCK);
-    pub fn TryAcquireSRWLockExclusive(SRWLock: LPSRWLOCK) -> BOOLEAN;
-    pub fn TryAcquireSRWLockShared(SRWLock: LPSRWLOCK) -> BOOLEAN;
+    pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK);
+    pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK);
+    pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK);
+    pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
+    pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
+    pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
 }
-
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
new file mode 100644
index 00000000000..20ceff0aa69
--- /dev/null
+++ b/src/libstd/sys/windows/time.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.
+use libc;
+use ops::Sub;
+use time::Duration;
+use sync::{Once, ONCE_INIT};
+
+pub struct SteadyTime {
+    t: libc::LARGE_INTEGER,
+}
+
+impl SteadyTime {
+    pub fn now() -> SteadyTime {
+        let mut t = SteadyTime { t: 0 };
+        unsafe { libc::QueryPerformanceCounter(&mut t.t); }
+        t
+    }
+
+    pub fn ns(&self) -> u64 {
+        self.t as u64 * 1_000_000_000 / frequency() as u64
+    }
+}
+
+fn frequency() -> libc::LARGE_INTEGER {
+    static mut FREQUENCY: libc::LARGE_INTEGER = 0;
+    static ONCE: Once = ONCE_INIT;
+
+    unsafe {
+        ONCE.call_once(|| {
+            libc::QueryPerformanceFrequency(&mut FREQUENCY);
+        });
+        FREQUENCY
+    }
+}
+
+impl<'a> Sub for &'a SteadyTime {
+    type Output = Duration;
+
+    fn sub(self, other: &SteadyTime) -> Duration {
+        let diff = self.t as i64 - other.t as i64;
+        Duration::microseconds(diff * 1_000_000 / frequency() as i64)
+    }
+}
diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs
index d6c94f27a8b..f62571942a7 100644
--- a/src/libstd/time/mod.rs
+++ b/src/libstd/time/mod.rs
@@ -10,7 +10,7 @@
 
 //! Temporal quantification.
 
-use libc;
+use sys::time::SteadyTime;
 
 pub use self::duration::Duration;
 
@@ -20,69 +20,5 @@ pub mod duration;
 /// in nanoseconds since an unspecified epoch.
 // NB: this is intentionally not public, this is not ready to stabilize its api.
 fn precise_time_ns() -> u64 {
-    return os_precise_time_ns();
-
-    #[cfg(windows)]
-    fn os_precise_time_ns() -> u64 {
-        let mut ticks_per_s = 0;
-        assert_eq!(unsafe {
-            libc::QueryPerformanceFrequency(&mut ticks_per_s)
-        }, 1);
-        let ticks_per_s = if ticks_per_s == 0 {1} else {ticks_per_s};
-        let mut ticks = 0;
-        assert_eq!(unsafe {
-            libc::QueryPerformanceCounter(&mut ticks)
-        }, 1);
-
-        return (ticks as u64 * 1000000000) / (ticks_per_s as u64);
-    }
-
-    #[cfg(any(target_os = "macos", target_os = "ios"))]
-    fn os_precise_time_ns() -> u64 {
-        use sync;
-
-        static mut TIMEBASE: libc::mach_timebase_info = libc::mach_timebase_info { numer: 0,
-                                                                                   denom: 0 };
-        static ONCE: sync::Once = sync::ONCE_INIT;
-        unsafe {
-            ONCE.call_once(|| {
-                imp::mach_timebase_info(&mut TIMEBASE);
-            });
-            let time = imp::mach_absolute_time();
-            time * TIMEBASE.numer as u64 / TIMEBASE.denom as u64
-        }
-    }
-
-    #[cfg(not(any(windows, target_os = "macos", target_os = "ios")))]
-    fn os_precise_time_ns() -> u64 {
-        let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
-        unsafe {
-            imp::clock_gettime(libc::CLOCK_MONOTONIC, &mut ts);
-        }
-        return (ts.tv_sec as u64) * 1000000000 + (ts.tv_nsec as u64)
-    }
-}
-
-#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios")))]
-mod imp {
-    use libc::{c_int, timespec};
-
-    // Apparently android provides this in some other library?
-    #[cfg(not(target_os = "android"))]
-    #[link(name = "rt")]
-    extern {}
-
-    extern {
-        pub fn clock_gettime(clk_id: c_int, tp: *mut timespec) -> c_int;
-    }
-
-}
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-mod imp {
-    use libc::{c_int, mach_timebase_info};
-
-    extern {
-        pub fn mach_absolute_time() -> u64;
-        pub fn mach_timebase_info(info: *mut mach_timebase_info) -> c_int;
-    }
+    SteadyTime::now().ns()
 }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 630f7768885..0ea429116b0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -747,6 +747,8 @@ pub enum Expr_ {
     /// Variable reference, possibly containing `::` and/or
     /// type parameters, e.g. foo::bar::<baz>
     ExprPath(Path),
+    /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
+    ExprQPath(P<QPath>),
 
     ExprAddrOf(Mutability, P<Expr>),
     ExprBreak(Option<Ident>),
@@ -771,12 +773,12 @@ pub enum Expr_ {
 ///
 ///     <Vec<T> as SomeTrait>::SomeAssociatedItem
 ///      ^~~~~     ^~~~~~~~~   ^~~~~~~~~~~~~~~~~~
-///      self_type  trait_name  item_name
+///      self_type  trait_name  item_path
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub struct QPath {
     pub self_type: P<Ty>,
     pub trait_ref: P<TraitRef>,
-    pub item_name: Ident, // FIXME(#20301) -- should use Name
+    pub item_path: PathSegment,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@@ -955,7 +957,7 @@ pub type Mac = Spanned<Mac_>;
 pub enum Mac_ {
     // NB: the additional ident for a macro_rules-style macro is actually
     // stored in the enclosing item. Oog.
-    MacInvocTT(Path, Vec<TokenTree> , SyntaxContext),   // new macro-invocation
+    MacInvocTT(Path, Vec<TokenTree>, SyntaxContext),   // new macro-invocation
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@@ -1528,6 +1530,19 @@ pub struct ViewItem {
     pub span: Span,
 }
 
+impl ViewItem {
+    pub fn id(&self) -> NodeId {
+        match self.node {
+            ViewItemExternCrate(_, _, id) => id,
+            ViewItemUse(ref vp) => match vp.node {
+                ViewPathSimple(_, _, id) => id,
+                ViewPathGlob(_, id) => id,
+                ViewPathList(_, _, id) => id,
+            }
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub enum ViewItem_ {
     /// Ident: name used to refer to this crate in the code
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 3ef57279175..f462a730d3a 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -107,6 +107,7 @@ pub fn path_to_string<PI: Iterator<Item=PathElem>>(path: PI) -> String {
 #[derive(Copy, Show)]
 pub enum Node<'ast> {
     NodeItem(&'ast Item),
+    NodeViewItem(&'ast ViewItem),
     NodeForeignItem(&'ast ForeignItem),
     NodeTraitItem(&'ast TraitItem),
     NodeImplItem(&'ast ImplItem),
@@ -133,6 +134,7 @@ enum MapEntry<'ast> {
 
     /// All the node types, with a parent ID.
     EntryItem(NodeId, &'ast Item),
+    EntryViewItem(NodeId, &'ast ViewItem),
     EntryForeignItem(NodeId, &'ast ForeignItem),
     EntryTraitItem(NodeId, &'ast TraitItem),
     EntryImplItem(NodeId, &'ast ImplItem),
@@ -167,6 +169,7 @@ impl<'ast> MapEntry<'ast> {
     fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
         match node {
             NodeItem(n) => EntryItem(p, n),
+            NodeViewItem(n) => EntryViewItem(p, n),
             NodeForeignItem(n) => EntryForeignItem(p, n),
             NodeTraitItem(n) => EntryTraitItem(p, n),
             NodeImplItem(n) => EntryImplItem(p, n),
@@ -185,6 +188,7 @@ impl<'ast> MapEntry<'ast> {
     fn parent(self) -> Option<NodeId> {
         Some(match self {
             EntryItem(id, _) => id,
+            EntryViewItem(id, _) => id,
             EntryForeignItem(id, _) => id,
             EntryTraitItem(id, _) => id,
             EntryImplItem(id, _) => id,
@@ -204,6 +208,7 @@ impl<'ast> MapEntry<'ast> {
     fn to_node(self) -> Option<Node<'ast>> {
         Some(match self {
             EntryItem(_, n) => NodeItem(n),
+            EntryViewItem(_, n) => NodeViewItem(n),
             EntryForeignItem(_, n) => NodeForeignItem(n),
             EntryTraitItem(_, n) => NodeTraitItem(n),
             EntryImplItem(_, n) => NodeImplItem(n),
@@ -336,6 +341,13 @@ impl<'ast> Map<'ast> {
         }
     }
 
+    pub fn expect_view_item(&self, id: NodeId) -> &'ast ViewItem {
+        match self.find(id) {
+            Some(NodeViewItem(view_item)) => view_item,
+            _ => panic!("expected view item, found {}", self.node_to_string(id))
+        }
+    }
+
     pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef {
         match self.find(id) {
             Some(NodeItem(i)) => {
@@ -513,7 +525,7 @@ impl<'ast> Map<'ast> {
         NodesMatchingSuffix {
             map: self,
             item_name: parts.last().unwrap(),
-            in_which: &parts[0..(parts.len() - 1)],
+            in_which: &parts[..(parts.len() - 1)],
             idx: 0,
         }
     }
@@ -521,6 +533,7 @@ impl<'ast> Map<'ast> {
     pub fn opt_span(&self, id: NodeId) -> Option<Span> {
         let sp = match self.find(id) {
             Some(NodeItem(item)) => item.span,
+            Some(NodeViewItem(item)) => item.span,
             Some(NodeForeignItem(foreign_item)) => foreign_item.span,
             Some(NodeTraitItem(trait_method)) => {
                 match *trait_method {
@@ -813,6 +826,11 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         self.parent = parent;
     }
 
+    fn visit_view_item(&mut self, item: &'ast ViewItem) {
+        self.insert(item.id(), NodeViewItem(item));
+        visit::walk_view_item(self, item);
+    }
+
     fn visit_pat(&mut self, pat: &'ast Pat) {
         self.insert(pat.id, match pat.node {
             // Note: this is at least *potentially* a pattern...
@@ -1018,6 +1036,7 @@ impl<'a> NodePrinter for pprust::State<'a> {
     fn print_node(&mut self, node: &Node) -> IoResult<()> {
         match *node {
             NodeItem(a)        => self.print_item(&*a),
+            NodeViewItem(a)    => self.print_view_item(&*a),
             NodeForeignItem(a) => self.print_foreign_item(&*a),
             NodeTraitItem(a)   => self.print_trait_method(&*a),
             NodeImplItem(a)    => self.print_impl_item(&*a),
@@ -1060,6 +1079,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
             };
             format!("{} {}{}", item_str, path_str, id_str)
         }
+        Some(NodeViewItem(item)) => {
+            format!("view item {}{}", pprust::view_item_to_string(&*item), id_str)
+        }
         Some(NodeForeignItem(item)) => {
             let path_str = map.path_to_str_with_ident(id, item.ident);
             format!("foreign item {}{}", path_str, id_str)
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 9a422e17bb4..bf26687deed 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -313,7 +313,7 @@ impl FileMap {
             let begin = begin.to_uint();
             let slice = &self.src[begin..];
             match slice.find('\n') {
-                Some(e) => &slice[0..e],
+                Some(e) => &slice[..e],
                 None => slice
             }.to_string()
         })
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 3f81dac2b0d..7213b0fa955 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -118,6 +118,9 @@ impl SpanHandler {
     pub fn fileline_note(&self, sp: Span, msg: &str) {
         self.handler.custom_emit(&self.cm, FileLine(sp), msg, Note);
     }
+    pub fn fileline_help(&self, sp: Span, msg: &str) {
+        self.handler.custom_emit(&self.cm, FileLine(sp), msg, Help);
+    }
     pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
         self.handler.emit(Some((&self.cm, sp)), msg, Bug);
         panic!(ExplicitBug);
@@ -277,7 +280,7 @@ fn print_maybe_styled(w: &mut EmitterWriter,
             // to be miscolored. We assume this is rare enough that we don't
             // have to worry about it.
             if msg.ends_with("\n") {
-                try!(t.write_str(&msg[0..(msg.len()-1)]));
+                try!(t.write_str(&msg[..(msg.len()-1)]));
                 try!(t.reset());
                 try!(t.write_str("\n"));
             } else {
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index fd3bac5b2fc..4258eb32fdf 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -63,6 +63,12 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     'statement: loop {
         match state {
             Asm => {
+                if asm_str_style.is_some() {
+                    // If we already have a string with instructions,
+                    // ending up in Asm state again is an error.
+                    cx.span_err(sp, "malformed inline assembly");
+                    return DummyResult::expr(sp);
+                }
                 let (s, style) = match expr_to_string(cx, p.parse_expr(),
                                                    "inline assembly must be a string literal") {
                     Some((s, st)) => (s, st),
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 9b9d8a9ceb3..f2498abfa6a 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -73,6 +73,108 @@ impl<F> ItemModifier for F
     }
 }
 
+#[derive(Show,Clone)]
+pub enum Annotatable {
+    Item(P<ast::Item>),
+    TraitItem(ast::TraitItem),
+    ImplItem(ast::ImplItem),
+}
+
+impl Annotatable {
+    pub fn attrs(&self) -> &[ast::Attribute] {
+        match *self {
+            Annotatable::Item(ref i) => &i.attrs[],
+            Annotatable::TraitItem(ref i) => match *i {
+                ast::TraitItem::RequiredMethod(ref tm) => &tm.attrs[],
+                ast::TraitItem::ProvidedMethod(ref m) => &m.attrs[],
+                ast::TraitItem::TypeTraitItem(ref at) => &at.attrs[],
+            },
+            Annotatable::ImplItem(ref i) => match *i {
+                ast::ImplItem::MethodImplItem(ref m) => &m.attrs[],
+                ast::ImplItem::TypeImplItem(ref t) => &t.attrs[],
+            }
+        }
+    }
+
+    pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
+        match self {
+            Annotatable::Item(i) => Annotatable::Item(P(ast::Item {
+                attrs: attrs,
+                ..(*i).clone()
+            })),
+            Annotatable::TraitItem(i) => match i {
+                ast::TraitItem::RequiredMethod(tm) => Annotatable::TraitItem(
+                    ast::TraitItem::RequiredMethod(
+                        ast::TypeMethod { attrs: attrs, ..tm })),
+                ast::TraitItem::ProvidedMethod(m) => Annotatable::TraitItem(
+                    ast::TraitItem::ProvidedMethod(P(
+                        ast::Method { attrs: attrs, ..(*m).clone() }))),
+                ast::TraitItem::TypeTraitItem(at) => Annotatable::TraitItem(
+                    ast::TraitItem::TypeTraitItem(P(
+                        ast::AssociatedType { attrs: attrs, ..(*at).clone() }))),
+            },
+            Annotatable::ImplItem(i) => match i {
+                ast::ImplItem::MethodImplItem(m) => Annotatable::ImplItem(
+                    ast::ImplItem::MethodImplItem(P(
+                        ast::Method { attrs: attrs, ..(*m).clone() }))),
+                ast::ImplItem::TypeImplItem(t) => Annotatable::ImplItem(
+                    ast::ImplItem::TypeImplItem(P(
+                        ast::Typedef { attrs: attrs, ..(*t).clone() }))),
+            }
+        }
+    }
+
+    pub fn expect_item(self) -> P<ast::Item> {
+        match self {
+            Annotatable::Item(i) => i,
+            _ => panic!("expected Item")
+        }
+    }
+
+    pub fn expect_trait_item(self) -> ast::TraitItem {
+        match self {
+            Annotatable::TraitItem(i) => i,
+            _ => panic!("expected Item")
+        }
+    }
+
+    pub fn expect_impl_item(self) -> ast::ImplItem {
+        match self {
+            Annotatable::ImplItem(i) => i,
+            _ => panic!("expected Item")
+        }
+    }
+}
+
+// A more flexible ItemModifier (ItemModifier should go away, eventually, FIXME).
+// meta_item is the annotation, item is the item being modified, parent_item
+// is the impl or trait item is declared in if item is part of such a thing.
+// FIXME Decorators should follow the same pattern too.
+pub trait MultiItemModifier {
+    fn expand(&self,
+              ecx: &mut ExtCtxt,
+              span: Span,
+              meta_item: &ast::MetaItem,
+              item: Annotatable)
+              -> Annotatable;
+}
+
+impl<F> MultiItemModifier for F
+    where F: Fn(&mut ExtCtxt,
+                Span,
+                &ast::MetaItem,
+                Annotatable) -> Annotatable
+{
+    fn expand(&self,
+              ecx: &mut ExtCtxt,
+              span: Span,
+              meta_item: &ast::MetaItem,
+              item: Annotatable)
+              -> Annotatable {
+        (*self)(ecx, span, meta_item, item)
+    }
+}
+
 /// Represents a thing that maps token trees to Macro Results
 pub trait TTMacroExpander {
     fn expand<'cx>(&self,
@@ -299,6 +401,10 @@ pub enum SyntaxExtension {
     /// in-place.
     Modifier(Box<ItemModifier + 'static>),
 
+    /// A syntax extension that is attached to an item and modifies it
+    /// in-place. More flexible version than Modifier.
+    MultiModifier(Box<MultiItemModifier + 'static>),
+
     /// A normal, function-like syntax extension.
     ///
     /// `bytes!` is a `NormalTT`.
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index 7c65d2b4ff4..f73023ddd1e 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -92,11 +92,10 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
     let recurse = vec!(cx.ident_of(krate),
                     cx.ident_of("Decodable"),
                     cx.ident_of("decode"));
+    let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
     // throw an underscore in front to suppress unused variable warnings
     let blkarg = cx.ident_of("_d");
     let blkdecoder = cx.expr_ident(trait_span, blkarg);
-    let calldecode = cx.expr_call_global(trait_span, recurse, vec!(blkdecoder.clone()));
-    let lambdadecode = cx.lambda_expr_1(trait_span, calldecode, blkarg);
 
     return match *substr.fields {
         StaticStruct(_, ref summary) => {
@@ -116,7 +115,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                     cx.expr_method_call(span, blkdecoder.clone(), read_struct_field,
                                         vec!(cx.expr_str(span, name),
                                           cx.expr_uint(span, field),
-                                          lambdadecode.clone())))
+                                          exprdecode.clone())))
             });
             let result = cx.expr_ok(trait_span, result);
             cx.expr_method_call(trait_span,
@@ -147,7 +146,7 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                     let idx = cx.expr_uint(span, field);
                     cx.expr_try(span,
                         cx.expr_method_call(span, blkdecoder.clone(), rvariant_arg,
-                                            vec!(idx, lambdadecode.clone())))
+                                            vec!(idx, exprdecode.clone())))
                 });
 
                 arms.push(cx.arm(v_span,
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index e6b6f7bbd49..161b27d7abb 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -21,13 +21,7 @@
 //!   (e.g. `Option<T>`), the parameters are automatically given the
 //!   current trait as a bound. (This includes separate type parameters
 //!   and lifetimes for methods.)
-//! - Additional bounds on the type parameters, e.g. the `Ord` instance
-//!   requires an explicit `PartialEq` bound at the
-//!   moment. (`TraitDef.additional_bounds`)
-//!
-//! Unsupported: FIXME #6257: calling methods on reference fields,
-//! e.g. derive Eq/Ord/Clone don't work on `struct A(&int)`,
-//! because of how the auto-dereferencing happens.
+//! - Additional bounds on the type parameters (`TraitDef.additional_bounds`)
 //!
 //! The most important thing for implementers is the `Substructure` and
 //! `SubstructureFields` objects. The latter groups 5 possibilities of the
@@ -79,6 +73,15 @@
 //! enums (one for each variant). For empty struct and empty enum
 //! variants, it is represented as a count of 0.
 //!
+//! # "`cs`" functions
+//!
+//! The `cs_...` functions ("combine substructure) are designed to
+//! make life easier by providing some pre-made recipes for common
+//! tasks; mostly calling the function being derived on all the
+//! arguments and then combining them back together in some way (or
+//! letting the user chose that). They are not meant to be the only
+//! way to handle the structures that this code creates.
+//!
 //! # Examples
 //!
 //! The following simplified `PartialEq` is used for in-code examples:
@@ -102,22 +105,22 @@
 //! When generating the `expr` for the `A` impl, the `SubstructureFields` is
 //!
 //! ```{.text}
-//! Struct(~[FieldInfo {
+//! Struct(vec![FieldInfo {
 //!            span: <span of x>
 //!            name: Some(<ident of x>),
 //!            self_: <expr for &self.x>,
-//!            other: ~[<expr for &other.x]
+//!            other: vec![<expr for &other.x]
 //!          }])
 //! ```
 //!
 //! For the `B` impl, called with `B(a)` and `B(b)`,
 //!
 //! ```{.text}
-//! Struct(~[FieldInfo {
+//! Struct(vec![FieldInfo {
 //!           span: <span of `int`>,
 //!           name: None,
-//!           <expr for &a>
-//!           ~[<expr for &b>]
+//!           self_: <expr for &a>
+//!           other: vec![<expr for &b>]
 //!          }])
 //! ```
 //!
@@ -128,11 +131,11 @@
 //!
 //! ```{.text}
 //! EnumMatching(0, <ast::Variant for C0>,
-//!              ~[FieldInfo {
+//!              vec![FieldInfo {
 //!                 span: <span of int>
 //!                 name: None,
 //!                 self_: <expr for &a>,
-//!                 other: ~[<expr for &b>]
+//!                 other: vec![<expr for &b>]
 //!               }])
 //! ```
 //!
@@ -140,11 +143,11 @@
 //!
 //! ```{.text}
 //! EnumMatching(1, <ast::Variant for C1>,
-//!              ~[FieldInfo {
+//!              vec![FieldInfo {
 //!                 span: <span of x>
 //!                 name: Some(<ident of x>),
 //!                 self_: <expr for &self.x>,
-//!                 other: ~[<expr for &other.x>]
+//!                 other: vec![<expr for &other.x>]
 //!                }])
 //! ```
 //!
@@ -152,7 +155,7 @@
 //!
 //! ```{.text}
 //! EnumNonMatchingCollapsed(
-//!     ~[<ident of self>, <ident of __arg_1>],
+//!     vec![<ident of self>, <ident of __arg_1>],
 //!     &[<ast::Variant for C0>, <ast::Variant for C1>],
 //!     &[<ident for self index value>, <ident of __arg_1 index value>])
 //! ```
@@ -168,16 +171,16 @@
 //!
 //! ## Static
 //!
-//! A static method on the above would result in,
+//! A static method on the types above would result in,
 //!
 //! ```{.text}
-//! StaticStruct(<ast::StructDef of A>, Named(~[(<ident of x>, <span of x>)]))
+//! StaticStruct(<ast::StructDef of A>, Named(vec![(<ident of x>, <span of x>)]))
 //!
-//! StaticStruct(<ast::StructDef of B>, Unnamed(~[<span of x>]))
+//! StaticStruct(<ast::StructDef of B>, Unnamed(vec![<span of x>]))
 //!
-//! StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span of int>])),
-//!                                   (<ident of C1>, <span of C1>,
-//!                                    Named(~[(<ident of x>, <span of x>)]))])
+//! StaticEnum(<ast::EnumDef of C>,
+//!            vec![(<ident of C0>, <span of C0>, Unnamed(vec![<span of int>])),
+//!                 (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)]))])
 //! ```
 
 pub use self::StaticFields::*;
@@ -1378,8 +1381,8 @@ pub fn cs_fold<F>(use_foldl: bool,
 /// process the collected results. i.e.
 ///
 /// ```
-/// f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1),
-///              self_2.method(__arg_1_2, __arg_2_2)])
+/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
+///                  self_2.method(__arg_1_2, __arg_2_2)])
 /// ```
 #[inline]
 pub fn cs_same_method<F>(f: F,
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index db99c142443..08336be87d1 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -63,11 +63,21 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
 fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
     let state_expr = match substr.nonself_args {
         [ref state_expr] => state_expr,
-        _ => cx.span_bug(trait_span, "incorrect number of arguments in `deriving(Hash)`")
+        _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`")
     };
-    let hash_ident = substr.method_ident;
     let call_hash = |&: span, thing_expr| {
-        let expr = cx.expr_method_call(span, thing_expr, hash_ident, vec!(state_expr.clone()));
+        let hash_path = {
+            let strs = vec![
+                cx.ident_of("std"),
+                cx.ident_of("hash"),
+                cx.ident_of("Hash"),
+                cx.ident_of("hash"),
+            ];
+
+            cx.expr_path(cx.path_global(span, strs))
+        };
+        let ref_thing = cx.expr_addr_of(span, thing_expr);
+        let expr = cx.expr_call(span, hash_path, vec!(ref_thing, state_expr.clone()));
         cx.stmt_expr(expr)
     };
     let mut stmts = Vec::new();
@@ -86,16 +96,12 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
 
             fs
         }
-        _ => cx.span_bug(trait_span, "impossible substructure in `deriving(Hash)`")
+        _ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`")
     };
 
     for &FieldInfo { ref self_, span, .. } in fields.iter() {
         stmts.push(call_hash(span, self_.clone()));
     }
 
-    if stmts.len() == 0 {
-        cx.span_bug(trait_span, "#[derive(Hash)] needs at least one field");
-    }
-
     cx.expr_block(cx.block(trait_span, stmts, None))
 }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 9ef996ac317..c95bdeefd45 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -395,81 +395,15 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
                    -> SmallVector<P<ast::Item>> {
     let it = expand_item_modifiers(it, fld);
 
-    let mut decorator_items = SmallVector::zero();
-    let mut new_attrs = Vec::new();
-    for attr in it.attrs.iter() {
-        let mname = attr.name();
-
-        match fld.cx.syntax_env.find(&intern(mname.get())) {
-            Some(rc) => match *rc {
-                Decorator(ref dec) => {
-                    attr::mark_used(attr);
-
-                    fld.cx.bt_push(ExpnInfo {
-                        call_site: attr.span,
-                        callee: NameAndSpan {
-                            name: mname.get().to_string(),
-                            format: MacroAttribute,
-                            span: None
-                        }
-                    });
-
-                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
-                    // but that double-mut-borrows fld
-                    let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
-                    dec.expand(fld.cx, attr.span, &*attr.node.value, &*it,
-                               box |&mut : item| items.push(item));
-                    decorator_items.extend(items.into_iter()
-                        .flat_map(|item| expand_item(item, fld).into_iter()));
-
-                    fld.cx.bt_pop();
-                }
-                _ => new_attrs.push((*attr).clone()),
-            },
-            _ => new_attrs.push((*attr).clone()),
-        }
-    }
-
-    let mut new_items = match it.node {
-        ast::ItemMac(..) => expand_item_mac(it, fld),
-        ast::ItemMod(_) | ast::ItemForeignMod(_) => {
-            let valid_ident =
-                it.ident.name != parse::token::special_idents::invalid.name;
-
-            if valid_ident {
-                fld.cx.mod_push(it.ident);
-            }
-            let macro_use = contains_macro_use(fld, &new_attrs[]);
-            let result = with_exts_frame!(fld.cx.syntax_env,
-                                          macro_use,
-                                          noop_fold_item(it, fld));
-            if valid_ident {
-                fld.cx.mod_pop();
-            }
-            result
-        },
-        _ => {
-            let it = P(ast::Item {
-                attrs: new_attrs,
-                ..(*it).clone()
-            });
-            noop_fold_item(it, fld)
-        }
-    };
-
-    new_items.push_all(decorator_items);
-    new_items
+    expand_annotatable(Annotatable::Item(it), fld)
+        .into_iter().map(|i| i.expect_item()).collect()
 }
 
 fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
                          -> P<ast::Item> {
     // partition the attributes into ItemModifiers and others
-    let (modifiers, other_attrs): (Vec<_>, _) = it.attrs.iter().cloned().partition(|attr| {
-        match fld.cx.syntax_env.find(&intern(attr.name().get())) {
-            Some(rc) => match *rc { Modifier(_) => true, _ => false },
-            _ => false
-        }
-    });
+    let (modifiers, other_attrs) = modifiers(&it.attrs, fld);
+
     // update the attrs, leave everything else alone. Is this mutation really a good idea?
     it = P(ast::Item {
         attrs: other_attrs,
@@ -477,7 +411,8 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
     });
 
     if modifiers.is_empty() {
-        return it;
+        let it = expand_item_multi_modifier(Annotatable::Item(it), fld);
+        return it.expect_item();
     }
 
     for attr in modifiers.iter() {
@@ -504,7 +439,12 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
         }
     }
 
-    // expansion may have added new ItemModifiers
+    // Expansion may have added new ItemModifiers.
+    // It is possible, that an item modifier could expand to a multi-modifier or
+    // vice versa. In this case we will expand all modifiers before multi-modifiers,
+    // which might give an odd ordering. However, I think it is unlikely that the
+    // two kinds will be mixed, and I old-style multi-modifiers should be deprecated
+    // anyway.
     expand_item_modifiers(it, fld)
 }
 
@@ -1029,6 +969,196 @@ impl<'a> Folder for PatIdentRenamer<'a> {
     }
 }
 
+fn expand_annotatable(a: Annotatable,
+                      fld: &mut MacroExpander)
+                      -> SmallVector<Annotatable> {
+    let a = expand_item_multi_modifier(a, fld);
+
+    let mut decorator_items = SmallVector::zero();
+    let mut new_attrs = Vec::new();
+    for attr in a.attrs().iter() {
+        let mname = attr.name();
+
+        match fld.cx.syntax_env.find(&intern(mname.get())) {
+            Some(rc) => match *rc {
+                Decorator(ref dec) => {
+                    let it = match a {
+                        Annotatable::Item(ref it) => it,
+                        // ItemDecorators are only implemented for Items.
+                        _ => break,
+                    };
+
+                    attr::mark_used(attr);
+
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            name: mname.get().to_string(),
+                            format: MacroAttribute,
+                            span: None
+                        }
+                    });
+
+                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
+                    // but that double-mut-borrows fld
+                    let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
+                    dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
+                               box |&mut: item| items.push(item));
+                    decorator_items.extend(items.into_iter()
+                        .flat_map(|item| expand_item(item, fld).into_iter()));
+
+                    fld.cx.bt_pop();
+                }
+                _ => new_attrs.push((*attr).clone()),
+            },
+            _ => new_attrs.push((*attr).clone()),
+        }
+    }
+
+    let mut new_items: SmallVector<Annotatable> = match a {
+        Annotatable::Item(it) => match it.node {
+            ast::ItemMac(..) => {
+                expand_item_mac(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect()
+            }
+            ast::ItemMod(_) | ast::ItemForeignMod(_) => {
+                let valid_ident =
+                    it.ident.name != parse::token::special_idents::invalid.name;
+
+                if valid_ident {
+                    fld.cx.mod_push(it.ident);
+                }
+                let macro_use = contains_macro_use(fld, &new_attrs[]);
+                let result = with_exts_frame!(fld.cx.syntax_env,
+                                              macro_use,
+                                              noop_fold_item(it, fld));
+                if valid_ident {
+                    fld.cx.mod_pop();
+                }
+                result.into_iter().map(|i| Annotatable::Item(i)).collect()
+            },
+            _ => {
+                let it = P(ast::Item {
+                    attrs: new_attrs,
+                    ..(*it).clone()
+                });
+                noop_fold_item(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect()
+            }
+        },
+        Annotatable::TraitItem(it) => match it {
+            ast::TraitItem::ProvidedMethod(m) => {
+                expand_method(m, fld).into_iter().map(|m|
+                    Annotatable::TraitItem(ast::TraitItem::ProvidedMethod(m))).collect()
+            }
+            ast::TraitItem::RequiredMethod(m) => {
+                SmallVector::one(Annotatable::TraitItem(
+                    ast::TraitItem::RequiredMethod(fld.fold_type_method(m))))
+            }
+            ast::TraitItem::TypeTraitItem(t) => {
+                SmallVector::one(Annotatable::TraitItem(
+                    ast::TraitItem::TypeTraitItem(P(fld.fold_associated_type((*t).clone())))))
+            }
+        },
+        Annotatable::ImplItem(it) => match it {
+            ast::ImplItem::MethodImplItem(m) => {
+                expand_method(m, fld).into_iter().map(|m|
+                    Annotatable::ImplItem(ast::ImplItem::MethodImplItem(m))).collect()
+            }
+            ast::ImplItem::TypeImplItem(t) => {
+                SmallVector::one(Annotatable::ImplItem(
+                    ast::ImplItem::TypeImplItem(P(fld.fold_typedef((*t).clone())))))
+            }
+        }
+    };
+
+    new_items.push_all(decorator_items.into_iter().map(|i| Annotatable::Item(i)).collect());
+    new_items
+}
+
+fn expand_trait_item(i: ast::TraitItem,
+                     fld: &mut MacroExpander)
+                     -> SmallVector<ast::TraitItem> {
+    expand_annotatable(Annotatable::TraitItem(i), fld)
+        .into_iter().map(|i| i.expect_trait_item()).collect()
+
+}
+
+fn expand_impl_item(i: ast::ImplItem,
+                    fld: &mut MacroExpander)
+                    -> SmallVector<ast::ImplItem> {
+    expand_annotatable(Annotatable::ImplItem(i), fld)
+        .into_iter().map(|i| i.expect_impl_item()).collect()
+}
+
+// partition the attributes into ItemModifiers and others
+fn modifiers(attrs: &Vec<ast::Attribute>,
+             fld: &MacroExpander)
+             -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
+    attrs.iter().cloned().partition(|attr| {
+        match fld.cx.syntax_env.find(&intern(attr.name().get())) {
+            Some(rc) => match *rc {
+                Modifier(_) => true,
+                _ => false
+            },
+            _ => false
+        }
+    })
+}
+
+// partition the attributes into MultiModifiers and others
+fn multi_modifiers(attrs: &[ast::Attribute],
+                   fld: &MacroExpander)
+                   -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
+    attrs.iter().cloned().partition(|attr| {
+        match fld.cx.syntax_env.find(&intern(attr.name().get())) {
+            Some(rc) => match *rc {
+                MultiModifier(_) => true,
+                _ => false
+            },
+            _ => false
+        }
+    })
+}
+
+fn expand_item_multi_modifier(mut it: Annotatable,
+                              fld: &mut MacroExpander)
+                              -> Annotatable {
+    let (modifiers, other_attrs) = multi_modifiers(it.attrs(), fld);
+
+    // Update the attrs, leave everything else alone. Is this mutation really a good idea?
+    it = it.fold_attrs(other_attrs);
+
+    if modifiers.is_empty() {
+        return it
+    }
+
+    for attr in modifiers.iter() {
+        let mname = attr.name();
+
+        match fld.cx.syntax_env.find(&intern(mname.get())) {
+            Some(rc) => match *rc {
+                MultiModifier(ref mac) => {
+                    attr::mark_used(attr);
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            name: mname.get().to_string(),
+                            format: MacroAttribute,
+                            span: None,
+                        }
+                    });
+                    it = mac.expand(fld.cx, attr.span, &*attr.node.value, it);
+                    fld.cx.bt_pop();
+                }
+                _ => unreachable!()
+            },
+            _ => unreachable!()
+        }
+    }
+
+    // Expansion may have added new ItemModifiers.
+    expand_item_multi_modifier(it, fld)
+}
+
 // expand a method
 fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<ast::Method>> {
     m.and_then(|m| match m.node {
@@ -1042,7 +1172,7 @@ fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<as
                       vis) => {
             let id = fld.new_id(m.id);
             let (rewritten_fn_decl, rewritten_body)
-                = expand_and_rename_fn_decl_and_block(decl,body,fld);
+                = expand_and_rename_fn_decl_and_block(decl, body, fld);
             SmallVector::one(P(ast::Method {
                     attrs: m.attrs.move_map(|a| fld.fold_attribute(a)),
                     id: id,
@@ -1147,6 +1277,14 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
         expand_arm(arm, self)
     }
 
+    fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
+        expand_trait_item(i, self)
+    }
+
+    fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
+        expand_impl_item(i, self)
+    }
+
     fn fold_method(&mut self, method: P<ast::Method>) -> SmallVector<P<ast::Method>> {
         expand_method(method, self)
     }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 8175c0a9eec..9231d4ad659 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -71,6 +71,8 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
     ("visible_private_types", Active),
     ("slicing_syntax", Active),
     ("box_syntax", Active),
+    ("on_unimplemented", Active),
+    ("simd_ffi", Active),
 
     ("if_let", Accepted),
     ("while_let", Accepted),
@@ -127,6 +129,7 @@ pub struct Features {
     pub visible_private_types: bool,
     pub quote: bool,
     pub old_orphan_check: bool,
+    pub simd_ffi: bool,
 }
 
 impl Features {
@@ -138,6 +141,7 @@ impl Features {
             visible_private_types: false,
             quote: false,
             old_orphan_check: false,
+            simd_ffi: false,
         }
     }
 }
@@ -249,6 +253,10 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
                 self.gate_feature("linkage", i.span,
                                   "the `linkage` attribute is experimental \
                                    and not portable across platforms")
+            } else if attr.name() == "rustc_on_unimplemented" {
+                self.gate_feature("on_unimplemented", i.span,
+                                  "the `#[rustc_on_unimplemented]` attribute \
+                                  is an experimental feature")
             }
         }
         match i.node {
@@ -519,6 +527,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
         visible_private_types: cx.has_feature("visible_private_types"),
         quote: cx.has_feature("quote"),
         old_orphan_check: cx.has_feature("old_orphan_check"),
+        simd_ffi: cx.has_feature("simd_ffi"),
     },
     unknown_features)
 }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index c45a4005339..16c29c9b5eb 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -102,6 +102,14 @@ pub trait Folder : Sized {
         noop_fold_item_underscore(i, self)
     }
 
+    fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
+        noop_fold_trait_item(i, self)
+    }
+
+    fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
+        noop_fold_impl_item(i, self)
+    }
+
     fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
         noop_fold_fn_decl(d, self)
     }
@@ -454,7 +462,10 @@ pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
         QPath {
             self_type: fld.fold_ty(qpath.self_type),
             trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
-            item_name: fld.fold_ident(qpath.item_name),
+            item_path: PathSegment {
+                identifier: fld.fold_ident(qpath.item_path.identifier),
+                parameters: fld.fold_path_parameters(qpath.item_path.parameters),
+            }
         }
     })
 }
@@ -1004,21 +1015,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
         ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
-            let mut new_impl_items = Vec::new();
-            for impl_item in impl_items.iter() {
-                match *impl_item {
-                    MethodImplItem(ref x) => {
-                        for method in folder.fold_method((*x).clone())
-                                            .into_iter() {
-                            new_impl_items.push(MethodImplItem(method))
-                        }
-                    }
-                    TypeImplItem(ref t) => {
-                        new_impl_items.push(TypeImplItem(
-                                P(folder.fold_typedef((**t).clone()))));
-                    }
-                }
-            }
+            let new_impl_items = impl_items.into_iter().flat_map(|item| {
+                folder.fold_impl_item(item).into_iter()
+            }).collect();
             let ifce = match ifce {
                 None => None,
                 Some(ref trait_ref) => {
@@ -1032,43 +1031,50 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
                      folder.fold_ty(ty),
                      new_impl_items)
         }
-        ItemTrait(unsafety, generics, bounds, methods) => {
+        ItemTrait(unsafety, generics, bounds, items) => {
             let bounds = folder.fold_bounds(bounds);
-            let methods = methods.into_iter().flat_map(|method| {
-                let r = match method {
-                    RequiredMethod(m) => {
-                            SmallVector::one(RequiredMethod(
-                                    folder.fold_type_method(m)))
-                                .into_iter()
-                    }
-                    ProvidedMethod(method) => {
-                        // the awkward collect/iter idiom here is because
-                        // even though an iter and a map satisfy the same
-                        // trait bound, they're not actually the same type, so
-                        // the method arms don't unify.
-                        let methods: SmallVector<ast::TraitItem> =
-                            folder.fold_method(method).into_iter()
-                            .map(|m| ProvidedMethod(m)).collect();
-                        methods.into_iter()
-                    }
-                    TypeTraitItem(at) => {
-                        SmallVector::one(TypeTraitItem(P(
-                                    folder.fold_associated_type(
-                                        (*at).clone()))))
-                            .into_iter()
-                    }
-                };
-                r
+            let items = items.into_iter().flat_map(|item| {
+                folder.fold_trait_item(item).into_iter()
             }).collect();
             ItemTrait(unsafety,
                       folder.fold_generics(generics),
                       bounds,
-                      methods)
+                      items)
         }
         ItemMac(m) => ItemMac(folder.fold_mac(m)),
     }
 }
 
+pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T) -> SmallVector<TraitItem> {
+    match i {
+        RequiredMethod(m) => {
+                SmallVector::one(RequiredMethod(
+                        folder.fold_type_method(m)))
+        }
+        ProvidedMethod(method) => {
+            folder.fold_method(method).into_iter()
+                .map(|m| ProvidedMethod(m)).collect()
+        }
+        TypeTraitItem(at) => {
+            SmallVector::one(TypeTraitItem(P(
+                        folder.fold_associated_type(
+                            (*at).clone()))))
+        }
+    }
+}
+
+pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T) -> SmallVector<ImplItem> {
+    match i {
+        MethodImplItem(ref x) => {
+            folder.fold_method((*x).clone()).into_iter().map(|m| MethodImplItem(m)).collect()
+        }
+        TypeImplItem(ref t) => {
+            SmallVector::one(TypeImplItem(
+                    P(folder.fold_typedef((**t).clone()))))
+        }
+    }
+}
+
 pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMethod {
     let TypeMethod {
         id,
@@ -1381,6 +1387,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                           e2.map(|x| folder.fold_expr(x)))
             }
             ExprPath(pth) => ExprPath(folder.fold_path(pth)),
+            ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
             ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
             ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 9c947f422e9..fa675a9fcaa 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -28,6 +28,7 @@
 #![feature(box_syntax)]
 #![feature(quote, unsafe_destructor)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate arena;
 extern crate fmt_macros;
@@ -35,6 +36,7 @@ extern crate serialize;
 extern crate term;
 extern crate libc;
 #[macro_use] extern crate log;
+#[macro_use] #[no_link] extern crate rustc_bitflags;
 
 extern crate "serialize" as rustc_serialize; // used by deriving
 
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index e9e207e7dbc..9d03ec73af8 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -24,14 +24,6 @@ use ptr::P;
 pub enum ObsoleteSyntax {
     Sized,
     ForSized,
-    OwnedType,
-    OwnedExpr,
-    OwnedPattern,
-    OwnedVector,
-    OwnedSelf,
-    ImportRenaming,
-    SubsliceMatch,
-    ExternCrateRenaming,
     ProcType,
     ProcExpr,
     ClosureType,
@@ -69,38 +61,6 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
                 "`proc` expression",
                 "use a `move ||` expression instead",
             ),
-            ObsoleteSyntax::OwnedType => (
-                "`~` notation for owned pointers",
-                "use `Box<T>` in `std::owned` instead"
-            ),
-            ObsoleteSyntax::OwnedExpr => (
-                "`~` notation for owned pointer allocation",
-                "use the `box` operator instead of `~`"
-            ),
-            ObsoleteSyntax::OwnedPattern => (
-                "`~` notation for owned pointer patterns",
-                "use the `box` operator instead of `~`"
-            ),
-            ObsoleteSyntax::OwnedVector => (
-                "`~[T]` is no longer a type",
-                "use the `Vec` type instead"
-            ),
-            ObsoleteSyntax::OwnedSelf => (
-                "`~self` is no longer supported",
-                "write `self: Box<Self>` instead"
-            ),
-            ObsoleteSyntax::ImportRenaming => (
-                "`use foo = bar` syntax",
-                "write `use bar as foo` instead"
-            ),
-            ObsoleteSyntax::SubsliceMatch => (
-                "subslice match syntax",
-                "instead of `..xs`, write `xs..` in a pattern"
-            ),
-            ObsoleteSyntax::ExternCrateRenaming => (
-                "`extern crate foo = bar` syntax",
-                "write `extern crate bar as foo` instead"
-            ),
             ObsoleteSyntax::ClosureType => (
                 "`|uint| -> bool` closure type syntax",
                 "use unboxed closures instead, no type annotation needed"
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 8d1599e176e..130972b4582 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -25,7 +25,7 @@ use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
 use ast::{ExprBreak, ExprCall, ExprCast};
 use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
-use ast::{ExprMethodCall, ExprParen, ExprPath};
+use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
@@ -52,7 +52,7 @@ use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
 use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
 use ast::{TtDelimited, TtSequence, TtToken};
 use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
-use ast::{TypeField, TyFixedLengthVec, TyBareFn};
+use ast::{TyFixedLengthVec, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
 use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
 use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
@@ -71,7 +71,7 @@ use parse::attr::ParserAttr;
 use parse::classify;
 use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed};
 use parse::lexer::{Reader, TokenAndSpan};
-use parse::obsolete::*;
+use parse::obsolete::{ParserObsoleteMethods, ObsoleteSyntax};
 use parse::token::{self, MatchNt, SubstNt, SpecialVarNt, InternedString};
 use parse::token::{keywords, special_idents, SpecialMacroVar};
 use parse::{new_sub_parser_from_file, ParseSess};
@@ -1404,22 +1404,6 @@ impl<'a> Parser<'a> {
         MutTy { ty: t, mutbl: mutbl }
     }
 
-    /// Parse [mut/const/imm] ID : TY
-    /// now used only by obsolete record syntax parser...
-    pub fn parse_ty_field(&mut self) -> TypeField {
-        let lo = self.span.lo;
-        let mutbl = self.parse_mutability();
-        let id = self.parse_ident();
-        self.expect(&token::Colon);
-        let ty = self.parse_ty_sum();
-        let hi = ty.span.hi;
-        ast::TypeField {
-            ident: id,
-            mt: MutTy { ty: ty, mutbl: mutbl },
-            span: mk_sp(lo, hi),
-        }
-    }
-
     /// Parse optional return type [ -> TY ] in function decl
     pub fn parse_ret_ty(&mut self) -> FunctionRetTy {
         if self.eat(&token::RArrow) {
@@ -1506,17 +1490,6 @@ impl<'a> Parser<'a> {
             } else {
                 TyTup(ts)
             }
-        } else if self.token == token::Tilde {
-            // OWNED POINTER
-            self.bump();
-            let last_span = self.last_span;
-            match self.token {
-                token::OpenDelim(token::Bracket) => {
-                    self.obsolete(last_span, ObsoleteSyntax::OwnedVector)
-                }
-                _ => self.obsolete(last_span, ObsoleteSyntax::OwnedType)
-            }
-            TyTup(vec![self.parse_ty()])
         } else if self.check(&token::BinOp(token::Star)) {
             // STAR POINTER (bare pointer?)
             self.bump();
@@ -1573,7 +1546,10 @@ impl<'a> Parser<'a> {
             TyQPath(P(QPath {
                 self_type: self_type,
                 trait_ref: P(trait_ref),
-                item_name: item_name,
+                item_path: ast::PathSegment {
+                    identifier: item_name,
+                    parameters: ast::PathParameters::none()
+                }
             }))
         } else if self.check(&token::ModSep) ||
                   self.token.is_ident() ||
@@ -1894,11 +1870,7 @@ impl<'a> Parser<'a> {
             if !self.eat(&token::ModSep) {
                 segments.push(ast::PathSegment {
                     identifier: identifier,
-                    parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
-                        lifetimes: Vec::new(),
-                        types: OwnedSlice::empty(),
-                        bindings: OwnedSlice::empty(),
-                    })
+                    parameters: ast::PathParameters::none()
                 });
                 return segments;
             }
@@ -2254,6 +2226,37 @@ impl<'a> Parser<'a> {
                 hi = self.last_span.hi;
             }
             _ => {
+                if self.eat_lt() {
+                    // QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
+                    let self_type = self.parse_ty_sum();
+                    self.expect_keyword(keywords::As);
+                    let trait_ref = self.parse_trait_ref();
+                    self.expect(&token::Gt);
+                    self.expect(&token::ModSep);
+                    let item_name = self.parse_ident();
+                    let parameters = if self.eat(&token::ModSep) {
+                        self.expect_lt();
+                        // Consumed `item::<`, go look for types
+                        let (lifetimes, types, bindings) =
+                            self.parse_generic_values_after_lt();
+                        ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+                            lifetimes: lifetimes,
+                            types: OwnedSlice::from_vec(types),
+                            bindings: OwnedSlice::from_vec(bindings),
+                        })
+                    } else {
+                        ast::PathParameters::none()
+                    };
+                    let hi = self.span.hi;
+                    return self.mk_expr(lo, hi, ExprQPath(P(QPath {
+                        self_type: self_type,
+                        trait_ref: P(trait_ref),
+                        item_path: ast::PathSegment {
+                            identifier: item_name,
+                            parameters: parameters
+                        }
+                    })));
+                }
                 if self.eat_keyword(keywords::Move) {
                     return self.parse_lambda_expr(CaptureByValue);
                 }
@@ -2802,20 +2805,6 @@ impl<'a> Parser<'a> {
             hi = e.span.hi;
             ex = ExprAddrOf(m, e);
           }
-          token::Tilde => {
-            self.bump();
-            let last_span = self.last_span;
-            match self.token {
-                token::OpenDelim(token::Bracket) => {
-                    self.obsolete(last_span, ObsoleteSyntax::OwnedVector)
-                },
-                _ => self.obsolete(last_span, ObsoleteSyntax::OwnedExpr)
-            }
-
-            let e = self.parse_prefix_expr();
-            hi = e.span.hi;
-            ex = self.mk_unary(UnUniq, e);
-          }
           token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => {
             // A range, closed above: `..expr`.
             self.bump();
@@ -3221,10 +3210,6 @@ impl<'a> Parser<'a> {
                             span: self.span,
                         }));
                         before_slice = false;
-                    } else {
-                        let _ = self.parse_pat();
-                        let span = self.span;
-                        self.obsolete(span, ObsoleteSyntax::SubsliceMatch);
                     }
                     continue
                 }
@@ -3333,20 +3318,6 @@ impl<'a> Parser<'a> {
                 span: mk_sp(lo, hi)
             })
           }
-          token::Tilde => {
-            // parse ~pat
-            self.bump();
-            let sub = self.parse_pat();
-            pat = PatBox(sub);
-            let last_span = self.last_span;
-            hi = last_span.hi;
-            self.obsolete(last_span, ObsoleteSyntax::OwnedPattern);
-            return P(ast::Pat {
-                id: ast::DUMMY_NODE_ID,
-                node: pat,
-                span: mk_sp(lo, hi)
-            })
-          }
           token::BinOp(token::And) | token::AndAnd => {
             // parse &pat and &mut pat
             let lo = self.span.lo;
@@ -4455,16 +4426,6 @@ impl<'a> Parser<'a> {
                 self_ident_hi = self.last_span.hi;
                 eself
             }
-            token::Tilde => {
-                // We need to make sure it isn't a type
-                if self.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
-                    self.bump();
-                    drop(self.expect_self_ident());
-                    let last_span = self.last_span;
-                    self.obsolete(last_span, ObsoleteSyntax::OwnedSelf)
-                }
-                SelfStatic
-            }
             token::BinOp(token::Star) => {
                 // Possibly "*self" or "*mut self" -- not supported. Try to avoid
                 // emitting cryptic "unexpected token" errors.
@@ -4505,15 +4466,6 @@ impl<'a> Parser<'a> {
                     } else {
                         SelfValue(self_ident)
                     }
-                } else if self.token.is_mutability() &&
-                        self.look_ahead(1, |t| *t == token::Tilde) &&
-                        self.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
-                    mutbl_self = self.parse_mutability();
-                    self.bump();
-                    drop(self.expect_self_ident());
-                    let last_span = self.last_span;
-                    self.obsolete(last_span, ObsoleteSyntax::OwnedSelf);
-                    SelfStatic
                 } else {
                     SelfStatic
                 }
@@ -5394,13 +5346,7 @@ impl<'a> Parser<'a> {
         let (maybe_path, ident) = match self.token {
             token::Ident(..) => {
                 let the_ident = self.parse_ident();
-                let path = if self.token == token::Eq {
-                    self.bump();
-                    let path = self.parse_str();
-                    let span = self.span;
-                    self.obsolete(span, ObsoleteSyntax::ExternCrateRenaming);
-                    Some(path)
-                } else if self.eat_keyword(keywords::As) {
+                let path = if self.eat_keyword(keywords::As) {
                     // skip the ident if there is one
                     if self.token.is_ident() { self.bump(); }
 
@@ -5663,17 +5609,7 @@ impl<'a> Parser<'a> {
         }
         // either a view item or an item:
         if self.eat_keyword(keywords::Extern) {
-            let next_is_mod = self.eat_keyword(keywords::Mod);
-
-            if next_is_mod || self.eat_keyword(keywords::Crate) {
-                if next_is_mod {
-                    let last_span = self.last_span;
-                    self.span_err(mk_sp(lo, last_span.hi),
-                                 &format!("`extern mod` is obsolete, use \
-                                          `extern crate` instead \
-                                          to refer to external \
-                                          crates.")[])
-                }
+            if self.eat_keyword(keywords::Crate) {
                 return self.parse_item_extern_crate(lo, visibility, attrs);
             }
 
@@ -6039,35 +5975,7 @@ impl<'a> Parser<'a> {
 
         let first_ident = self.parse_ident();
         let mut path = vec!(first_ident);
-        match self.token {
-          token::Eq => {
-            // x = foo::bar
-            self.bump();
-            let path_lo = self.span.lo;
-            path = vec!(self.parse_ident());
-            while self.check(&token::ModSep) {
-                self.bump();
-                let id = self.parse_ident();
-                path.push(id);
-            }
-            let span = mk_sp(path_lo, self.span.hi);
-            self.obsolete(span, ObsoleteSyntax::ImportRenaming);
-            let path = ast::Path {
-                span: span,
-                global: false,
-                segments: path.into_iter().map(|identifier| {
-                    ast::PathSegment {
-                        identifier: identifier,
-                        parameters: ast::PathParameters::none(),
-                    }
-                }).collect()
-            };
-            return P(spanned(lo, self.span.hi,
-                             ViewPathSimple(first_ident, path,
-                                           ast::DUMMY_NODE_ID)));
-          }
-
-          token::ModSep => {
+        if let token::ModSep = self.token {
             // foo::bar or foo::{a,b,c} or foo::*
             while self.check(&token::ModSep) {
                 self.bump();
@@ -6120,8 +6028,6 @@ impl<'a> Parser<'a> {
                   _ => break
                 }
             }
-          }
-          _ => ()
         }
         let mut rename_to = path[path.len() - 1u];
         let path = ast::Path {
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index b69b812c958..06d510d37bd 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -59,10 +59,6 @@
 //! line (which it can't) and so naturally place the content on its own line to
 //! avoid combining it with other lines and making matters even worse.
 
-pub use self::PrintStackBreak::*;
-pub use self::Breaks::*;
-pub use self::Token::*;
-
 use std::io;
 use std::string;
 use std::iter::repeat;
@@ -87,7 +83,7 @@ pub struct BeginToken {
 
 #[derive(Clone)]
 pub enum Token {
-    String(string::String, int),
+    String(String, int),
     Break(BreakToken),
     Begin(BeginToken),
     End,
@@ -96,12 +92,15 @@ pub enum Token {
 
 impl Token {
     pub fn is_eof(&self) -> bool {
-        match *self { Eof => true, _ => false }
+        match *self {
+            Token::Eof => true,
+            _ => false,
+        }
     }
 
     pub fn is_hardbreak_tok(&self) -> bool {
         match *self {
-            Break(BreakToken {
+            Token::Break(BreakToken {
                 offset: 0,
                 blank_space: bs
             }) if bs == SIZE_INFINITY =>
@@ -112,22 +111,22 @@ impl Token {
     }
 }
 
-pub fn tok_str(t: Token) -> string::String {
-    match t {
-        String(s, len) => return format!("STR({},{})", s, len),
-        Break(_) => return "BREAK".to_string(),
-        Begin(_) => return "BEGIN".to_string(),
-        End => return "END".to_string(),
-        Eof => return "EOF".to_string()
+pub fn tok_str(token: &Token) -> String {
+    match *token {
+        Token::String(ref s, len) => format!("STR({},{})", s, len),
+        Token::Break(_) => "BREAK".to_string(),
+        Token::Begin(_) => "BEGIN".to_string(),
+        Token::End => "END".to_string(),
+        Token::Eof => "EOF".to_string()
     }
 }
 
-pub fn buf_str(toks: Vec<Token>,
-               szs: Vec<int>,
+pub fn buf_str(toks: &[Token],
+               szs: &[int],
                left: uint,
                right: uint,
                lim: uint)
-               -> string::String {
+               -> String {
     let n = toks.len();
     assert_eq!(n, szs.len());
     let mut i = left;
@@ -140,7 +139,7 @@ pub fn buf_str(toks: Vec<Token>,
         }
         s.push_str(&format!("{}={}",
                            szs[i],
-                           tok_str(toks[i].clone()))[]);
+                           tok_str(&toks[i]))[]);
         i += 1u;
         i %= n;
     }
@@ -167,7 +166,7 @@ pub fn mk_printer(out: Box<io::Writer+'static>, linewidth: uint) -> Printer {
     // fall behind.
     let n: uint = 3 * linewidth;
     debug!("mk_printer {}", linewidth);
-    let token: Vec<Token> = repeat(Eof).take(n).collect();
+    let token: Vec<Token> = repeat(Token::Eof).take(n).collect();
     let size: Vec<int> = repeat(0i).take(n).collect();
     let scan_stack: Vec<uint> = repeat(0u).take(n).collect();
     Printer {
@@ -312,20 +311,18 @@ impl Printer {
     pub fn replace_last_token(&mut self, t: Token) {
         self.token[self.right] = t;
     }
-    pub fn pretty_print(&mut self, t: Token) -> io::IoResult<()> {
+    pub fn pretty_print(&mut self, token: Token) -> io::IoResult<()> {
         debug!("pp ~[{},{}]", self.left, self.right);
-        match t {
-          Eof => {
+        match token {
+          Token::Eof => {
             if !self.scan_stack_empty {
                 self.check_stack(0);
-                let left = self.token[self.left].clone();
-                let left_size = self.size[self.left];
-                try!(self.advance_left(left, left_size));
+                try!(self.advance_left());
             }
             self.indent(0);
             Ok(())
           }
-          Begin(b) => {
+          Token::Begin(b) => {
             if self.scan_stack_empty {
                 self.left_total = 1;
                 self.right_total = 1;
@@ -334,27 +331,27 @@ impl Printer {
             } else { self.advance_right(); }
             debug!("pp Begin({})/buffer ~[{},{}]",
                    b.offset, self.left, self.right);
-            self.token[self.right] = t;
+            self.token[self.right] = token;
             self.size[self.right] = -self.right_total;
             let right = self.right;
             self.scan_push(right);
             Ok(())
           }
-          End => {
+          Token::End => {
             if self.scan_stack_empty {
                 debug!("pp End/print ~[{},{}]", self.left, self.right);
-                self.print(t, 0)
+                self.print(token, 0)
             } else {
                 debug!("pp End/buffer ~[{},{}]", self.left, self.right);
                 self.advance_right();
-                self.token[self.right] = t;
+                self.token[self.right] = token;
                 self.size[self.right] = -1;
                 let right = self.right;
                 self.scan_push(right);
                 Ok(())
             }
           }
-          Break(b) => {
+          Token::Break(b) => {
             if self.scan_stack_empty {
                 self.left_total = 1;
                 self.right_total = 1;
@@ -366,21 +363,21 @@ impl Printer {
             self.check_stack(0);
             let right = self.right;
             self.scan_push(right);
-            self.token[self.right] = t;
+            self.token[self.right] = token;
             self.size[self.right] = -self.right_total;
             self.right_total += b.blank_space;
             Ok(())
           }
-          String(ref s, len) => {
+          Token::String(s, len) => {
             if self.scan_stack_empty {
                 debug!("pp String('{}')/print ~[{},{}]",
-                       *s, self.left, self.right);
-                self.print(t.clone(), len)
+                       s, self.left, self.right);
+                self.print(Token::String(s, len), len)
             } else {
                 debug!("pp String('{}')/buffer ~[{},{}]",
-                       *s, self.left, self.right);
+                       s, self.left, self.right);
                 self.advance_right();
-                self.token[self.right] = t.clone();
+                self.token[self.right] = Token::String(s, len);
                 self.size[self.right] = len;
                 self.right_total += len;
                 self.check_stream()
@@ -401,9 +398,7 @@ impl Printer {
                     self.size[scanned] = SIZE_INFINITY;
                 }
             }
-            let left = self.token[self.left].clone();
-            let left_size = self.size[self.left];
-            try!(self.advance_left(left, left_size));
+            try!(self.advance_left());
             if self.left != self.right {
                 try!(self.check_stream());
             }
@@ -450,42 +445,52 @@ impl Printer {
         self.right %= self.buf_len;
         assert!((self.right != self.left));
     }
-    pub fn advance_left(&mut self, x: Token, l: int) -> io::IoResult<()> {
+    pub fn advance_left(&mut self) -> io::IoResult<()> {
         debug!("advance_left ~[{},{}], sizeof({})={}", self.left, self.right,
-               self.left, l);
-        if l >= 0 {
-            let ret = self.print(x.clone(), l);
-            match x {
-              Break(b) => self.left_total += b.blank_space,
-              String(_, len) => {
-                assert_eq!(len, l); self.left_total += len;
-              }
-              _ => ()
-            }
-            if self.left != self.right {
-                self.left += 1u;
-                self.left %= self.buf_len;
-                let left = self.token[self.left].clone();
-                let left_size = self.size[self.left];
-                try!(self.advance_left(left, left_size));
+               self.left, self.size[self.left]);
+
+        let mut left_size = self.size[self.left];
+
+        while left_size >= 0 {
+            let left = self.token[self.left].clone();
+
+            let len = match left {
+                Token::Break(b) => b.blank_space,
+                Token::String(_, len) => {
+                    assert_eq!(len, left_size);
+                    len
+                }
+                _ => 0
+            };
+
+            try!(self.print(left, left_size));
+
+            self.left_total += len;
+
+            if self.left == self.right {
+                break;
             }
-            ret
-        } else {
-            Ok(())
+
+            self.left += 1u;
+            self.left %= self.buf_len;
+
+            left_size = self.size[self.left];
         }
+
+        Ok(())
     }
     pub fn check_stack(&mut self, k: int) {
         if !self.scan_stack_empty {
             let x = self.scan_top();
             match self.token[x] {
-                Begin(_) => {
+                Token::Begin(_) => {
                     if k > 0 {
                         let popped = self.scan_pop();
                         self.size[popped] = self.size[x] + self.right_total;
                         self.check_stack(k - 1);
                     }
                 }
-                End => {
+                Token::End => {
                     // paper says + not =, but that makes no sense.
                     let popped = self.scan_pop();
                     self.size[popped] = 1;
@@ -520,7 +525,7 @@ impl Printer {
         } else {
             PrintStackElem {
                 offset: 0,
-                pbreak: Broken(Inconsistent)
+                pbreak: PrintStackBreak::Broken(Breaks::Inconsistent)
             }
         }
     }
@@ -531,56 +536,56 @@ impl Printer {
         }
         write!(self.out, "{}", s)
     }
-    pub fn print(&mut self, x: Token, l: int) -> io::IoResult<()> {
-        debug!("print {} {} (remaining line space={})", tok_str(x.clone()), l,
+    pub fn print(&mut self, token: Token, l: int) -> io::IoResult<()> {
+        debug!("print {} {} (remaining line space={})", tok_str(&token), l,
                self.space);
-        debug!("{}", buf_str(self.token.clone(),
-                             self.size.clone(),
+        debug!("{}", buf_str(&self.token[],
+                             &self.size[],
                              self.left,
                              self.right,
                              6));
-        match x {
-          Begin(b) => {
+        match token {
+          Token::Begin(b) => {
             if l > self.space {
                 let col = self.margin - self.space + b.offset;
                 debug!("print Begin -> push broken block at col {}", col);
                 self.print_stack.push(PrintStackElem {
                     offset: col,
-                    pbreak: Broken(b.breaks)
+                    pbreak: PrintStackBreak::Broken(b.breaks)
                 });
             } else {
                 debug!("print Begin -> push fitting block");
                 self.print_stack.push(PrintStackElem {
                     offset: 0,
-                    pbreak: Fits
+                    pbreak: PrintStackBreak::Fits
                 });
             }
             Ok(())
           }
-          End => {
+          Token::End => {
             debug!("print End -> pop End");
             let print_stack = &mut self.print_stack;
             assert!((print_stack.len() != 0u));
             print_stack.pop().unwrap();
             Ok(())
           }
-          Break(b) => {
+          Token::Break(b) => {
             let top = self.get_top();
             match top.pbreak {
-              Fits => {
+              PrintStackBreak::Fits => {
                 debug!("print Break({}) in fitting block", b.blank_space);
                 self.space -= b.blank_space;
                 self.indent(b.blank_space);
                 Ok(())
               }
-              Broken(Consistent) => {
+              PrintStackBreak::Broken(Breaks::Consistent) => {
                 debug!("print Break({}+{}) in consistent block",
                        top.offset, b.offset);
                 let ret = self.print_newline(top.offset + b.offset);
                 self.space = self.margin - (top.offset + b.offset);
                 ret
               }
-              Broken(Inconsistent) => {
+              PrintStackBreak::Broken(Breaks::Inconsistent) => {
                 if l > self.space {
                     debug!("print Break({}+{}) w/ newline in inconsistent",
                            top.offset, b.offset);
@@ -597,14 +602,14 @@ impl Printer {
               }
             }
           }
-          String(s, len) => {
+          Token::String(s, len) => {
             debug!("print String({})", s);
             assert_eq!(l, len);
             // assert!(l <= space);
             self.space -= len;
             self.print_str(&s[])
           }
-          Eof => {
+          Token::Eof => {
             // Eof should never get here.
             panic!();
           }
@@ -616,41 +621,45 @@ impl Printer {
 //
 // "raw box"
 pub fn rbox(p: &mut Printer, indent: uint, b: Breaks) -> io::IoResult<()> {
-    p.pretty_print(Begin(BeginToken {
+    p.pretty_print(Token::Begin(BeginToken {
         offset: indent as int,
         breaks: b
     }))
 }
 
 pub fn ibox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
-    rbox(p, indent, Inconsistent)
+    rbox(p, indent, Breaks::Inconsistent)
 }
 
 pub fn cbox(p: &mut Printer, indent: uint) -> io::IoResult<()> {
-    rbox(p, indent, Consistent)
+    rbox(p, indent, Breaks::Consistent)
 }
 
 pub fn break_offset(p: &mut Printer, n: uint, off: int) -> io::IoResult<()> {
-    p.pretty_print(Break(BreakToken {
+    p.pretty_print(Token::Break(BreakToken {
         offset: off,
         blank_space: n as int
     }))
 }
 
-pub fn end(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(End) }
+pub fn end(p: &mut Printer) -> io::IoResult<()> {
+    p.pretty_print(Token::End)
+}
 
-pub fn eof(p: &mut Printer) -> io::IoResult<()> { p.pretty_print(Eof) }
+pub fn eof(p: &mut Printer) -> io::IoResult<()> {
+    p.pretty_print(Token::Eof)
+}
 
 pub fn word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
-    p.pretty_print(String(/* bad */ wrd.to_string(), wrd.len() as int))
+    p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as int))
 }
 
 pub fn huge_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
-    p.pretty_print(String(/* bad */ wrd.to_string(), SIZE_INFINITY))
+    p.pretty_print(Token::String(/* bad */ wrd.to_string(), SIZE_INFINITY))
 }
 
 pub fn zero_word(p: &mut Printer, wrd: &str) -> io::IoResult<()> {
-    p.pretty_print(String(/* bad */ wrd.to_string(), 0))
+    p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0))
 }
 
 pub fn spaces(p: &mut Printer, n: uint) -> io::IoResult<()> {
@@ -670,7 +679,9 @@ pub fn hardbreak(p: &mut Printer) -> io::IoResult<()> {
 }
 
 pub fn hardbreak_tok_offset(off: int) -> Token {
-    Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
+    Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
 }
 
-pub fn hardbreak_tok() -> Token { return hardbreak_tok_offset(0); }
+pub fn hardbreak_tok() -> Token {
+    hardbreak_tok_offset(0)
+}
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 9b6f8e6002d..5d76dc71006 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -25,7 +25,8 @@ use parse::token::{self, BinOpToken, Token};
 use parse::lexer::comments;
 use parse;
 use print::pp::{self, break_offset, word, space, zerobreak, hardbreak};
-use print::pp::{Breaks, Consistent, Inconsistent, eof};
+use print::pp::{Breaks, eof};
+use print::pp::Breaks::{Consistent, Inconsistent};
 use ptr::P;
 
 use std::{ascii, mem};
@@ -459,7 +460,7 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
 
 impl<'a> State<'a> {
     pub fn ibox(&mut self, u: uint) -> IoResult<()> {
-        self.boxes.push(pp::Inconsistent);
+        self.boxes.push(pp::Breaks::Inconsistent);
         pp::ibox(&mut self.s, u)
     }
 
@@ -469,7 +470,7 @@ impl<'a> State<'a> {
     }
 
     pub fn cbox(&mut self, u: uint) -> IoResult<()> {
-        self.boxes.push(pp::Consistent);
+        self.boxes.push(pp::Breaks::Consistent);
         pp::cbox(&mut self.s, u)
     }
 
@@ -531,11 +532,17 @@ impl<'a> State<'a> {
     }
 
     pub fn is_begin(&mut self) -> bool {
-        match self.s.last_token() { pp::Begin(_) => true, _ => false }
+        match self.s.last_token() {
+            pp::Token::Begin(_) => true,
+            _ => false,
+        }
     }
 
     pub fn is_end(&mut self) -> bool {
-        match self.s.last_token() { pp::End => true, _ => false }
+        match self.s.last_token() {
+            pp::Token::End => true,
+            _ => false,
+        }
     }
 
     // is this the beginning of a line?
@@ -545,7 +552,7 @@ impl<'a> State<'a> {
 
     pub fn in_cbox(&self) -> bool {
         match self.boxes.last() {
-            Some(&last_box) => last_box == pp::Consistent,
+            Some(&last_box) => last_box == pp::Breaks::Consistent,
             None => false
         }
     }
@@ -727,14 +734,7 @@ impl<'a> State<'a> {
                 try!(self.print_bounds("", &bounds[]));
             }
             ast::TyQPath(ref qpath) => {
-                try!(word(&mut self.s, "<"));
-                try!(self.print_type(&*qpath.self_type));
-                try!(space(&mut self.s));
-                try!(self.word_space("as"));
-                try!(self.print_trait_ref(&*qpath.trait_ref));
-                try!(word(&mut self.s, ">"));
-                try!(word(&mut self.s, "::"));
-                try!(self.print_ident(qpath.item_name));
+                try!(self.print_qpath(&**qpath, false))
             }
             ast::TyFixedLengthVec(ref ty, ref v) => {
                 try!(word(&mut self.s, "["));
@@ -1504,108 +1504,168 @@ impl<'a> State<'a> {
         Ok(())
     }
 
+    fn print_expr_box(&mut self,
+                      place: &Option<P<ast::Expr>>,
+                      expr: &ast::Expr) -> IoResult<()> {
+        try!(word(&mut self.s, "box"));
+        try!(word(&mut self.s, "("));
+        try!(place.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
+        try!(self.word_space(")"));
+        self.print_expr(expr)
+    }
+
+    fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) -> IoResult<()> {
+        try!(self.ibox(indent_unit));
+        try!(word(&mut self.s, "["));
+        try!(self.commasep_exprs(Inconsistent, &exprs[]));
+        try!(word(&mut self.s, "]"));
+        self.end()
+    }
+
+    fn print_expr_repeat(&mut self,
+                         element: &ast::Expr,
+                         count: &ast::Expr) -> IoResult<()> {
+        try!(self.ibox(indent_unit));
+        try!(word(&mut self.s, "["));
+        try!(self.print_expr(element));
+        try!(self.word_space(";"));
+        try!(self.print_expr(count));
+        try!(word(&mut self.s, "]"));
+        self.end()
+    }
+
+    fn print_expr_struct(&mut self,
+                         path: &ast::Path,
+                         fields: &[ast::Field],
+                         wth: &Option<P<ast::Expr>>) -> IoResult<()> {
+        try!(self.print_path(path, true));
+        if !(fields.is_empty() && wth.is_none()) {
+            try!(word(&mut self.s, "{"));
+            try!(self.commasep_cmnt(
+                Consistent,
+                &fields[],
+                |s, field| {
+                    try!(s.ibox(indent_unit));
+                    try!(s.print_ident(field.ident.node));
+                    try!(s.word_space(":"));
+                    try!(s.print_expr(&*field.expr));
+                    s.end()
+                },
+                |f| f.span));
+            match *wth {
+                Some(ref expr) => {
+                    try!(self.ibox(indent_unit));
+                    if !fields.is_empty() {
+                        try!(word(&mut self.s, ","));
+                        try!(space(&mut self.s));
+                    }
+                    try!(word(&mut self.s, ".."));
+                    try!(self.print_expr(&**expr));
+                    try!(self.end());
+                }
+                _ => try!(word(&mut self.s, ",")),
+            }
+            try!(word(&mut self.s, "}"));
+        }
+        Ok(())
+    }
+
+    fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) -> IoResult<()> {
+        try!(self.popen());
+        try!(self.commasep_exprs(Inconsistent, &exprs[]));
+        if exprs.len() == 1 {
+            try!(word(&mut self.s, ","));
+        }
+        self.pclose()
+    }
+
+    fn print_expr_call(&mut self,
+                       func: &ast::Expr,
+                       args: &[P<ast::Expr>]) -> IoResult<()> {
+        try!(self.print_expr_maybe_paren(func));
+        self.print_call_post(args)
+    }
+
+    fn print_expr_method_call(&mut self,
+                              ident: ast::SpannedIdent,
+                              tys: &[P<ast::Ty>],
+                              args: &[P<ast::Expr>]) -> IoResult<()> {
+        let base_args = args.slice_from(1);
+        try!(self.print_expr(&*args[0]));
+        try!(word(&mut self.s, "."));
+        try!(self.print_ident(ident.node));
+        if tys.len() > 0u {
+            try!(word(&mut self.s, "::<"));
+            try!(self.commasep(Inconsistent, tys,
+                               |s, ty| s.print_type(&**ty)));
+            try!(word(&mut self.s, ">"));
+        }
+        self.print_call_post(base_args)
+    }
+
+    fn print_expr_binary(&mut self,
+                         op: ast::BinOp,
+                         lhs: &ast::Expr,
+                         rhs: &ast::Expr) -> IoResult<()> {
+        try!(self.print_expr(lhs));
+        try!(space(&mut self.s));
+        try!(self.word_space(ast_util::binop_to_string(op)));
+        self.print_expr(rhs)
+    }
+
+    fn print_expr_unary(&mut self,
+                        op: ast::UnOp,
+                        expr: &ast::Expr) -> IoResult<()> {
+        try!(word(&mut self.s, ast_util::unop_to_string(op)));
+        self.print_expr_maybe_paren(expr)
+    }
+
+    fn print_expr_addr_of(&mut self,
+                          mutability: ast::Mutability,
+                          expr: &ast::Expr) -> IoResult<()> {
+        try!(word(&mut self.s, "&"));
+        try!(self.print_mutability(mutability));
+        self.print_expr_maybe_paren(expr)
+    }
+
     pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
         try!(self.maybe_print_comment(expr.span.lo));
         try!(self.ibox(indent_unit));
         try!(self.ann.pre(self, NodeExpr(expr)));
         match expr.node {
-            ast::ExprBox(ref p, ref e) => {
-                try!(word(&mut self.s, "box"));
-                try!(word(&mut self.s, "("));
-                try!(p.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
-                try!(self.word_space(")"));
-                try!(self.print_expr(&**e));
+            ast::ExprBox(ref place, ref expr) => {
+                try!(self.print_expr_box(place, &**expr));
             }
             ast::ExprVec(ref exprs) => {
-                try!(self.ibox(indent_unit));
-                try!(word(&mut self.s, "["));
-                try!(self.commasep_exprs(Inconsistent, &exprs[]));
-                try!(word(&mut self.s, "]"));
-                try!(self.end());
+                try!(self.print_expr_vec(&exprs[]));
             }
-
             ast::ExprRepeat(ref element, ref count) => {
-                try!(self.ibox(indent_unit));
-                try!(word(&mut self.s, "["));
-                try!(self.print_expr(&**element));
-                try!(self.word_space(";"));
-                try!(self.print_expr(&**count));
-                try!(word(&mut self.s, "]"));
-                try!(self.end());
+                try!(self.print_expr_repeat(&**element, &**count));
             }
-
             ast::ExprStruct(ref path, ref fields, ref wth) => {
-                try!(self.print_path(path, true));
-                if !(fields.is_empty() && wth.is_none()) {
-                    try!(word(&mut self.s, "{"));
-                    try!(self.commasep_cmnt(
-                        Consistent,
-                        &fields[],
-                        |s, field| {
-                            try!(s.ibox(indent_unit));
-                            try!(s.print_ident(field.ident.node));
-                            try!(s.word_space(":"));
-                            try!(s.print_expr(&*field.expr));
-                            s.end()
-                        },
-                        |f| f.span));
-                    match *wth {
-                        Some(ref expr) => {
-                            try!(self.ibox(indent_unit));
-                            if !fields.is_empty() {
-                                try!(word(&mut self.s, ","));
-                                try!(space(&mut self.s));
-                            }
-                            try!(word(&mut self.s, ".."));
-                            try!(self.print_expr(&**expr));
-                            try!(self.end());
-                        }
-                        _ => try!(word(&mut self.s, ",")),
-                    }
-                    try!(word(&mut self.s, "}"));
-                }
+                try!(self.print_expr_struct(path, &fields[], wth));
             }
             ast::ExprTup(ref exprs) => {
-                try!(self.popen());
-                try!(self.commasep_exprs(Inconsistent, &exprs[]));
-                if exprs.len() == 1 {
-                    try!(word(&mut self.s, ","));
-                }
-                try!(self.pclose());
+                try!(self.print_expr_tup(&exprs[]));
             }
             ast::ExprCall(ref func, ref args) => {
-                try!(self.print_expr_maybe_paren(&**func));
-                try!(self.print_call_post(&args[]));
+                try!(self.print_expr_call(&**func, &args[]));
             }
             ast::ExprMethodCall(ident, ref tys, ref args) => {
-                let base_args = args.slice_from(1);
-                try!(self.print_expr(&*args[0]));
-                try!(word(&mut self.s, "."));
-                try!(self.print_ident(ident.node));
-                if tys.len() > 0u {
-                    try!(word(&mut self.s, "::<"));
-                    try!(self.commasep(Inconsistent, &tys[],
-                                       |s, ty| s.print_type(&**ty)));
-                    try!(word(&mut self.s, ">"));
-                }
-                try!(self.print_call_post(base_args));
+                try!(self.print_expr_method_call(ident, &tys[], &args[]));
             }
             ast::ExprBinary(op, ref lhs, ref rhs) => {
-                try!(self.print_expr(&**lhs));
-                try!(space(&mut self.s));
-                try!(self.word_space(ast_util::binop_to_string(op)));
-                try!(self.print_expr(&**rhs));
+                try!(self.print_expr_binary(op, &**lhs, &**rhs));
             }
             ast::ExprUnary(op, ref expr) => {
-                try!(word(&mut self.s, ast_util::unop_to_string(op)));
-                try!(self.print_expr_maybe_paren(&**expr));
+                try!(self.print_expr_unary(op, &**expr));
             }
             ast::ExprAddrOf(m, ref expr) => {
-                try!(word(&mut self.s, "&"));
-                try!(self.print_mutability(m));
-                try!(self.print_expr_maybe_paren(&**expr));
+                try!(self.print_expr_addr_of(m, &**expr));
+            }
+            ast::ExprLit(ref lit) => {
+                try!(self.print_literal(&**lit));
             }
-            ast::ExprLit(ref lit) => try!(self.print_literal(&**lit)),
             ast::ExprCast(ref expr, ref ty) => {
                 try!(self.print_expr(&**expr));
                 try!(space(&mut self.s));
@@ -1749,6 +1809,7 @@ impl<'a> State<'a> {
                 }
             }
             ast::ExprPath(ref path) => try!(self.print_path(path, true)),
+            ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)),
             ast::ExprBreak(opt_ident) => {
                 try!(word(&mut self.s, "break"));
                 try!(space(&mut self.s));
@@ -1933,6 +1994,22 @@ impl<'a> State<'a> {
         Ok(())
     }
 
+    fn print_qpath(&mut self,
+                   qpath: &ast::QPath,
+                   colons_before_params: bool)
+                   -> IoResult<()>
+    {
+        try!(word(&mut self.s, "<"));
+        try!(self.print_type(&*qpath.self_type));
+        try!(space(&mut self.s));
+        try!(self.word_space("as"));
+        try!(self.print_trait_ref(&*qpath.trait_ref));
+        try!(word(&mut self.s, ">"));
+        try!(word(&mut self.s, "::"));
+        try!(self.print_ident(qpath.item_path.identifier));
+        self.print_path_parameters(&qpath.item_path.parameters, colons_before_params)
+    }
+
     fn print_path_parameters(&mut self,
                              parameters: &ast::PathParameters,
                              colons_before_params: bool)
@@ -2881,7 +2958,7 @@ impl<'a> State<'a> {
             comments::BlankLine => {
                 // We need to do at least one, possibly two hardbreaks.
                 let is_semi = match self.s.last_token() {
-                    pp::String(s, _) => ";" == s,
+                    pp::Token::String(s, _) => ";" == s,
                     _ => false
                 };
                 if is_semi || self.is_begin() || self.is_end() {
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index 13a14d069d7..37fa8703706 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -38,7 +38,6 @@
 
 use std::fmt::{self, Show};
 use std::hash::{Hash, Hasher};
-#[cfg(stage0)] use std::hash::Writer;
 use std::ops::Deref;
 use std::ptr;
 
@@ -107,13 +106,6 @@ impl<T: Show> Show for P<T> {
     }
 }
 
-#[cfg(stage0)]
-impl<S: Writer, T: Hash<S>> Hash<S> for P<T> {
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 impl<S: Hasher, T: Hash<S>> Hash<S> for P<T> {
     fn hash(&self, state: &mut S) {
         (**self).hash(state);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 3f91304dcc5..7778b4fa34a 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -126,6 +126,9 @@ pub trait Visitor<'v> : Sized {
     fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
         walk_path(self, path)
     }
+    fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) {
+        walk_qpath(self, qpath_span, qpath)
+    }
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         walk_path_segment(self, path_span, path_segment)
     }
@@ -419,9 +422,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_ty_param_bounds_helper(visitor, bounds);
         }
         TyQPath(ref qpath) => {
-            visitor.visit_ty(&*qpath.self_type);
-            visitor.visit_trait_ref(&*qpath.trait_ref);
-            visitor.visit_ident(typ.span, qpath.item_name);
+            visitor.visit_qpath(typ.span, &**qpath);
         }
         TyFixedLengthVec(ref ty, ref expression) => {
             visitor.visit_ty(&**ty);
@@ -450,6 +451,14 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     }
 }
 
+pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V,
+                                      qpath_span: Span,
+                                      qpath: &'v QPath) {
+    visitor.visit_ty(&*qpath.self_type);
+    visitor.visit_trait_ref(&*qpath.trait_ref);
+    visitor.visit_path_segment(qpath_span, &qpath.item_path);
+}
+
 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
@@ -881,6 +890,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprPath(ref path) => {
             visitor.visit_path(path, expression.id)
         }
+        ExprQPath(ref qpath) => {
+            visitor.visit_qpath(expression.span, &**qpath)
+        }
         ExprBreak(_) | ExprAgain(_) => {}
         ExprRet(ref optional_expression) => {
             walk_expr_opt(visitor, optional_expression)
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index 2117b68c08e..027c5a1a708 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -52,6 +52,7 @@
 #![feature(slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 #![deny(missing_docs)]
 
 #[macro_use] extern crate log;
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index c4cb53d6cb7..b9e37156dc7 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -35,6 +35,7 @@
 #![feature(asm, slicing_syntax)]
 #![feature(box_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate getopts;
 extern crate regex;
@@ -211,6 +212,8 @@ pub struct TestDesc {
     pub should_fail: ShouldFail,
 }
 
+unsafe impl Send for TestDesc {}
+
 #[derive(Show)]
 pub struct TestDescAndFn {
     pub desc: TestDesc,
@@ -525,6 +528,8 @@ pub enum TestResult {
     TrBench(BenchSamples),
 }
 
+unsafe impl Send for TestResult {}
+
 enum OutputLocation<T> {
     Pretty(Box<term::Terminal<term::WriterWrapper> + Send>),
     Raw(T),
@@ -978,7 +983,6 @@ enum TestEvent {
 
 pub type MonitorMsg = (TestDesc, TestResult, Vec<u8> );
 
-unsafe impl Send for MonitorMsg {}
 
 fn run_tests<F>(opts: &TestOpts,
                 tests: Vec<TestDescAndFn> ,
@@ -1332,10 +1336,11 @@ impl MetricMap {
 /// elimination.
 ///
 /// This function is a no-op, and does not even read from `dummy`.
-pub fn black_box<T>(dummy: T) {
+pub fn black_box<T>(dummy: T) -> T {
     // we need to "use" the argument in some way LLVM can't
     // introspect.
     unsafe {asm!("" : : "r"(&dummy))}
+    dummy
 }
 
 
diff --git a/src/libunicode/lib.rs b/src/libunicode/lib.rs
index 17607383bee..fbe912ced90 100644
--- a/src/libunicode/lib.rs
+++ b/src/libunicode/lib.rs
@@ -31,6 +31,7 @@
 #![no_std]
 #![feature(slicing_syntax)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![allow(unstable)]
 
 extern crate core;
 
diff --git a/src/rt/arch/aarch64/morestack.S b/src/rt/arch/aarch64/morestack.S
index 772b8467014..c5e412140e4 100644
--- a/src/rt/arch/aarch64/morestack.S
+++ b/src/rt/arch/aarch64/morestack.S
@@ -9,7 +9,7 @@
 
 #if defined(__APPLE__)
 #define MORESTACK ___morestack
-#define STACK_EXHAUSTED _rust_stack_exhausted
+#define STACK_EXHAUSTED _rust_stack_exhausted@plt
 #else
 #define MORESTACK __morestack
 #define STACK_EXHAUSTED rust_stack_exhausted
@@ -30,6 +30,6 @@
 // FIXME(AARCH64): this might not be perfectly right but works for now
 MORESTACK:
 	.cfi_startproc
-	bl STACK_EXHAUSTED@plt
+	bl STACK_EXHAUSTED
 	// the above function ensures that it never returns
 	.cfi_endproc
diff --git a/src/rt/arch/powerpc/morestack.S b/src/rt/arch/powerpc/morestack.S
new file mode 100644
index 00000000000..2502ac1eb48
--- /dev/null
+++ b/src/rt/arch/powerpc/morestack.S
@@ -0,0 +1,18 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section       .note.GNU-stack, "", %progbits
+#endif
+
+/* See i386/morestack.S for the lengthy, general explanation. */
+
+.global rust_stack_exhausted
+
+.hidden __morestack
+
+// FIXME(POWERPC): this might not be perfectly right but works for now
+__morestack:
+       .cfi_startproc
+       bl rust_stack_exhausted
+       // the above function ensures that it never returns
+       .cfi_endproc
+.end  __morestack
diff --git a/src/rt/arch/powerpc/record_sp.S b/src/rt/arch/powerpc/record_sp.S
new file mode 100644
index 00000000000..e93a69a711b
--- /dev/null
+++ b/src/rt/arch/powerpc/record_sp.S
@@ -0,0 +1,4 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section       .note.GNU-stack, "", %progbits
+#endif
diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs
index 44b1630d9fb..50a6ad43aee 100644
--- a/src/rustbook/build.rs
+++ b/src/rustbook/build.rs
@@ -20,6 +20,7 @@ use error::{Error, CliResult, CommandResult};
 use book;
 use book::{Book, BookItem};
 use css;
+use javascript;
 
 use regex::Regex;
 
@@ -63,7 +64,7 @@ fn write_toc(book: &Book, path_to_root: &Path, out: &mut Writer) -> IoResult<()>
         Ok(())
     }
 
-    try!(writeln!(out, "<div id='toc'>"));
+    try!(writeln!(out, "<div id='toc' class='mobile-hidden'>"));
     try!(writeln!(out, "<ul class='chapter'>"));
     try!(walk_items(&book.chapters[], "", path_to_root, out));
     try!(writeln!(out, "</ul>"));
@@ -102,6 +103,14 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
         let prelude = tmp.path().join("prelude.html");
         {
             let mut toc = BufferedWriter::new(try!(File::create(&prelude)));
+            try!(writeln!(&mut toc, r#"<div id="nav">
+                <button id="toggle-nav">
+                  <span class="sr-only">Toggle navigation</span>
+                  <span class="bar"></span>
+                  <span class="bar"></span>
+                  <span class="bar"></span>
+                </button>
+              </div>"#));
             let _ = write_toc(book, &item.path_to_root, &mut toc);
             try!(writeln!(&mut toc, "<div id='page-wrapper'>"));
             try!(writeln!(&mut toc, "<div id='page'>"));
@@ -111,6 +120,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
         let postlude = tmp.path().join("postlude.html");
         {
             let mut toc = BufferedWriter::new(try!(File::create(&postlude)));
+            try!(toc.write_str(javascript::JAVASCRIPT));
             try!(writeln!(&mut toc, "</div></div>"));
         }
 
diff --git a/src/rustbook/css.rs b/src/rustbook/css.rs
index 92433589155..65ba031a2d6 100644
--- a/src/rustbook/css.rs
+++ b/src/rustbook/css.rs
@@ -45,7 +45,7 @@ body {
 #page {
     margin-left: auto;
     margin-right:auto;
-    width: 750px;
+    max-width: 750px;
 }
 
 .chapter {
@@ -69,4 +69,58 @@ body {
 .chapter li a {
     color: #000000;
 }
+
+@media only screen and (max-width: 1060px) {
+    #toc {
+        width: 100%;
+        margin-right: 0;
+        top: 40px;
+    }
+    #page-wrapper {
+        top: 40px;
+        left: 15px;
+        padding-right: 15px;
+    }
+    .mobile-hidden {
+        display: none;
+    }
+}
+
+
+#toggle-nav {
+    height: 20px;
+    width:  30px;
+    padding: 3px 3px 0 3px;
+}
+
+#toggle-nav {
+    margin-top: 5px;
+    width: 30px;
+    height: 30px;
+    background-color: #FFF;
+    border: 1px solid #666;
+    border-radius: 3px 3px 3px 3px;
+}
+
+.sr-only {
+    position: absolute;
+    width: 1px;
+    height: 1px;
+    margin: -1px;
+    padding: 0;
+    overflow: hidden;
+    clip: rect(0, 0, 0, 0);
+    border: 0;
+}
+
+.bar {
+    display: block;
+    background-color: #000;
+    border-radius: 2px;
+    width: 100%;
+    height: 2px;
+    margin: 2px 0 3px;
+    padding: 0;
+}
+
 "#;
diff --git a/src/rustbook/javascript.rs b/src/rustbook/javascript.rs
new file mode 100644
index 00000000000..eb4401e1835
--- /dev/null
+++ b/src/rustbook/javascript.rs
@@ -0,0 +1,43 @@
+// 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.
+
+// The rust-book JavaScript in string form.
+
+pub static JAVASCRIPT: &'static str = r#"
+<script type="text/javascript">
+document.addEventListener("DOMContentLoaded", function(event) {
+  document.getElementById("toggle-nav").onclick = toggleNav;
+  function toggleNav() {
+    var toc = document.getElementById("toc");
+    var pagewrapper = document.getElementById("page-wrapper");
+    toggleClass(toc, "mobile-hidden");
+    toggleClass(pagewrapper, "mobile-hidden");
+  };
+
+  function toggleClass(el, className) {
+     // from http://youmightnotneedjquery.com/
+     if (el.classList) {
+       el.classList.toggle(className);
+     } else {
+       var classes = el.className.split(' ');
+       var existingIndex = classes.indexOf(className);
+
+       if (existingIndex >= 0) {
+         classes.splice(existingIndex, 1);
+       } else {
+         classes.push(className);
+       }
+
+       el.className = classes.join(' ');
+     }
+  }
+});
+</script>
+"#;
diff --git a/src/rustbook/main.rs b/src/rustbook/main.rs
index 48dad14321a..ea72c653087 100644
--- a/src/rustbook/main.rs
+++ b/src/rustbook/main.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(slicing_syntax, box_syntax)]
+#![allow(unstable)]
 
 extern crate regex;
 
@@ -39,6 +40,7 @@ mod serve;
 mod test;
 
 mod css;
+mod javascript;
 
 #[cfg(not(test))] // thanks #12327
 fn main() {
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index 2ac855681f2..4a16b9c257c 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-05
+2015-01-13
diff --git a/src/snapshots.txt b/src/snapshots.txt
index aa31974c67a..16fb109bb7d 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,12 @@
+S 2015-01-15 9ade482
+  freebsd-x86_64 eb8f52c6e8dc24a293456d5e4dc5d1072442e758
+  linux-i386 0197ad7179d74eba06a8b46432548caf226aa03d
+  linux-x86_64 03459f8b216e96ed8b9abe25a42a75859195103d
+  macos-i386 b5c004883ddff84159f11a3329cde682e0b7f75b
+  macos-x86_64 b69ea42e1c995682adf0390ed4ef8a762c001a4e
+  winnt-i386 7fa6e35d26bbffa3888d440a0d5f116414ef8c0a
+  winnt-x86_64 ac04a4f1f26e0219d91e7eae6f580ca3cfee4231
+
 S 2015-01-07 9e4e524
   freebsd-x86_64 2563d33151bce1bbe08a85d712564bddc7503fc6
   linux-i386 d8b73fc9aa3ad72ce1408a41e35d78dba10eb4d4
diff --git a/src/test/auxiliary/issue-17718.rs b/src/test/auxiliary/issue-17718.rs
index 689610d799e..cbe56b00c13 100644
--- a/src/test/auxiliary/issue-17718.rs
+++ b/src/test/auxiliary/issue-17718.rs
@@ -11,12 +11,12 @@
 use std::sync::atomic;
 
 pub const C1: uint = 1;
-pub const C2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+pub const C2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
 pub const C3: fn() = foo;
 pub const C4: uint = C1 * C1 + C1 / C1;
 pub const C5: &'static uint = &C4;
 
 pub static S1: uint = 3;
-pub static S2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+pub static S2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
 
 fn foo() {}
diff --git a/src/test/compile-fail/obsolete-tuple-struct-deref.rs b/src/test/auxiliary/issue-21202.rs
index ad5fac3e21e..afdbf78aa82 100644
--- a/src/test/compile-fail/obsolete-tuple-struct-deref.rs
+++ b/src/test/auxiliary/issue-21202.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() {
-    struct S(isize);
-    let s = S(0);
-    let x = *s; //~ ERROR single-field tuple-structs can no longer be dereferenced
+pub mod A {
+    pub struct Foo;
+    impl Foo {
+        fn foo(&self) { }
+    }
 }
diff --git a/src/test/auxiliary/macro_crate_test.rs b/src/test/auxiliary/macro_crate_test.rs
index 9eeb7ee8857..e3e91e05f55 100644
--- a/src/test/auxiliary/macro_crate_test.rs
+++ b/src/test/auxiliary/macro_crate_test.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -16,7 +16,7 @@
 extern crate syntax;
 extern crate rustc;
 
-use syntax::ast::{TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem, ImplItem, TraitItem, Method};
 use syntax::codemap::Span;
 use syntax::ext::base::*;
 use syntax::parse::token;
@@ -37,6 +37,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_syntax_extension(
         token::intern("into_foo"),
         Modifier(box expand_into_foo));
+    reg.register_syntax_extension(
+        token::intern("into_multi_foo"),
+        MultiModifier(box expand_into_foo_multi));
 }
 
 fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
@@ -65,6 +68,30 @@ fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: &MetaItem, it: P<Item>)
     })
 }
 
+fn expand_into_foo_multi(cx: &mut ExtCtxt,
+                         sp: Span,
+                         attr: &MetaItem,
+                         it: Annotatable) -> Annotatable {
+    match it {
+        Annotatable::Item(it) => {
+            Annotatable::Item(P(Item {
+                attrs: it.attrs.clone(),
+                ..(*quote_item!(cx, enum Foo2 { Bar2, Baz2 }).unwrap()).clone()
+            }))
+        }
+        Annotatable::ImplItem(it) => {
+            Annotatable::ImplItem(ImplItem::MethodImplItem(
+                quote_method!(cx, fn foo(&self) -> i32 { 42 })
+            ))
+        }
+        Annotatable::TraitItem(it) => {
+            Annotatable::TraitItem(TraitItem::ProvidedMethod(
+                quote_method!(cx, fn foo(&self) -> i32 { 0 })
+            ))
+        }
+    }
+}
+
 fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult+'static> {
     use syntax::ext::quote::rt::*;
 
diff --git a/src/test/auxiliary/no_method_suggested_traits.rs b/src/test/auxiliary/no_method_suggested_traits.rs
new file mode 100644
index 00000000000..328561495ee
--- /dev/null
+++ b/src/test/auxiliary/no_method_suggested_traits.rs
@@ -0,0 +1,43 @@
+// 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.
+
+pub use reexport::Reexported;
+
+pub mod foo {
+    pub trait PubPub {
+        fn method(&self) {}
+
+        fn method3(&self) {}
+    }
+
+    impl PubPub for u32 {}
+    impl PubPub for i32 {}
+}
+pub mod bar {
+    trait PubPriv {
+        fn method(&self);
+    }
+}
+mod qux {
+    pub trait PrivPub {
+        fn method(&self);
+    }
+}
+mod quz {
+    trait PrivPriv {
+        fn method(&self);
+    }
+}
+
+mod reexport {
+    pub trait Reexported {
+        fn method(&self);
+    }
+}
diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs
index fad5e174644..58e2430b0ff 100644
--- a/src/test/bench/shootout-binarytrees.rs
+++ b/src/test/bench/shootout-binarytrees.rs
@@ -44,26 +44,30 @@ use std::iter::range_step;
 use std::thread::Thread;
 use arena::TypedArena;
 
-enum Tree<'a> {
-    Nil,
-    Node(&'a Tree<'a>, &'a Tree<'a>, int)
+struct Tree<'a> {
+    l: Option<&'a Tree<'a>>,
+    r: Option<&'a Tree<'a>>,
+    i: i32
 }
 
-fn item_check(t: &Tree) -> int {
+fn item_check(t: &Option<&Tree>) -> i32 {
     match *t {
-        Tree::Nil => 0,
-        Tree::Node(l, r, i) => i + item_check(l) - item_check(r)
+        None => 0,
+        Some(&Tree { ref l, ref r, i }) => i + item_check(l) - item_check(r)
     }
 }
 
-fn bottom_up_tree<'r>(arena: &'r TypedArena<Tree<'r>>, item: int, depth: int)
-                  -> &'r Tree<'r> {
+fn bottom_up_tree<'r>(arena: &'r TypedArena<Tree<'r>>, item: i32, depth: i32)
+                  -> Option<&'r Tree<'r>> {
     if depth > 0 {
-        arena.alloc(Tree::Node(bottom_up_tree(arena, 2 * item - 1, depth - 1),
-                               bottom_up_tree(arena, 2 * item, depth - 1),
-                               item))
+        let t: &Tree<'r> = arena.alloc(Tree {
+            l: bottom_up_tree(arena, 2 * item - 1, depth - 1),
+            r: bottom_up_tree(arena, 2 * item, depth - 1),
+            i: item
+        });
+        Some(t)
     } else {
-        arena.alloc(Tree::Nil)
+        None
     }
 }
 
@@ -86,7 +90,7 @@ fn main() {
         let tree = bottom_up_tree(&arena, 0, depth);
 
         println!("stretch tree of depth {}\t check: {}",
-                 depth, item_check(tree));
+                 depth, item_check(&tree));
     }
 
     let long_lived_arena = TypedArena::new();
@@ -94,14 +98,14 @@ fn main() {
 
     let messages = range_step(min_depth, max_depth + 1, 2).map(|depth| {
             use std::num::Int;
-            let iterations = 2i.pow((max_depth - depth + min_depth) as uint);
+            let iterations = 2.pow((max_depth - depth + min_depth) as usize);
             Thread::scoped(move|| {
                 let mut chk = 0;
-                for i in range(1, iterations + 1) {
+                for i in 1 .. iterations + 1 {
                     let arena = TypedArena::new();
                     let a = bottom_up_tree(&arena, i, depth);
                     let b = bottom_up_tree(&arena, -i, depth);
-                    chk += item_check(a) + item_check(b);
+                    chk += item_check(&a) + item_check(&b);
                 }
                 format!("{}\t trees of depth {}\t check: {}",
                         iterations * 2, depth, chk)
@@ -113,5 +117,5 @@ fn main() {
     }
 
     println!("long lived tree of depth {}\t check: {}",
-             max_depth, item_check(long_lived_tree));
+             max_depth, item_check(&long_lived_tree));
 }
diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs
index 5a47f9fbc57..9e5618579e4 100644
--- a/src/test/bench/shootout-fasta-redux.rs
+++ b/src/test/bench/shootout-fasta-redux.rs
@@ -128,7 +128,7 @@ impl<'a, W: Writer> RepeatFasta<'a, W> {
         copy_memory(buf.as_mut_slice(), alu);
         let buf_len = buf.len();
         copy_memory(buf.slice_mut(alu_len, buf_len),
-                    &alu[0..LINE_LEN]);
+                    &alu[..LINE_LEN]);
 
         let mut pos = 0;
         let mut bytes;
@@ -204,7 +204,7 @@ impl<'a, W: Writer> RandomFasta<'a, W> {
         for i in range(0u, chars_left) {
             buf[i] = self.nextc();
         }
-        self.out.write(&buf[0..chars_left])
+        self.out.write(&buf[..chars_left])
     }
 }
 
diff --git a/src/test/bench/shootout-threadring.rs b/src/test/bench/shootout-threadring.rs
index ea4b3c46312..47f17997e84 100644
--- a/src/test/bench/shootout-threadring.rs
+++ b/src/test/bench/shootout-threadring.rs
@@ -41,18 +41,19 @@
 use std::sync::mpsc::{channel, Sender, Receiver};
 use std::thread::Thread;
 
-fn start(n_tasks: int, token: int) {
+fn start(n_tasks: i32, token: i32) {
     let (tx, mut rx) = channel();
     tx.send(token).unwrap();
-    for i in range(2, n_tasks + 1) {
+    let mut guards = Vec::with_capacity(n_tasks as usize);
+    for i in 2 .. n_tasks + 1 {
         let (tx, next_rx) = channel();
-        Thread::spawn(move|| roundtrip(i, tx, rx));
-        rx = next_rx;
+        let cur_rx = std::mem::replace(&mut rx, next_rx);
+        guards.push(Thread::scoped(move|| roundtrip(i, tx, cur_rx)));
     }
-    Thread::spawn(move|| roundtrip(1, tx, rx));
+    let guard = Thread::scoped(move|| roundtrip(1, tx, rx));
 }
 
-fn roundtrip(id: int, tx: Sender<int>, rx: Receiver<int>) {
+fn roundtrip(id: i32, tx: Sender<i32>, rx: Receiver<i32>) {
     for token in rx.iter() {
         if token == 1 {
             println!("{}", id);
@@ -64,7 +65,6 @@ fn roundtrip(id: int, tx: Sender<int>, rx: Receiver<int>) {
 
 fn main() {
     let args = std::os::args();
-    let args = args.as_slice();
     let token = if std::os::getenv("RUST_BENCH").is_some() {
         2000000
     } else {
diff --git a/src/test/compile-fail/array-not-vector.rs b/src/test/compile-fail/array-not-vector.rs
index 6581019fdd5..2415288a3eb 100644
--- a/src/test/compile-fail/array-not-vector.rs
+++ b/src/test/compile-fail/array-not-vector.rs
@@ -9,8 +9,18 @@
 // except according to those terms.
 
 fn main() {
-    let _x: isize = [1is, 2, 3]; //~ ERROR expected isize, found array of 3 elements
+    let _x: isize = [1is, 2, 3];
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `[isize; 3]`
+    //~| expected isize
+    //~| found array of 3 elements
 
     let x: &[isize] = &[1, 2, 3];
-    let _y: &isize = x; //~ ERROR expected isize, found slice
+    let _y: &isize = x;
+    //~^ ERROR mismatched types
+    //~| expected `&isize`
+    //~| found `&[isize]`
+    //~| expected isize
+    //~| found slice
 }
diff --git a/src/test/compile-fail/associated-types-eq-3.rs b/src/test/compile-fail/associated-types-eq-3.rs
index ed81c0fccbc..fdfff559086 100644
--- a/src/test/compile-fail/associated-types-eq-3.rs
+++ b/src/test/compile-fail/associated-types-eq-3.rs
@@ -30,7 +30,12 @@ fn foo1<I: Foo<A=Bar>>(x: I) {
 }
 
 fn foo2<I: Foo>(x: I) {
-    let _: Bar = x.boo(); //~ERROR mismatched types
+    let _: Bar = x.boo();
+    //~^ ERROR mismatched types
+    //~| expected `Bar`
+    //~| found `<I as Foo>::A`
+    //~| expected struct `Bar`
+    //~| found associated type
 }
 
 
@@ -41,6 +46,12 @@ pub fn baz(x: &Foo<A=Bar>) {
 
 pub fn main() {
     let a = 42is;
-    foo1(a); //~ERROR expected usize, found struct Bar
-    baz(&a); //~ERROR expected usize, found struct Bar
+    foo1(a);
+    //~^ ERROR type mismatch resolving
+    //~| expected usize
+    //~| found struct `Bar`
+    baz(&a);
+    //~^ ERROR type mismatch resolving
+    //~| expected usize
+    //~| found struct `Bar`
 }
diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs
index 74c8dffced5..5cb9aca8beb 100644
--- a/src/test/compile-fail/associated-types-path-2.rs
+++ b/src/test/compile-fail/associated-types-path-2.rs
@@ -25,7 +25,9 @@ pub fn f2<T: Foo>(a: T) -> T::A {
 
 pub fn f1_int_int() {
     f1(2is, 4is);
-    //~^ ERROR expected usize, found isize
+    //~^ ERROR type mismatch resolving
+    //~| expected usize
+    //~| found isize
 }
 
 pub fn f1_int_uint() {
@@ -46,7 +48,11 @@ pub fn f1_uint_int() {
 
 pub fn f2_int() {
     let _: isize = f2(2is);
-    //~^ ERROR expected `isize`, found `usize`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `usize`
+    //~| expected isize
+    //~| found usize
 }
 
 pub fn main() { }
diff --git a/src/test/compile-fail/bad-const-type.rs b/src/test/compile-fail/bad-const-type.rs
index 2450f22669a..ed62506420a 100644
--- a/src/test/compile-fail/bad-const-type.rs
+++ b/src/test/compile-fail/bad-const-type.rs
@@ -8,7 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:expected `collections::string::String`, found `isize`
-
 static i: String = 10is;
+//~^ ERROR mismatched types
+//~| expected `collections::string::String`
+//~| found `isize`
+//~| expected struct `collections::string::String`
+//~| found isize
 fn main() { println!("{}", i); }
diff --git a/src/test/compile-fail/block-must-not-have-result-do.rs b/src/test/compile-fail/block-must-not-have-result-do.rs
index 687171f8c1f..30039a1c54c 100644
--- a/src/test/compile-fail/block-must-not-have-result-do.rs
+++ b/src/test/compile-fail/block-must-not-have-result-do.rs
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `()`, found `bool`
-
 fn main() {
     loop {
-        true
+        true //~  ERROR mismatched types
+             //~| expected ()
+             //~| found bool
+             //~| expected ()
+             //~| found bool
     }
 }
diff --git a/src/test/compile-fail/block-must-not-have-result-res.rs b/src/test/compile-fail/block-must-not-have-result-res.rs
index 328c032325e..6161660ddf7 100644
--- a/src/test/compile-fail/block-must-not-have-result-res.rs
+++ b/src/test/compile-fail/block-must-not-have-result-res.rs
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `()`, found `bool`
-
 struct r;
 
 impl Drop for r {
     fn drop(&mut self) {
-        true
+        true //~  ERROR mismatched types
+             //~| expected ()
+             //~| found bool
+             //~| expected ()
+             //~| found bool
     }
 }
 
diff --git a/src/test/compile-fail/block-must-not-have-result-while.rs b/src/test/compile-fail/block-must-not-have-result-while.rs
index ed903f3fd65..ba6340ed395 100644
--- a/src/test/compile-fail/block-must-not-have-result-while.rs
+++ b/src/test/compile-fail/block-must-not-have-result-while.rs
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `()`, found `bool`
-
 fn main() {
     while true {
-        true
+        true //~  ERROR mismatched types
+             //~| expected `()`
+             //~| found `bool`
+             //~| expected ()
+             //~| found bool
     }
 }
diff --git a/src/test/compile-fail/coercion-slice.rs b/src/test/compile-fail/coercion-slice.rs
index 8d48ede0e15..d7a37d26991 100644
--- a/src/test/compile-fail/coercion-slice.rs
+++ b/src/test/compile-fail/coercion-slice.rs
@@ -11,5 +11,10 @@
 // Tests that we forbid coercion from `[T; n]` to `&[T]`
 
 fn main() {
-    let _: &[isize] = [0is]; //~ERROR: mismatched types: expected `&[isize]`, found `[isize; 1]`
+    let _: &[isize] = [0is];
+    //~^ ERROR mismatched types
+    //~| expected `&[isize]`
+    //~| found `[isize; 1]`
+    //~| expected &-ptr
+    //~| found array of 1 elements
 }
diff --git a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
new file mode 100644
index 00000000000..c9dfb8201a9
--- /dev/null
+++ b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
@@ -0,0 +1,29 @@
+// 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.
+
+#![feature(optin_builtin_traits)]
+
+trait MyTrait {}
+
+struct TestType<T>;
+
+unsafe impl<T: MyTrait> Send for TestType<T> {}
+//~^ ERROR conflicting implementations for trait `core::marker::Send`
+//~^^ ERROR conflicting implementations for trait `core::marker::Send`
+
+impl<T: MyTrait> !Send for TestType<T> {}
+//~^ ERROR conflicting implementations for trait `core::marker::Send`
+
+unsafe impl<T> Send for TestType<T> {}
+//~^ ERROR error: conflicting implementations for trait `core::marker::Send`
+
+impl !Send for TestType<i32> {}
+
+fn main() {}
diff --git a/src/test/compile-fail/coherence-impls-builtin.rs b/src/test/compile-fail/coherence-impls-builtin.rs
new file mode 100644
index 00000000000..2ca288b60a3
--- /dev/null
+++ b/src/test/compile-fail/coherence-impls-builtin.rs
@@ -0,0 +1,37 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::marker::Send;
+
+enum TestE {
+  A
+}
+
+struct MyType;
+
+unsafe impl Send for TestE {}
+unsafe impl Send for MyType {}
+unsafe impl Send for (MyType, MyType) {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+unsafe impl Send for &'static MyType {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+unsafe impl Send for [MyType] {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+unsafe impl Send for &'static [MyType] {}
+//~^ ERROR builtin traits can only be implemented on structs or enums
+
+fn is_send<T: Send>() {}
+
+fn main() {
+    is_send::<(MyType, TestE)>();
+}
diff --git a/src/test/compile-fail/coherence-negative-impls-safe.rs b/src/test/compile-fail/coherence-negative-impls-safe.rs
new file mode 100644
index 00000000000..3b335d586f3
--- /dev/null
+++ b/src/test/compile-fail/coherence-negative-impls-safe.rs
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct TestType;
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative implementations are not unsafe
+
+fn main() {}
diff --git a/src/test/compile-fail/coherence-orphan.rs b/src/test/compile-fail/coherence-orphan.rs
index 0bd0224b246..f9f965e1ae3 100644
--- a/src/test/compile-fail/coherence-orphan.rs
+++ b/src/test/compile-fail/coherence-orphan.rs
@@ -8,8 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-linelength
 // aux-build:coherence-orphan-lib.rs
 
+#![feature(optin_builtin_traits)]
+
 extern crate "coherence-orphan-lib" as lib;
 
 use lib::TheTrait;
@@ -22,4 +25,7 @@ impl TheTrait<TheType> for isize { } //~ ERROR E0117
 
 impl TheTrait<isize> for TheType { }
 
+impl !Send for Vec<isize> { } //~ ERROR E0117
+//~^ ERROR conflicting
+
 fn main() { }
diff --git a/src/test/compile-fail/const-cast-different-types.rs b/src/test/compile-fail/const-cast-different-types.rs
index 6b8e126db77..6e3732908ac 100644
--- a/src/test/compile-fail/const-cast-different-types.rs
+++ b/src/test/compile-fail/const-cast-different-types.rs
@@ -10,9 +10,17 @@
 
 static a: &'static str = "foo";
 static b: *const u8 = a as *const u8;
-//~^ ERROR mismatched types: expected `*const u8`, found `&'static str`
+//~^ ERROR mismatched types
+//~| expected *const u8
+//~| found &'static str
+//~| expected u8
+//~| found str
 static c: *const u8 = &a as *const u8;
-//~^ ERROR mismatched types: expected `*const u8`, found `&&'static str`
+//~^ ERROR mismatched types
+//~| expected *const u8
+//~| found &&'static str
+//~| expected u8
+//~| found &-ptr
 
 fn main() {
 }
diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs
index ff96ea93184..86b7a8c8918 100644
--- a/src/test/compile-fail/cross-borrow-trait.rs
+++ b/src/test/compile-fail/cross-borrow-trait.rs
@@ -19,6 +19,10 @@ impl Trait for Foo {}
 
 pub fn main() {
     let x: Box<Trait> = box Foo;
-    let _y: &Trait = x; //~ ERROR mismatched types: expected `&Trait`, found `Box<Trait>`
+    let _y: &Trait = x; //~  ERROR mismatched types
+                        //~| expected `&Trait`
+                        //~| found `Box<Trait>`
+                        //~| expected &-ptr
+                        //~| found box
 }
 
diff --git a/src/test/compile-fail/destructure-trait-ref.rs b/src/test/compile-fail/destructure-trait-ref.rs
index 5166ef8f72f..5cc0d6a143a 100644
--- a/src/test/compile-fail/destructure-trait-ref.rs
+++ b/src/test/compile-fail/destructure-trait-ref.rs
@@ -37,7 +37,22 @@ fn main() {
     let box x = box 1is as Box<T>; //~ ERROR type `Box<T>` cannot be dereferenced
 
     // n > m
-    let &&x = &1is as &T;     //~ ERROR found &-ptr
-    let &&&x = &(&1is as &T); //~ ERROR found &-ptr
-    let box box x = box 1is as Box<T>;    //~ ERROR found box
+    let &&x = &1is as &T;
+    //~^ ERROR mismatched types
+    //~| expected `T`
+    //~| found `&_`
+    //~| expected trait T
+    //~| found &-ptr
+    let &&&x = &(&1is as &T);
+    //~^ ERROR mismatched types
+    //~| expected `T`
+    //~| found `&_`
+    //~| expected trait T
+    //~| found &-ptr
+    let box box x = box 1is as Box<T>;
+    //~^ ERROR mismatched types
+    //~| expected `T`
+    //~| found `Box<_>`
+    //~| expected trait T
+    //~| found box
 }
diff --git a/src/test/compile-fail/dst-bad-assign.rs b/src/test/compile-fail/dst-bad-assign.rs
index 634b5999e9e..152864b601c 100644
--- a/src/test/compile-fail/dst-bad-assign.rs
+++ b/src/test/compile-fail/dst-bad-assign.rs
@@ -44,6 +44,11 @@ pub fn main() {
     // Assignment.
     let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
     let z: Box<ToBar> = box Bar1 {f: 36};
-    f5.ptr = Bar1 {f: 36}; //~ ERROR mismatched types: expected `ToBar`, found `Bar1`
-    //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `ToBar`
+    f5.ptr = Bar1 {f: 36};
+    //~^ ERROR mismatched types
+    //~| expected `ToBar`
+    //~| found `Bar1`
+    //~| expected trait ToBar
+    //~| found struct `Bar1`
+    //~| ERROR the trait `core::marker::Sized` is not implemented for the type `ToBar`
 }
diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs
index e70db87a39a..2b96c5ebe12 100644
--- a/src/test/compile-fail/dst-bad-coerce1.rs
+++ b/src/test/compile-fail/dst-bad-coerce1.rs
@@ -22,7 +22,11 @@ pub fn main() {
     let f1 = Fat { ptr: [1, 2, 3] };
     let f2: &Fat<[isize; 3]> = &f1;
     let f3: &Fat<[usize]> = f2;
-    //~^ ERROR mismatched types: expected `&Fat<[usize]>`, found `&Fat<[isize; 3]>`
+    //~^ ERROR mismatched types
+    //~| expected `&Fat<[usize]>`
+    //~| found `&Fat<[isize; 3]>`
+    //~| expected usize
+    //~| found isize
 
     // With a trait.
     let f1 = Fat { ptr: Foo };
diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs
index 8e81eacae92..c1443bdbb30 100644
--- a/src/test/compile-fail/dst-bad-coerce4.rs
+++ b/src/test/compile-fail/dst-bad-coerce4.rs
@@ -18,5 +18,9 @@ pub fn main() {
     // With a vec of isizes.
     let f1: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] };
     let f2: &Fat<[isize; 3]> = f1;
-    //~^ ERROR mismatched types: expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
+    //~^ ERROR mismatched types
+    //~| expected `&Fat<[isize; 3]>`
+    //~| found `&Fat<[isize]>`
+    //~| expected array of 3 elements
+    //~| found slice
 }
diff --git a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
index fbc5263d82d..92542ab3bcb 100644
--- a/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
+++ b/src/test/compile-fail/explicit-self-lifetime-mismatch.rs
@@ -15,8 +15,14 @@ struct Foo<'a,'b> {
 
 impl<'a,'b> Foo<'a,'b> {
     fn bar(self: Foo<'b,'a>) {}
-    //~^ ERROR mismatched types: expected `Foo<'a, 'b>`, found `Foo<'b, 'a>`
-    //~^^ ERROR mismatched types: expected `Foo<'a, 'b>`, found `Foo<'b, 'a>`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<'a, 'b>`
+    //~| found `Foo<'b, 'a>`
+    //~| lifetime mismatch
+    //~| ERROR mismatched types
+    //~| expected `Foo<'a, 'b>`
+    //~| found `Foo<'b, 'a>`
+    //~| lifetime mismatch
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/fail-no-dead-code-core.rs b/src/test/compile-fail/fail-no-dead-code-core.rs
index 6f75181c31c..ee86c6ca1f0 100644
--- a/src/test/compile-fail/fail-no-dead-code-core.rs
+++ b/src/test/compile-fail/fail-no-dead-code-core.rs
@@ -10,6 +10,7 @@
 
 #![deny(dead_code)]
 #![allow(unreachable_code)]
+#![allow(unstable)]
 
 #[macro_use] extern crate core;
 
diff --git a/src/test/compile-fail/feature-gate-simd-ffi.rs b/src/test/compile-fail/feature-gate-simd-ffi.rs
new file mode 100644
index 00000000000..409c85b7198
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-simd-ffi.rs
@@ -0,0 +1,26 @@
+// 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(simd)]
+#![allow(dead_code)]
+
+use std::simd::f32x4;
+
+#[simd] #[derive(Copy)] #[repr(C)] struct LocalSimd(u8, u8);
+
+extern {
+    fn foo() -> f32x4; //~ ERROR use of SIMD type
+    fn bar(x: f32x4); //~ ERROR use of SIMD type
+
+    fn baz() -> LocalSimd; //~ ERROR use of SIMD type
+    fn qux(x: LocalSimd); //~ ERROR use of SIMD type
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/fn-item-type.rs b/src/test/compile-fail/fn-item-type.rs
index b2394a29899..5015810ff47 100644
--- a/src/test/compile-fail/fn-item-type.rs
+++ b/src/test/compile-fail/fn-item-type.rs
@@ -18,8 +18,16 @@ fn eq<T>(x: T, y: T) { }
 
 fn main() {
     let f = if true { foo } else { bar };
-    //~^ ERROR expected fn item, found a different fn item
+    //~^ ERROR if and else have incompatible types
+    //~| expected `fn(isize) -> isize {foo}`
+    //~| found `fn(isize) -> isize {bar}`
+    //~| expected fn item,
+    //~| found a different fn item
 
     eq(foo, bar);
-    //~^ ERROR expected fn item, found a different fn item
+    //~^ ERROR mismatched types
+    //~|  expected `fn(isize) -> isize {foo}`
+    //~|  found `fn(isize) -> isize {bar}`
+    //~|  expected fn item
+    //~|  found a different fn item
 }
diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs
index 3f5a92605b7..f19e27640cb 100644
--- a/src/test/compile-fail/fn-trait-formatting.rs
+++ b/src/test/compile-fail/fn-trait-formatting.rs
@@ -14,12 +14,25 @@
 fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
 
 fn main() {
-    let _: () = (box |:_: isize| {}) as Box<FnOnce(isize)>; //~ ERROR object-safe
-    //~^ ERROR Box<core::ops::FnOnce(isize)>
+    let _: () = (box |:_: isize| {}) as Box<FnOnce(isize)>;
+    //~^ ERROR object-safe
+    //~| ERROR mismatched types
+    //~| expected `()`
+    //~| found `Box<core::ops::FnOnce(isize)>`
+    //~| expected ()
+    //~| found box
     let _: () = (box |&:_: isize, isize| {}) as Box<Fn(isize, isize)>;
-    //~^ ERROR Box<core::ops::Fn(isize, isize)>
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `Box<core::ops::Fn(isize, isize)>`
+    //~| expected ()
+    //~| found box
     let _: () = (box |&mut:| -> isize unimplemented!()) as Box<FnMut() -> isize>;
-    //~^ ERROR Box<core::ops::FnMut() -> isize>
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `Box<core::ops::FnMut() -> isize>`
+    //~| expected ()
+    //~| found box
 
     needs_fn(1is); //~ ERROR `core::ops::Fn(isize) -> isize`
 }
diff --git a/src/test/compile-fail/fully-qualified-type-name1.rs b/src/test/compile-fail/fully-qualified-type-name1.rs
index 5ab946a53e5..029acbff9c3 100644
--- a/src/test/compile-fail/fully-qualified-type-name1.rs
+++ b/src/test/compile-fail/fully-qualified-type-name1.rs
@@ -13,5 +13,9 @@
 fn main() {
     let x: Option<usize>;
     x = 5;
-    //~^ ERROR mismatched types: expected `core::option::Option<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `core::option::Option<usize>`
+    //~| found `_`
+    //~| expected enum `core::option::Option`
+    //~| found integral variable
 }
diff --git a/src/test/compile-fail/fully-qualified-type-name2.rs b/src/test/compile-fail/fully-qualified-type-name2.rs
index 94af50dac0e..ab542d90800 100644
--- a/src/test/compile-fail/fully-qualified-type-name2.rs
+++ b/src/test/compile-fail/fully-qualified-type-name2.rs
@@ -20,7 +20,11 @@ mod y {
 
 fn bar(x: x::foo) -> y::foo {
     return x;
-    //~^ ERROR mismatched types: expected `y::foo`, found `x::foo`
+    //~^ ERROR mismatched types
+    //~| expected `y::foo`
+    //~| found `x::foo`
+    //~| expected enum `y::foo`
+    //~| found enum `x::foo`
 }
 
 fn main() {
diff --git a/src/test/compile-fail/fully-qualified-type-name4.rs b/src/test/compile-fail/fully-qualified-type-name4.rs
index 9250444c3e6..d6d668b366a 100644
--- a/src/test/compile-fail/fully-qualified-type-name4.rs
+++ b/src/test/compile-fail/fully-qualified-type-name4.rs
@@ -14,7 +14,11 @@ use std::option::Option;
 
 fn bar(x: usize) -> Option<usize> {
     return x;
-    //~^ ERROR mismatched types: expected `core::option::Option<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `core::option::Option<usize>`
+    //~| found `usize`
+    //~| expected enum `core::option::Option`
+    //~| found usize
 }
 
 fn main() {
diff --git a/src/test/compile-fail/generic-type-params-name-repr.rs b/src/test/compile-fail/generic-type-params-name-repr.rs
index 5769b9d7932..3e34344d78b 100644
--- a/src/test/compile-fail/generic-type-params-name-repr.rs
+++ b/src/test/compile-fail/generic-type-params-name-repr.rs
@@ -19,23 +19,47 @@ struct HashMap<K, V, H = Hash<K>>;
 fn main() {
     // Ensure that the printed type doesn't include the default type params...
     let _: Foo<isize> = ();
-    //~^ ERROR mismatched types: expected `Foo<isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<isize>`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 
     // ...even when they're present, but the same types as the defaults.
     let _: Foo<isize, B, C> = ();
-    //~^ ERROR mismatched types: expected `Foo<isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<isize>`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 
     // Including cases where the default is using previous type params.
     let _: HashMap<String, isize> = ();
-    //~^ ERROR mismatched types: expected `HashMap<collections::string::String, isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `HashMap<collections::string::String, isize>`
+    //~| found `()`
+    //~| expected struct `HashMap`
+    //~| found ()
     let _: HashMap<String, isize, Hash<String>> = ();
-    //~^ ERROR mismatched types: expected `HashMap<collections::string::String, isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `HashMap<collections::string::String, isize>`
+    //~| found `()`
+    //~| expected struct `HashMap`
+    //~| found ()
 
     // But not when there's a different type in between.
     let _: Foo<A, isize, C> = ();
-    //~^ ERROR mismatched types: expected `Foo<A, isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<A, isize>`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 
     // And don't print <> at all when there's just defaults.
     let _: Foo<A, B, C> = ();
-    //~^ ERROR mismatched types: expected `Foo`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 }
diff --git a/src/test/compile-fail/huge-enum.rs b/src/test/compile-fail/huge-enum.rs
index aef1fa85e0d..6e7c05370b9 100644
--- a/src/test/compile-fail/huge-enum.rs
+++ b/src/test/compile-fail/huge-enum.rs
@@ -12,12 +12,12 @@
 
 // FIXME: work properly with higher limits
 
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 fn main() {
     let big: Option<[u32; (1<<29)-1]> = None;
 }
 
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 fn main() {
     let big: Option<[u32; (1<<45)-1]> = None;
 }
diff --git a/src/test/compile-fail/if-branch-types.rs b/src/test/compile-fail/if-branch-types.rs
index be54554a3c0..2209a02c639 100644
--- a/src/test/compile-fail/if-branch-types.rs
+++ b/src/test/compile-fail/if-branch-types.rs
@@ -10,5 +10,9 @@
 
 fn main() {
     let x = if true { 10is } else { 10us };
-    //~^ ERROR if and else have incompatible types: expected `isize`, found `usize`
+    //~^ ERROR if and else have incompatible types
+    //~| expected `isize`
+    //~| found `usize`
+    //~| expected isize
+    //~| found usize
 }
diff --git a/src/test/compile-fail/if-without-else-result.rs b/src/test/compile-fail/if-without-else-result.rs
index 89beb9a3160..a9567f4272f 100644
--- a/src/test/compile-fail/if-without-else-result.rs
+++ b/src/test/compile-fail/if-without-else-result.rs
@@ -10,6 +10,10 @@
 
 fn main() {
     let a = if true { true };
-//~^ ERROR if may be missing an else clause: expected `()`, found `bool` (expected (), found bool)
+    //~^ ERROR if may be missing an else clause
+    //~| expected `()`
+    //~| found `bool`
+    //~| expected ()
+    //~| found bool
     println!("{}", a);
 }
diff --git a/src/test/compile-fail/integer-literal-suffix-inference.rs b/src/test/compile-fail/integer-literal-suffix-inference.rs
index 1e42a9447f6..5d9314faef9 100644
--- a/src/test/compile-fail/integer-literal-suffix-inference.rs
+++ b/src/test/compile-fail/integer-literal-suffix-inference.rs
@@ -39,62 +39,242 @@ fn main() {
     fn id_u64(n: u64) -> u64 { n }
 
     id_i8(a8); // ok
-    id_i8(a16); //~ ERROR mismatched types: expected `i8`, found `i16`
-    id_i8(a32); //~ ERROR mismatched types: expected `i8`, found `i32`
-    id_i8(a64); //~ ERROR mismatched types: expected `i8`, found `i64`
+    id_i8(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i16`
+    //~| expected i8
+    //~| found i16
+    id_i8(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i32`
+    //~| expected i8
+    //~| found i32
+    id_i8(a64);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i64`
+    //~| expected i8
+    //~| found i64
 
-    id_i16(a8); //~ ERROR mismatched types: expected `i16`, found `i8`
+    id_i16(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i8`
+    //~| expected i16
+    //~| found i8
     id_i16(a16); // ok
-    id_i16(a32); //~ ERROR mismatched types: expected `i16`, found `i32`
-    id_i16(a64); //~ ERROR mismatched types: expected `i16`, found `i64`
+    id_i16(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i32`
+    //~| expected i16
+    //~| found i32
+    id_i16(a64);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i64`
+    //~| expected i16
+    //~| found i64
 
-    id_i32(a8); //~ ERROR mismatched types: expected `i32`, found `i8`
-    id_i32(a16); //~ ERROR mismatched types: expected `i32`, found `i16`
+    id_i32(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i8`
+    //~| expected i32
+    //~| found i8
+    id_i32(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i16`
+    //~| expected i32
+    //~| found i16
     id_i32(a32); // ok
-    id_i32(a64); //~ ERROR mismatched types: expected `i32`, found `i64`
+    id_i32(a64);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i64`
+    //~| expected i32
+    //~| found i64
 
-    id_i64(a8); //~ ERROR mismatched types: expected `i64`, found `i8`
-    id_i64(a16); //~ ERROR mismatched types: expected `i64`, found `i16`
-    id_i64(a32); //~ ERROR mismatched types: expected `i64`, found `i32`
+    id_i64(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i8`
+    //~| expected i64
+    //~| found i8
+    id_i64(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i16`
+    //~| expected i64
+    //~| found i16
+    id_i64(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i32`
+    //~| expected i64
+    //~| found i32
     id_i64(a64); // ok
 
     id_i8(c8); // ok
-    id_i8(c16); //~ ERROR mismatched types: expected `i8`, found `i16`
-    id_i8(c32); //~ ERROR mismatched types: expected `i8`, found `i32`
-    id_i8(c64); //~ ERROR mismatched types: expected `i8`, found `i64`
+    id_i8(c16);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i16`
+    //~| expected i8
+    //~| found i16
+    id_i8(c32);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i32`
+    //~| expected i8
+    //~| found i32
+    id_i8(c64);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i64`
+    //~| expected i8
+    //~| found i64
 
-    id_i16(c8); //~ ERROR mismatched types: expected `i16`, found `i8`
+    id_i16(c8);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i8`
+    //~| expected i16
+    //~| found i8
     id_i16(c16); // ok
-    id_i16(c32); //~ ERROR mismatched types: expected `i16`, found `i32`
-    id_i16(c64); //~ ERROR mismatched types: expected `i16`, found `i64`
+    id_i16(c32);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i32`
+    //~| expected i16
+    //~| found i32
+    id_i16(c64);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i64`
+    //~| expected i16
+    //~| found i64
 
-    id_i32(c8); //~ ERROR mismatched types: expected `i32`, found `i8`
-    id_i32(c16); //~ ERROR mismatched types: expected `i32`, found `i16`
+    id_i32(c8);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i8`
+    //~| expected i32
+    //~| found i8
+    id_i32(c16);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i16`
+    //~| expected i32
+    //~| found i16
     id_i32(c32); // ok
-    id_i32(c64); //~ ERROR mismatched types: expected `i32`, found `i64`
+    id_i32(c64);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i64`
+    //~| expected i32
+    //~| found i64
 
-    id_i64(a8); //~ ERROR mismatched types: expected `i64`, found `i8`
-    id_i64(a16); //~ ERROR mismatched types: expected `i64`, found `i16`
-    id_i64(a32); //~ ERROR mismatched types: expected `i64`, found `i32`
+    id_i64(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i8`
+    //~| expected i64
+    //~| found i8
+    id_i64(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i16`
+    //~| expected i64
+    //~| found i16
+    id_i64(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i32`
+    //~| expected i64
+    //~| found i32
     id_i64(a64); // ok
 
     id_u8(b8); // ok
-    id_u8(b16); //~ ERROR mismatched types: expected `u8`, found `u16`
-    id_u8(b32); //~ ERROR mismatched types: expected `u8`, found `u32`
-    id_u8(b64); //~ ERROR mismatched types: expected `u8`, found `u64`
+    id_u8(b16);
+    //~^ ERROR mismatched types
+    //~| expected `u8`
+    //~| found `u16`
+    //~| expected u8
+    //~| found u16
+    id_u8(b32);
+    //~^ ERROR mismatched types
+    //~| expected `u8`
+    //~| found `u32`
+    //~| expected u8
+    //~| found u32
+    id_u8(b64);
+    //~^ ERROR mismatched types
+    //~| expected `u8`
+    //~| found `u64`
+    //~| expected u8
+    //~| found u64
 
-    id_u16(b8); //~ ERROR mismatched types: expected `u16`, found `u8`
+    id_u16(b8);
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u8`
+    //~| expected u16
+    //~| found u8
     id_u16(b16); // ok
-    id_u16(b32); //~ ERROR mismatched types: expected `u16`, found `u32`
-    id_u16(b64); //~ ERROR mismatched types: expected `u16`, found `u64`
+    id_u16(b32);
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u32`
+    //~| expected u16
+    //~| found u32
+    id_u16(b64);
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u64`
+    //~| expected u16
+    //~| found u64
 
-    id_u32(b8); //~ ERROR mismatched types: expected `u32`, found `u8`
-    id_u32(b16); //~ ERROR mismatched types: expected `u32`, found `u16`
+    id_u32(b8);
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `u8`
+    //~| expected u32
+    //~| found u8
+    id_u32(b16);
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `u16`
+    //~| expected u32
+    //~| found u16
     id_u32(b32); // ok
-    id_u32(b64); //~ ERROR mismatched types: expected `u32`, found `u64`
+    id_u32(b64);
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `u64`
+    //~| expected u32
+    //~| found u64
 
-    id_u64(b8); //~ ERROR mismatched types: expected `u64`, found `u8`
-    id_u64(b16); //~ ERROR mismatched types: expected `u64`, found `u16`
-    id_u64(b32); //~ ERROR mismatched types: expected `u64`, found `u32`
+    id_u64(b8);
+    //~^ ERROR mismatched types
+    //~| expected `u64`
+    //~| found `u8`
+    //~| expected u64
+    //~| found u8
+    id_u64(b16);
+    //~^ ERROR mismatched types
+    //~| expected `u64`
+    //~| found `u16`
+    //~| expected u64
+    //~| found u16
+    id_u64(b32);
+    //~^ ERROR mismatched types
+    //~| expected `u64`
+    //~| found `u32`
+    //~| expected u64
+    //~| found u32
     id_u64(b64); // ok
 }
diff --git a/src/test/compile-fail/integral-variable-unification-error.rs b/src/test/compile-fail/integral-variable-unification-error.rs
index fbbe4cf8dbc..3374f715917 100644
--- a/src/test/compile-fail/integral-variable-unification-error.rs
+++ b/src/test/compile-fail/integral-variable-unification-error.rs
@@ -11,5 +11,9 @@
 fn main() {
     let mut x = 2;
     x = 5.0;
-//~^ ERROR expected `_`, found `_` (expected integral variable, found floating-point variable)
+    //~^ ERROR mismatched types
+    //~| expected `_`
+    //~| found `_`
+    //~| expected integral variable
+    //~| found floating-point variable
 }
diff --git a/src/test/compile-fail/issue-10176.rs b/src/test/compile-fail/issue-10176.rs
index 832cc57bd24..6e84e777898 100644
--- a/src/test/compile-fail/issue-10176.rs
+++ b/src/test/compile-fail/issue-10176.rs
@@ -10,7 +10,11 @@
 
 fn f() -> isize {
     (return 1, return 2)
-//~^ ERROR mismatched types: expected `isize`, found `(_, _)` (expected isize, found tuple)
+//~^ ERROR mismatched types
+//~| expected `isize`
+//~| found `(_, _)`
+//~| expected isize
+//~| found tuple
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-11319.rs b/src/test/compile-fail/issue-11319.rs
index c818b3bb26c..d3e44b71b1c 100644
--- a/src/test/compile-fail/issue-11319.rs
+++ b/src/test/compile-fail/issue-11319.rs
@@ -10,7 +10,11 @@
 
 fn main() {
     match Some(10) {
-    //~^ ERROR match arms have incompatible types: expected `bool`, found `()`
+    //~^ ERROR match arms have incompatible types:
+    //~| expected `bool`
+    //~| found `()`
+    //~| expected bool
+    //~| found ()
         Some(5) => false,
         Some(2) => true,
         None    => (), //~ NOTE match arm with an incompatible type
diff --git a/src/test/compile-fail/issue-11771.rs b/src/test/compile-fail/issue-11771.rs
index 7ce23e1f6ac..2de86e527ef 100644
--- a/src/test/compile-fail/issue-11771.rs
+++ b/src/test/compile-fail/issue-11771.rs
@@ -11,11 +11,19 @@
 fn main() {
     let x = ();
     1 +
-    x //~ ERROR mismatched types: expected `_`, found `()` (expected integral variable, found ())
+    x //~  ERROR mismatched types
+      //~| expected `_`
+      //~| found `()`
+      //~| expected integral variable
+      //~| found ()
     ;
 
     let x: () = ();
     1 +
-    x //~ ERROR mismatched types: expected `_`, found `()` (expected integral variable, found ())
+    x //~  ERROR mismatched types
+      //~| expected `_`
+      //~| found `()`
+      //~| expected integral variable
+      //~| found ()
     ;
 }
diff --git a/src/test/compile-fail/issue-12997-2.rs b/src/test/compile-fail/issue-12997-2.rs
index 39957a24226..1cf534e7e41 100644
--- a/src/test/compile-fail/issue-12997-2.rs
+++ b/src/test/compile-fail/issue-12997-2.rs
@@ -12,6 +12,10 @@
 
 //! Test that makes sure wrongly-typed bench functions are rejected
 
-// error-pattern:expected &-ptr, found isize
 #[bench]
 fn bar(x: isize) { }
+//~^ ERROR mismatched types
+//~| expected `fn(&mut test::Bencher)`
+//~| found `fn(isize) {bar}`
+//~| expected &-ptr
+//~| found isize
diff --git a/src/test/compile-fail/issue-13058.rs b/src/test/compile-fail/issue-13058.rs
index eee82483cae..61b50ef705f 100644
--- a/src/test/compile-fail/issue-13058.rs
+++ b/src/test/compile-fail/issue-13058.rs
@@ -35,5 +35,9 @@ fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
 
 fn main() {
     check((3us, 5us));
-//~^ ERROR mismatched types: expected `&_`, found `(usize, usize)` (expected &-ptr, found tuple)
+//~^ ERROR mismatched types
+//~| expected `&_`
+//~| found `(usize, usize)`
+//~| expected &-ptr
+//~| found tuple
 }
diff --git a/src/test/compile-fail/issue-13359.rs b/src/test/compile-fail/issue-13359.rs
index 2e338860377..c53e5760941 100644
--- a/src/test/compile-fail/issue-13359.rs
+++ b/src/test/compile-fail/issue-13359.rs
@@ -14,8 +14,16 @@ fn bar(_s: u32) { }
 
 fn main() {
     foo(1*(1 as isize));
-    //~^ ERROR: mismatched types: expected `i16`, found `isize` (expected i16, found isize)
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `isize`
+    //~| expected i16
+    //~| found isize
 
     bar(1*(1 as usize));
-    //~^ ERROR: mismatched types: expected `u32`, found `usize` (expected u32, found usize)
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `usize`
+    //~| expected u32
+    //~| found usize
 }
diff --git a/src/test/compile-fail/issue-13466.rs b/src/test/compile-fail/issue-13466.rs
index 7d554545b5e..09e2905dc40 100644
--- a/src/test/compile-fail/issue-13466.rs
+++ b/src/test/compile-fail/issue-13466.rs
@@ -15,7 +15,18 @@ pub fn main() {
     // the actual arm `Result<T, E>` has two. typeck should not be
     // tricked into looking up a non-existing second type parameter.
     let _x: usize = match Some(1us) {
-        Ok(u) => u, //~ ERROR  mismatched types: expected `core::option::Option<usize>`
-        Err(e) => panic!(e)  //~ ERROR mismatched types: expected `core::option::Option<usize>`
+        Ok(u) => u,
+        //~^ ERROR mismatched types
+        //~| expected `core::option::Option<usize>`
+        //~| found `core::result::Result<_, _>`
+        //~| expected enum `core::option::Option`
+        //~| found enum `core::result::Result`
+
+        Err(e) => panic!(e)
+        //~^ ERROR mismatched types
+        //~| expected `core::option::Option<usize>`
+        //~| found `core::result::Result<_, _>`
+        //~| expected enum `core::option::Option`
+        //~| found enum `core::result::Result`
     };
 }
diff --git a/src/test/compile-fail/issue-13482-2.rs b/src/test/compile-fail/issue-13482-2.rs
index ef7d3d4d158..86a79416c77 100644
--- a/src/test/compile-fail/issue-13482-2.rs
+++ b/src/test/compile-fail/issue-13482-2.rs
@@ -14,8 +14,11 @@ fn main() {
     let x = [1,2];
     let y = match x {
         [] => None,
-        //~^ ERROR types: expected `[_#0i; 2]`, found `[_#7t; 0]`
-        //         (expected array of 2 elements, found array of 0 elements)
+//~^ ERROR mismatched types
+//~| expected `[_#0i; 2]`
+//~| found `[_#7t; 0]`
+//~| expected an array with a fixed size of 2 elements
+//~| found one with 0 elements
         [a,_] => Some(a)
     };
 }
diff --git a/src/test/compile-fail/issue-13482.rs b/src/test/compile-fail/issue-13482.rs
index 157280b1719..a345ce79612 100644
--- a/src/test/compile-fail/issue-13482.rs
+++ b/src/test/compile-fail/issue-13482.rs
@@ -12,8 +12,10 @@ fn main() {
   let x = [1,2];
   let y = match x {
     [] => None,
-//~^ ERROR types: expected `[_; 2]`, found `[_; 0]`
-//         (expected array of 2 elements, found array of 0 elements)
+    //~^ ERROR mismatched types
+    //~| expected `[_; 2]`
+    //~| found `[_; 0]`
+    //~| expected array with a fixed size of 2 elements
     [a,_] => Some(a)
   };
 }
diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/compile-fail/issue-13624.rs
index 83612823c59..2a5805790a7 100644
--- a/src/test/compile-fail/issue-13624.rs
+++ b/src/test/compile-fail/issue-13624.rs
@@ -15,7 +15,11 @@ mod a {
 
   pub fn get_enum_struct_variant() -> () {
     Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
-//~^ ERROR mismatched types: expected `()`, found `a::Enum` (expected (), found enum a::Enum)
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `a::Enum`
+    //~| expected ()
+    //~| found enum `a::Enum`
   }
 }
 
@@ -27,8 +31,11 @@ mod b {
       let enum_struct_variant = ::a::get_enum_struct_variant();
       match enum_struct_variant {
         a::Enum::EnumStructVariant { x, y, z } => {
-        //~^ ERROR mismatched types: expected `()`, found `a::Enum`
-        //         (expected (), found enum a::Enum)
+        //~^ ERROR mismatched types
+        //~| expected `()`
+        //~| found `a::Enum`
+        //~| expected ()
+        // found enum `a::Enum`
         }
       }
     }
diff --git a/src/test/compile-fail/issue-14091.rs b/src/test/compile-fail/issue-14091.rs
index c2ad09f5cb4..3ceb465cb4b 100644
--- a/src/test/compile-fail/issue-14091.rs
+++ b/src/test/compile-fail/issue-14091.rs
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: expected `bool`, found `_` (expected bool, found integral variable)
+// error-pattern:mismatched types
+// error-pattern:expected `bool`
+// error-pattern:found `_`
+// error-pattern:expected bool
+// error-pattern:found integral variable
 
 fn main(){assert!(1,1);}
diff --git a/src/test/compile-fail/issue-14541.rs b/src/test/compile-fail/issue-14541.rs
index ac49f8b99cf..deb8f00cd01 100644
--- a/src/test/compile-fail/issue-14541.rs
+++ b/src/test/compile-fail/issue-14541.rs
@@ -13,8 +13,11 @@ struct vec3 { y: f32, z: f32 }
 
 fn make(v: vec2) {
     let vec3 { y: _, z: _ } = v;
-    //~^ ERROR mismatched types: expected `vec2`, found `vec3`
-    //         (expected struct vec2, found struct vec3)
+    //~^ ERROR mismatched types
+    //~| expected `vec2`
+    //~| found `vec3`
+    //~| expected struct `vec2`
+    //~| found struct `vec3`
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-14845.rs b/src/test/compile-fail/issue-14845.rs
index 5166d84a025..d7ff6f2fe63 100644
--- a/src/test/compile-fail/issue-14845.rs
+++ b/src/test/compile-fail/issue-14845.rs
@@ -16,9 +16,17 @@ struct X {
 fn main() {
     let x = X { a: [0] };
     let _f = &x.a as *mut u8;
-    //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8; 1]`
+    //~^ ERROR mismatched types
+    //~| expected `*mut u8`
+    //~| found `&[u8; 1]`
+    //~| expected u8
+    //~| found array of 1 elements
 
     let local = [0u8];
     let _v = &local as *mut u8;
-    //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8; 1]`
+    //~^ ERROR mismatched types
+    //~| expected `*mut u8`
+    //~| found `&[u8; 1]`
+    //~| expected u8,
+    //~| found array of 1 elements
 }
diff --git a/src/test/compile-fail/issue-14853.rs b/src/test/compile-fail/issue-14853.rs
index 3d8ebc1ecdf..22ba54fea14 100644
--- a/src/test/compile-fail/issue-14853.rs
+++ b/src/test/compile-fail/issue-14853.rs
@@ -20,8 +20,7 @@ struct X { data: u32 }
 
 impl Something for X {
     fn yay<T: Str>(_:Option<X>, thing: &[T]) {
-//~^ ERROR in method `yay`, type parameter 0 requires bound `Str`, which is not required
-
+    //~^ ERROR the requirement `T : Str` appears on the impl method
     }
 }
 
diff --git a/src/test/compile-fail/issue-15783.rs b/src/test/compile-fail/issue-15783.rs
index 1b1b0302383..7080db23d42 100644
--- a/src/test/compile-fail/issue-15783.rs
+++ b/src/test/compile-fail/issue-15783.rs
@@ -14,7 +14,12 @@ pub fn foo(params: Option<&[&str]>) -> usize {
 
 fn main() {
     let name = "Foo";
-    let msg = foo(Some(&[name.as_slice()]));
-//~^ ERROR mismatched types: expected `core::option::Option<&[&str]>`
+    let x = Some(&[name.as_slice()]);
+    let msg = foo(x);
+//~^ ERROR mismatched types
+//~| expected `core::option::Option<&[&str]>`
+//~| found `core::option::Option<&[&str; 1]>`
+//~| expected slice
+//~| found array of 1 elements
     assert_eq!(msg, 3);
 }
diff --git a/src/test/compile-fail/issue-15896.rs b/src/test/compile-fail/issue-15896.rs
index c4373ba3351..7381ade263b 100644
--- a/src/test/compile-fail/issue-15896.rs
+++ b/src/test/compile-fail/issue-15896.rs
@@ -19,8 +19,11 @@ fn main() {
     let u = match e {
         E::B(
           Tau{t: x},
-          //~^ ERROR mismatched types: expected `main::R`, found `main::Tau`
-          //        (expected enum main::R, found struct main::Tau)
+          //~^ ERROR mismatched types
+          //~| expected `main::R`
+          //~| found `main::Tau`
+          //~| expected enum `main::R`
+          //~| found struct `main::Tau`
           _) => x,
     };
 }
diff --git a/src/test/compile-fail/issue-16338.rs b/src/test/compile-fail/issue-16338.rs
index f62bccb22f3..ba936561ae5 100644
--- a/src/test/compile-fail/issue-16338.rs
+++ b/src/test/compile-fail/issue-16338.rs
@@ -12,7 +12,10 @@ use std::raw::Slice;
 
 fn main() {
     let Slice { data: data, len: len } = "foo";
-    //~^ ERROR mismatched types: expected `&str`, found `core::raw::Slice<_>`
-    //         (expected &-ptr, found struct core::raw::Slice)
+    //~^ ERROR mismatched types
+    //~| expected `&str`
+    //~| found `core::raw::Slice<_>`
+    //~| expected &-ptr
+    //~| found struct `core::raw::Slice`
 }
 
diff --git a/src/test/compile-fail/issue-16401.rs b/src/test/compile-fail/issue-16401.rs
index 4890cc52c00..b943ef510da 100644
--- a/src/test/compile-fail/issue-16401.rs
+++ b/src/test/compile-fail/issue-16401.rs
@@ -13,8 +13,11 @@ use std::raw::Slice;
 fn main() {
     match () {
         Slice { data: data, len: len } => (),
-        //~^ ERROR mismatched types: expected `()`, found `core::raw::Slice<_>`
-        //         (expected (), found struct core::raw::Slice)
+        //~^ ERROR mismatched types
+        //~| expected `()`
+        //~| found `core::raw::Slice<_>`
+        //~| expected ()
+        //~| found struct `core::raw::Slice`
         _ => unreachable!()
     }
 }
diff --git a/src/test/compile-fail/issue-17033.rs b/src/test/compile-fail/issue-17033.rs
index 5048a9aa919..6010e206920 100644
--- a/src/test/compile-fail/issue-17033.rs
+++ b/src/test/compile-fail/issue-17033.rs
@@ -11,7 +11,11 @@
 #![feature(overloaded_calls)]
 
 fn f<'r>(p: &'r mut fn(p: &mut ())) {
-    (*p)(()) //~ ERROR mismatched types: expected `&mut ()`, found `()`
+    (*p)(()) //~  ERROR mismatched types
+             //~| expected `&mut ()`
+             //~| found `()`
+             //~| expected &-ptr
+             //~| found ()
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/compile-fail/issue-17283.rs
index 0c9fd9d9486..4889658d083 100644
--- a/src/test/compile-fail/issue-17283.rs
+++ b/src/test/compile-fail/issue-17283.rs
@@ -21,17 +21,29 @@ fn main() {
 
     // `x { ... }` should not be interpreted as a struct literal here
     if x = x {
-        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        //~^ ERROR mismatched types
+        //~| expected `bool`
+        //~| found `()`
+        //~| expected bool
+        //~| found ()
         println!("{}", x);
     }
     // Explicit parentheses on the left should match behavior of above
     if (x = x) {
-        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        //~^ ERROR mismatched types
+        //~| expected `bool`
+        //~| found `()`
+        //~| expected bool
+        //~| found ()
         println!("{}", x);
     }
     // The struct literal interpretation is fine with explicit parentheses on the right
     if y = (Foo { foo: x }) {
-        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        //~^ ERROR mismatched types
+        //~| expected `bool`
+        //~| found `()`
+        //~| expected bool
+        //~| found ()
         println!("{}", x);
     }
 }
diff --git a/src/test/compile-fail/issue-17718-static-sync.rs b/src/test/compile-fail/issue-17718-static-sync.rs
index 394a9cc69be..fa8035a7965 100644
--- a/src/test/compile-fail/issue-17718-static-sync.rs
+++ b/src/test/compile-fail/issue-17718-static-sync.rs
@@ -8,12 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-struct Foo { marker: marker::NoSync }
+use std::marker::Sync;
+
+struct Foo;
+impl !Sync for Foo {}
 
 static FOO: usize = 3;
-static BAR: Foo = Foo { marker: marker::NoSync };
+static BAR: Foo = Foo;
 //~^ ERROR: the trait `core::marker::Sync` is not implemented
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-17740.rs b/src/test/compile-fail/issue-17740.rs
index 73f86fee903..b4791eba76e 100644
--- a/src/test/compile-fail/issue-17740.rs
+++ b/src/test/compile-fail/issue-17740.rs
@@ -14,8 +14,14 @@ struct Foo<'a> {
 
 impl <'a> Foo<'a>{
     fn bar(self: &mut Foo) {
-    //~^ mismatched types: expected `Foo<'a>`, found `Foo<'_>` (lifetime mismatch)
-    //~| mismatched types: expected `Foo<'a>`, found `Foo<'_>` (lifetime mismatch)
+    //~^ mismatched types
+    //~| expected `Foo<'a>`
+    //~| found `Foo<'_>`
+    //~| lifetime mismatch
+    //~| mismatched types
+    //~| expected `Foo<'a>`
+    //~| found `Foo<'_>`
+    //~| lifetime mismatch
     }
 }
 
diff --git a/src/test/compile-fail/issue-17905.rs b/src/test/compile-fail/issue-17905.rs
index 1418cdf4039..9d1047f68e6 100644
--- a/src/test/compile-fail/issue-17905.rs
+++ b/src/test/compile-fail/issue-17905.rs
@@ -16,7 +16,10 @@ impl Pair<
     isize
 > {
     fn say(self: &Pair<&str, isize>) {
-//~^ ERROR mismatched types: expected `Pair<&'static str, isize>`, found `Pair<&str, isize>`
+//~^ ERROR mismatched types
+//~| expected `Pair<&'static str, isize>`
+//~| found `Pair<&str, isize>`
+//~| lifetime mismatch
         println!("{}", self);
     }
 }
diff --git a/src/test/compile-fail/issue-17913.rs b/src/test/compile-fail/issue-17913.rs
index 56cd544b3c6..1f5264aef61 100644
--- a/src/test/compile-fail/issue-17913.rs
+++ b/src/test/compile-fail/issue-17913.rs
@@ -13,14 +13,14 @@
 
 #![feature(box_syntax)]
 
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 fn main() {
     let n = 0us;
     let a = box [&n; 0xF000000000000000us];
     println!("{}", a[0xFFFFFFu]);
 }
 
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 fn main() {
     let n = 0us;
     let a = box [&n; 0xFFFFFFFFu];
diff --git a/src/test/compile-fail/issue-17999.rs b/src/test/compile-fail/issue-17999.rs
index 5726960f66a..eaefe55e066 100644
--- a/src/test/compile-fail/issue-17999.rs
+++ b/src/test/compile-fail/issue-17999.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![deny(unused_variables)]
+#![allow(unstable)]
 
 fn main() {
     for _ in range(1is, 101) {
diff --git a/src/test/compile-fail/issue-19991.rs b/src/test/compile-fail/issue-19991.rs
index 0f1dbfa3492..2d73b98ec1e 100644
--- a/src/test/compile-fail/issue-19991.rs
+++ b/src/test/compile-fail/issue-19991.rs
@@ -12,7 +12,11 @@
 // clause does not exist, instead of the unsympathetic "match arms have incompatible types"
 
 fn main() {
-    if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause: expected `()`
+    if let Some(homura) = Some("madoka") { //~  ERROR missing an else clause
+                                           //~| expected `()`
+                                           //~| found `i32`
+                                           //~| expected ()
+                                           //~| found i32
         765i32
     };
 }
diff --git a/src/test/compile-fail/issue-20831-debruijn.rs b/src/test/compile-fail/issue-20831-debruijn.rs
new file mode 100644
index 00000000000..aaf45f27398
--- /dev/null
+++ b/src/test/compile-fail/issue-20831-debruijn.rs
@@ -0,0 +1,49 @@
+// 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.
+
+// Regression test for #20831: debruijn index account was thrown off
+// by the (anonymous) lifetime in `<Self as Publisher>::Output`
+// below. Note that changing to a named lifetime made the problem go
+// away.
+
+use std::ops::{Shl, Shr};
+use std::cell::RefCell;
+
+pub trait Subscriber {
+    type Input;
+}
+
+pub trait Publisher<'a> {
+    type Output;
+    fn subscribe(&mut self, Box<Subscriber<Input=Self::Output> + 'a>);
+}
+
+pub trait Processor<'a> : Subscriber + Publisher<'a> { }
+
+impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
+
+struct MyStruct<'a> {
+    sub: Box<Subscriber<Input=u64> + 'a>
+}
+
+impl<'a> Publisher<'a> for MyStruct<'a> {
+    type Output = u64;
+    fn subscribe(&mut self, t : Box<Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+        // Not obvious, but there is an implicit lifetime here -------^
+        //~^^ ERROR cannot infer
+        //
+        // The fact that `Publisher` is using an implicit lifetime is
+        // what was causing the debruijn accounting to be off, so
+        // leave it that way!
+        self.sub = t;
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-21045.rs b/src/test/compile-fail/issue-21045.rs
new file mode 100644
index 00000000000..134240f8c8a
--- /dev/null
+++ b/src/test/compile-fail/issue-21045.rs
@@ -0,0 +1,16 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![feature(asm)]
+
+fn main() {
+    let a;
+    asm!("nop" "nop"); //~ ERROR malformed inline assembly
+    asm!("nop" "nop" : "=r"(a)); //~ ERROR malformed inline assembly
+}
diff --git a/src/test/compile-fail/issue-21160.rs b/src/test/compile-fail/issue-21160.rs
new file mode 100644
index 00000000000..0ee38166935
--- /dev/null
+++ b/src/test/compile-fail/issue-21160.rs
@@ -0,0 +1,21 @@
+// 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.
+
+struct Bar;
+
+impl Bar {
+    fn hash<T>(&self, _: T) {}
+}
+
+#[derive(Hash)]
+struct Foo(Bar);
+//~^ error: the trait `core::hash::Hash<__S>` is not implemented for the type `Bar`
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-21202.rs b/src/test/compile-fail/issue-21202.rs
new file mode 100644
index 00000000000..5c1de6dfc55
--- /dev/null
+++ b/src/test/compile-fail/issue-21202.rs
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-21202.rs
+
+extern crate "issue-21202" as crate1;
+
+use crate1::A;
+
+mod B {
+    use crate1::A::Foo;
+    fn bar(f: Foo) {
+        Foo::foo(&f);
+        //~^ ERROR: function `foo` is private
+    }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/issue-2611-4.rs b/src/test/compile-fail/issue-2611-4.rs
index b141c1f441a..31796e5e20c 100644
--- a/src/test/compile-fail/issue-2611-4.rs
+++ b/src/test/compile-fail/issue-2611-4.rs
@@ -20,7 +20,8 @@ struct E {
 }
 
 impl A for E {
-  fn b<F: Sync, G>(_x: F) -> F { panic!() } //~ ERROR type parameter 0 requires `Sync`
+    fn b<F: Sync, G>(_x: F) -> F { panic!() }
+    //~^ ERROR `F : core::marker::Sync` appears on the impl method
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-2951.rs b/src/test/compile-fail/issue-2951.rs
index 694bf05b210..d0781b56580 100644
--- a/src/test/compile-fail/issue-2951.rs
+++ b/src/test/compile-fail/issue-2951.rs
@@ -10,7 +10,12 @@
 
 fn foo<T, U>(x: T, y: U) {
     let mut xx = x;
-    xx = y; //~ ERROR expected `T`, found `U`
+    xx = y;
+    //~^  ERROR mismatched types
+    //~| expected `T`
+    //~| found `U`
+    //~| expected type parameter
+    //~| found a different type parameter
 }
 
 fn main() {
diff --git a/src/test/compile-fail/issue-3477.rs b/src/test/compile-fail/issue-3477.rs
index 798a8cfec9a..5e7c23164cb 100644
--- a/src/test/compile-fail/issue-3477.rs
+++ b/src/test/compile-fail/issue-3477.rs
@@ -9,5 +9,10 @@
 // except according to those terms.
 
 fn main() {
-    let _p: char = 100; //~ ERROR mismatched types: expected `char`, found
+    let _p: char = 100;
+    //~^ ERROR mismatched types
+    //~| expected `char`
+    //~| found `u8`
+    //~| expected char
+    //~| found u8
 }
diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/compile-fail/issue-3563.rs
index 86ab9be77fc..7ebc5b7a5b9 100644
--- a/src/test/compile-fail/issue-3563.rs
+++ b/src/test/compile-fail/issue-3563.rs
@@ -10,8 +10,13 @@
 
 trait A {
     fn a(&self) {
-        |&:| self.b() //~ ERROR type `&Self` does not implement any method in scope named `b`
-        //~^ ERROR expected (), found closure
+        |&:| self.b()
+        //~^ ERROR type `&Self` does not implement any method in scope named `b`
+        //~| ERROR mismatched types
+        //~| expected `()`
+        //~| found closure
+        //~| expected ()
+        //~| found closure
     }
 }
 fn main() {}
diff --git a/src/test/compile-fail/issue-3680.rs b/src/test/compile-fail/issue-3680.rs
index f018a02a945..4aff95b57de 100644
--- a/src/test/compile-fail/issue-3680.rs
+++ b/src/test/compile-fail/issue-3680.rs
@@ -11,7 +11,10 @@
 fn main() {
     match None {
         Err(_) => ()
-        //~^ ERROR mismatched types: expected `core::option::Option<_>`
-        //         , found `core::result::Result<_, _>`
+        //~^ ERROR mismatched types
+        //~| expected `core::option::Option<_>`
+        //~| found `core::result::Result<_, _>`
+        //~| expected enum `core::option::Option`
+        //~| found enum `core::result::Result`
     }
 }
diff --git a/src/test/compile-fail/issue-4201.rs b/src/test/compile-fail/issue-4201.rs
index 0391c73d90a..b5af1f03b63 100644
--- a/src/test/compile-fail/issue-4201.rs
+++ b/src/test/compile-fail/issue-4201.rs
@@ -12,7 +12,11 @@ fn main() {
     let a = if true {
         0
     } else if false {
-//~^ ERROR if may be missing an else clause: expected `()`, found `_`
+//~^ ERROR if may be missing an else clause
+//~| expected `()`
+//~| found `_`
+//~| expected ()
+//~| found integral variable
         1
     };
 }
diff --git a/src/test/compile-fail/issue-4517.rs b/src/test/compile-fail/issue-4517.rs
index 1943f1e5a19..881e124fd68 100644
--- a/src/test/compile-fail/issue-4517.rs
+++ b/src/test/compile-fail/issue-4517.rs
@@ -13,6 +13,9 @@ fn bar(int_param: usize) {}
 fn main() {
     let foo: [u8; 4] = [1u8; 4us];
     bar(foo);
-    //~^ ERROR mismatched types: expected `usize`, found `[u8; 4]`
-    //         (expected usize, found vector)
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `[u8; 4]`
+    //~| expected usize
+    //~| found array of 4 elements
 }
diff --git a/src/test/compile-fail/issue-4968.rs b/src/test/compile-fail/issue-4968.rs
index 88933c0add9..e7cd20f38a1 100644
--- a/src/test/compile-fail/issue-4968.rs
+++ b/src/test/compile-fail/issue-4968.rs
@@ -13,6 +13,9 @@
 const A: (isize,isize) = (4,2);
 fn main() {
     match 42 { A => () }
-    //~^ ERROR mismatched types: expected `_`, found `(isize, isize)`
-    //         (expected integral variable, found tuple)
+    //~^ ERROR mismatched types
+    //~| expected `_`
+    //~| found `(isize, isize)`
+    //~| expected integral variable
+    //~| found tuple
 }
diff --git a/src/test/compile-fail/issue-5100.rs b/src/test/compile-fail/issue-5100.rs
index ca7f87ff61a..b051abbc7ff 100644
--- a/src/test/compile-fail/issue-5100.rs
+++ b/src/test/compile-fail/issue-5100.rs
@@ -15,28 +15,48 @@ enum A { B, C }
 fn main() {
     match (true, false) {
         A::B => (),
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `A` (expected tuple, found enum A)
+//~^ ERROR mismatched types:
+//~| expected `(bool, bool)`
+//~| found `A`
+//~| expected tuple
+//~| found enum `A`
         _ => ()
     }
 
     match (true, false) {
         (true, false, false) => ()
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `(_, _, _)`
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `(_, _, _)`
+//~| expected a tuple with 2 elements
+//~| found one with 3 elements
     }
 
     match (true, false) {
         (true, false, false) => ()
-//~^ ERROR (expected a tuple with 2 elements, found one with 3 elements)
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `(_, _, _)`
+//~| expected a tuple with 2 elements
+//~| found one with 3 elements
     }
 
     match (true, false) {
         box (true, false) => ()
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `Box<_>` (expected tuple, found box)
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `Box<_>`
+//~| expected tuple
+//~| found box
     }
 
     match (true, false) {
         &(true, false) => ()
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `&_` (expected tuple, found &-ptr)
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `&_`
+//~| expected tuple
+//~| found &-ptr
     }
 
 
@@ -47,5 +67,9 @@ fn main() {
     for &(x,y) in v.iter() {} // should be OK
 
     // Make sure none of the errors above were fatal
-    let x: char = true; //~ ERROR expected `char`, found `bool`
+    let x: char = true; //~  ERROR mismatched types
+                        //~| expected `char`
+                        //~| found `bool`
+                        //~| expected char
+                        //~| found bool
 }
diff --git a/src/test/compile-fail/issue-5358-1.rs b/src/test/compile-fail/issue-5358-1.rs
index 96bad3a6a44..32702d3e2f6 100644
--- a/src/test/compile-fail/issue-5358-1.rs
+++ b/src/test/compile-fail/issue-5358-1.rs
@@ -13,7 +13,12 @@ struct S(Either<usize, usize>);
 
 fn main() {
     match S(Either::Left(5)) {
-        Either::Right(_) => {}  //~ ERROR mismatched types: expected `S`, found `Either
+        Either::Right(_) => {}
+        //~^ ERROR mismatched types
+        //~| expected `S`
+        //~| found `Either<_, _>`
+        //~| expected struct `S`
+        //~| found enum `Either`
         _ => {}
     }
 }
diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/compile-fail/issue-5500.rs
index 56867349065..565634191be 100644
--- a/src/test/compile-fail/issue-5500.rs
+++ b/src/test/compile-fail/issue-5500.rs
@@ -10,5 +10,9 @@
 
 fn main() {
     &panic!()
-    //~^ ERROR mismatched types: expected `()`, found `&_` (expected (), found &-ptr)
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `&_`
+    //~| expected ()
+    //~| found &-ptr
 }
diff --git a/src/test/compile-fail/issue-7013.rs b/src/test/compile-fail/issue-7013.rs
index d246e4e54d0..90ecfb6015d 100644
--- a/src/test/compile-fail/issue-7013.rs
+++ b/src/test/compile-fail/issue-7013.rs
@@ -35,5 +35,4 @@ struct A {
 fn main() {
     let a = A {v: box B{v: None} as Box<Foo+Send>};
     //~^ ERROR the trait `core::marker::Send` is not implemented
-    //~^^ ERROR the trait `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/issue-7061.rs b/src/test/compile-fail/issue-7061.rs
index c6869c44057..e261249bc99 100644
--- a/src/test/compile-fail/issue-7061.rs
+++ b/src/test/compile-fail/issue-7061.rs
@@ -12,7 +12,11 @@ struct BarStruct;
 
 impl<'a> BarStruct {
     fn foo(&'a mut self) -> Box<BarStruct> { self }
-    //~^ ERROR: error: mismatched types: expected `Box<BarStruct>`, found `&'a mut BarStruct
+    //~^ ERROR mismatched types
+    //~| expected `Box<BarStruct>`
+    //~| found `&'a mut BarStruct`
+    //~| expected box
+    //~| found &-ptr
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-7092.rs b/src/test/compile-fail/issue-7092.rs
index 116639f4945..eefb34fbe4c 100644
--- a/src/test/compile-fail/issue-7092.rs
+++ b/src/test/compile-fail/issue-7092.rs
@@ -14,7 +14,11 @@ enum Whatever {
 fn foo(x: Whatever) {
     match x {
         Some(field) =>
-//~^ ERROR: mismatched types: expected `Whatever`, found `core::option::Option<_>`
+//~^ ERROR mismatched types
+//~| expected `Whatever`
+//~| found `core::option::Option<_>`
+//~| expected enum `Whatever`
+//~| found enum `core::option::Option`
             field.access(), //~ ERROR the type of this value must be known in this context
     }
 }
diff --git a/src/test/compile-fail/issue-7867.rs b/src/test/compile-fail/issue-7867.rs
index e459a243cc8..0e81ec19c81 100644
--- a/src/test/compile-fail/issue-7867.rs
+++ b/src/test/compile-fail/issue-7867.rs
@@ -14,14 +14,27 @@ mod foo { pub fn bar() {} }
 
 fn main() {
     match (true, false) {
-        A::B => (), //~ ERROR expected `(bool, bool)`, found `A` (expected tuple, found enum A)
+        A::B => (),
+        //~^ ERROR mismatched types
+        //~| expected `(bool, bool)`
+        //~| found `A`
+        //~| expected tuple
+        //~| found enum `A`
         _ => ()
     }
 
     match &Some(42is) {
-        Some(x) => (), //~ ERROR expected `&core::option::Option<isize>`,
-                       //        found `core::option::Option<_>`
-        None => ()     //~ ERROR expected `&core::option::Option<isize>`,
-                       //        found `core::option::Option<_>`
+        Some(x) => (),
+        //~^ ERROR mismatched types
+        //~| expected `&core::option::Option<isize>`
+        //~| found `core::option::Option<_>`
+        //~| expected &-ptr
+        //~| found enum `core::option::Option`
+        None => ()
+        //~^ ERROR mismatched types
+        //~| expected `&core::option::Option<isize>`
+        //~| found `core::option::Option<_>`
+        //~| expected &-ptr
+        //~| found enum `core::option::Option`
     }
 }
diff --git a/src/test/compile-fail/issue-8761.rs b/src/test/compile-fail/issue-8761.rs
index 3f9e92afba2..30e4ec8ad0e 100644
--- a/src/test/compile-fail/issue-8761.rs
+++ b/src/test/compile-fail/issue-8761.rs
@@ -10,9 +10,17 @@
 
 enum Foo {
     A = 1i64,
-    //~^ ERROR mismatched types: expected `isize`, found `i64`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `i64`
+    //~| expected isize
+    //~| found i64
     B = 2u8
-    //~^ ERROR mismatched types: expected `isize`, found `u8`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `u8`
+    //~| expected isize
+    //~| found u8
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/kindck-nonsendable-1.rs b/src/test/compile-fail/kindck-nonsendable-1.rs
index 79aec386d9a..5bc769f8e11 100644
--- a/src/test/compile-fail/kindck-nonsendable-1.rs
+++ b/src/test/compile-fail/kindck-nonsendable-1.rs
@@ -19,6 +19,5 @@ fn main() {
     let x = Rc::new(3us);
     bar(move|| foo(x));
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
 
diff --git a/src/test/compile-fail/lint-ctypes.rs b/src/test/compile-fail/lint-ctypes.rs
index 801f9dfd1cf..5706453a220 100644
--- a/src/test/compile-fail/lint-ctypes.rs
+++ b/src/test/compile-fail/lint-ctypes.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![deny(improper_ctypes)]
+#![allow(unstable)]
 
 extern crate libc;
 
diff --git a/src/test/compile-fail/lint-dead-code-1.rs b/src/test/compile-fail/lint-dead-code-1.rs
index 34c79be7118..ceba33360d9 100644
--- a/src/test/compile-fail/lint-dead-code-1.rs
+++ b/src/test/compile-fail/lint-dead-code-1.rs
@@ -13,6 +13,7 @@
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 #![allow(missing_copy_implementations)]
+#![allow(unstable)]
 #![deny(dead_code)]
 
 #![crate_type="lib"]
diff --git a/src/test/compile-fail/lint-dead-code-3.rs b/src/test/compile-fail/lint-dead-code-3.rs
index 03b89c522ce..89ab78968d0 100644
--- a/src/test/compile-fail/lint-dead-code-3.rs
+++ b/src/test/compile-fail/lint-dead-code-3.rs
@@ -10,6 +10,7 @@
 
 #![allow(unused_variables)]
 #![allow(non_camel_case_types)]
+#![allow(unstable)]
 #![deny(dead_code)]
 
 #![crate_type="lib"]
diff --git a/src/test/compile-fail/lint-dead-code-4.rs b/src/test/compile-fail/lint-dead-code-4.rs
index ac8f158f8fb..3221be220d9 100644
--- a/src/test/compile-fail/lint-dead-code-4.rs
+++ b/src/test/compile-fail/lint-dead-code-4.rs
@@ -10,6 +10,7 @@
 
 #![allow(unused_variables)]
 #![allow(non_camel_case_types)]
+#![allow(unstable)]
 #![deny(dead_code)]
 
 extern crate libc;
diff --git a/src/test/compile-fail/lint-exceeding-bitshifts.rs b/src/test/compile-fail/lint-exceeding-bitshifts.rs
index 91a4d0fea0a..4c880eda099 100644
--- a/src/test/compile-fail/lint-exceeding-bitshifts.rs
+++ b/src/test/compile-fail/lint-exceeding-bitshifts.rs
@@ -10,6 +10,7 @@
 
 #![deny(exceeding_bitshifts)]
 #![allow(unused_variables)]
+#![allow(unstable)]
 #![allow(dead_code)]
 
 fn main() {
diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs
index c9d34d40479..ae156356b79 100644
--- a/src/test/compile-fail/lint-unused-extern-crate.rs
+++ b/src/test/compile-fail/lint-unused-extern-crate.rs
@@ -12,6 +12,7 @@
 
 #![deny(unused_extern_crates)]
 #![allow(unused_variables)]
+#![allow(unstable)]
 
 extern crate libc; //~ ERROR: unused extern crate
 
diff --git a/src/test/compile-fail/lint-uppercase-variables.rs b/src/test/compile-fail/lint-uppercase-variables.rs
index 9317e465a7a..d9f899ede04 100644
--- a/src/test/compile-fail/lint-uppercase-variables.rs
+++ b/src/test/compile-fail/lint-uppercase-variables.rs
@@ -11,6 +11,7 @@
 // ignore-tidy-linelength
 
 #![allow(dead_code)]
+#![allow(unstable)]
 #![deny(non_snake_case)]
 
 use std::io::File;
diff --git a/src/test/compile-fail/liveness-unused.rs b/src/test/compile-fail/liveness-unused.rs
index c9f8230b6c5..f27ee376f52 100644
--- a/src/test/compile-fail/liveness-unused.rs
+++ b/src/test/compile-fail/liveness-unused.rs
@@ -10,6 +10,7 @@
 
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
+#![allow(unstable)]
 #![allow(dead_code, non_camel_case_types)]
 
 fn f1(x: isize) {
diff --git a/src/test/compile-fail/match-struct.rs b/src/test/compile-fail/match-struct.rs
index e3b47372a4f..5bda3789687 100644
--- a/src/test/compile-fail/match-struct.rs
+++ b/src/test/compile-fail/match-struct.rs
@@ -14,7 +14,12 @@ enum E { C(isize) }
 
 fn main() {
     match (S { a: 1 }) {
-        E::C(_) => (), //~ ERROR mismatched types: expected `S`, found `E`
+        E::C(_) => (),
+        //~^ ERROR mismatched types
+        //~| expected `S`
+        //~| found `E`
+        //~| expected struct `S`
+        //~| found enum `E`
         _ => ()
     }
 }
diff --git a/src/test/compile-fail/match-vec-mismatch-2.rs b/src/test/compile-fail/match-vec-mismatch-2.rs
index 6bb049f3ca5..a4abdf3ddfe 100644
--- a/src/test/compile-fail/match-vec-mismatch-2.rs
+++ b/src/test/compile-fail/match-vec-mismatch-2.rs
@@ -11,6 +11,10 @@
 fn main() {
     match () {
         [()] => { }
-//~^ ERROR mismatched types: expected `()`, found `&[_]` (expected (), found &-ptr)
+        //~^ ERROR mismatched types
+        //~| expected `()`
+        //~| found `&[_]`
+        //~| expected ()
+        //~| found &-ptr
     }
 }
diff --git a/src/test/compile-fail/method-self-arg-1.rs b/src/test/compile-fail/method-self-arg-1.rs
index 178b7319976..4d416ed42de 100644
--- a/src/test/compile-fail/method-self-arg-1.rs
+++ b/src/test/compile-fail/method-self-arg-1.rs
@@ -18,7 +18,19 @@ impl Foo {
 
 fn main() {
     let x = Foo;
-    Foo::bar(x); //~ERROR mismatched types: expected `&Foo`, found `Foo`
-    Foo::bar(&&x); //~ERROR mismatched types: expected `&Foo`, found `&&Foo`
-    Foo::bar(&42is); //~ERROR mismatched types: expected `&Foo`, found `&isize`
+    Foo::bar(x); //~  ERROR mismatched types
+                 //~| expected `&Foo`
+                 //~| found `Foo`
+                 //~| expected &-ptr
+                 //~| found struct `Foo`
+    Foo::bar(&&x); //~  ERROR mismatched types
+                   //~| expected `&Foo`
+                   //~| found `&&Foo`
+                   //~| expected struct `Foo`
+                   //~| found &-ptr
+    Foo::bar(&42is); //~  ERROR mismatched types
+                     //~| expected `&Foo`
+                     //~| found `&isize`
+                     //~| expected struct `Foo`
+                     //~| found isize
 }
diff --git a/src/test/compile-fail/mut-pattern-mismatched.rs b/src/test/compile-fail/mut-pattern-mismatched.rs
index 9f1d3d1fb39..a3d016d756f 100644
--- a/src/test/compile-fail/mut-pattern-mismatched.rs
+++ b/src/test/compile-fail/mut-pattern-mismatched.rs
@@ -13,12 +13,18 @@ fn main() {
 
     // (separate lines to ensure the spans are accurate)
 
-     let &_ //~ ERROR expected `&mut isize`, found `&_`
+     let &_ //~  ERROR mismatched types
+            //~| expected `&mut isize`
+            //~| found `&_`
+            //~| values differ in mutability
         = foo;
     let &mut _ = foo;
 
     let bar = &1is;
     let &_ = bar;
-    let &mut _ //~ ERROR expected `&isize`, found `&mut _`
+    let &mut _ //~  ERROR mismatched types
+               //~| expected `&isize`
+               //~| found `&mut _`
+               //~| values differ in mutability
          = bar;
 }
diff --git a/src/test/compile-fail/mutable-enum-indirect.rs b/src/test/compile-fail/mutable-enum-indirect.rs
index f90bb610d37..1657d602e24 100644
--- a/src/test/compile-fail/mutable-enum-indirect.rs
+++ b/src/test/compile-fail/mutable-enum-indirect.rs
@@ -11,13 +11,18 @@
 // Tests that an `&` pointer to something inherently mutable is itself
 // to be considered mutable.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-enum Foo { A(marker::NoSync) }
+use std::marker::Sync;
+
+struct NoSync;
+impl !Sync for NoSync {}
+
+enum Foo { A(NoSync) }
 
 fn bar<T: Sync>(_: T) {}
 
 fn main() {
-    let x = Foo::A(marker::NoSync);
+    let x = Foo::A(NoSync);
     bar(&x); //~ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/no-method-suggested-traits.rs b/src/test/compile-fail/no-method-suggested-traits.rs
new file mode 100644
index 00000000000..ba8121eb5cc
--- /dev/null
+++ b/src/test/compile-fail/no-method-suggested-traits.rs
@@ -0,0 +1,62 @@
+// 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.
+
+// aux-build:no_method_suggested_traits.rs
+
+extern crate no_method_suggested_traits;
+
+mod foo {
+    trait Bar {
+        fn method(&self) {}
+
+        fn method2(&self) {}
+    }
+
+    impl Bar for u32 {}
+
+    impl Bar for char {}
+}
+
+fn main() {
+    1u32.method();
+    //~^ HELP following traits are implemented but not in scope, perhaps add a `use` for one of them
+    //~^^ ERROR does not implement
+    //~^^^ HELP `foo::Bar`
+    //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
+
+    'a'.method();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
+    //~^^^ HELP `foo::Bar`
+
+    1i32.method();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait is implemented but not in scope, perhaps add a `use` for it:
+    //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
+
+    1u64.method();
+    //~^ ERROR does not implement
+    //~^^ HELP following traits define a method `method`, perhaps you need to implement one of them
+    //~^^^ HELP `foo::Bar`
+    //~^^^^ HELP `no_method_suggested_traits::foo::PubPub`
+    //~^^^^^ HELP `no_method_suggested_traits::reexport::Reexported`
+    //~^^^^^^ HELP `no_method_suggested_traits::bar::PubPriv`
+    //~^^^^^^^ HELP `no_method_suggested_traits::qux::PrivPub`
+    //~^^^^^^^^ HELP `no_method_suggested_traits::quz::PrivPriv`
+
+    1u64.method2();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait defines a method `method2`, perhaps you need to implement it
+    //~^^^ HELP `foo::Bar`
+    1u64.method3();
+    //~^ ERROR does not implement
+    //~^^ HELP the following trait defines a method `method3`, perhaps you need to implement it
+    //~^^^ HELP `no_method_suggested_traits::foo::PubPub`
+}
diff --git a/src/test/compile-fail/no-send-res-ports.rs b/src/test/compile-fail/no-send-res-ports.rs
index 551953af135..52335ab76bd 100644
--- a/src/test/compile-fail/no-send-res-ports.rs
+++ b/src/test/compile-fail/no-send-res-ports.rs
@@ -37,7 +37,6 @@ fn main() {
 
     Thread::spawn(move|| {
         //~^ ERROR `core::marker::Send` is not implemented
-        //~^^ ERROR `core::marker::Send` is not implemented
         let y = x;
         println!("{:?}", y);
     });
diff --git a/src/test/compile-fail/no-type-for-node-ice.rs b/src/test/compile-fail/no-type-for-node-ice.rs
new file mode 100644
index 00000000000..aab4db6eadf
--- /dev/null
+++ b/src/test/compile-fail/no-type-for-node-ice.rs
@@ -0,0 +1,15 @@
+// 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.
+
+// Related issues: #20401, #20506, #20614, #20752, #20829, #20846, #20885, #20886
+
+fn main() {
+    "".homura[""]; //~ ERROR no field with that name was found
+}
diff --git a/src/test/compile-fail/no_send-enum.rs b/src/test/compile-fail/no_send-enum.rs
index cf1f13e8bb8..625d51260c4 100644
--- a/src/test/compile-fail/no_send-enum.rs
+++ b/src/test/compile-fail/no_send-enum.rs
@@ -8,16 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct NoSend;
+impl !Send for NoSend {}
 
 enum Foo {
-    A(marker::NoSend)
+    A(NoSend)
 }
 
 fn bar<T: Send>(_: T) {}
 
 fn main() {
-    let x = Foo::A(marker::NoSend);
+    let x = Foo::A(NoSend);
     bar(x);
     //~^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/no_send-rc.rs b/src/test/compile-fail/no_send-rc.rs
index 82cc319466a..d404988bd98 100644
--- a/src/test/compile-fail/no_send-rc.rs
+++ b/src/test/compile-fail/no_send-rc.rs
@@ -16,5 +16,4 @@ fn main() {
     let x = Rc::new(5is);
     bar(x);
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/no_send-struct.rs b/src/test/compile-fail/no_send-struct.rs
index bef70523787..7f16db0ba94 100644
--- a/src/test/compile-fail/no_send-struct.rs
+++ b/src/test/compile-fail/no_send-struct.rs
@@ -8,17 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
 
 struct Foo {
     a: isize,
-    ns: marker::NoSend
 }
 
+impl !Send for Foo {}
+
 fn bar<T: Send>(_: T) {}
 
 fn main() {
-    let x = Foo { a: 5, ns: marker::NoSend };
+    let x = Foo { a: 5 };
     bar(x);
     //~^ ERROR the trait `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/no_share-enum.rs b/src/test/compile-fail/no_share-enum.rs
index 33222eef44e..9331afdbbb5 100644
--- a/src/test/compile-fail/no_share-enum.rs
+++ b/src/test/compile-fail/no_share-enum.rs
@@ -8,14 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-enum Foo { A(marker::NoSync) }
+use std::marker::Sync;
+
+struct NoSync;
+impl !Sync for NoSync {}
+
+enum Foo { A(NoSync) }
 
 fn bar<T: Sync>(_: T) {}
 
 fn main() {
-    let x = Foo::A(marker::NoSync);
+    let x = Foo::A(NoSync);
     bar(x);
     //~^ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/no_share-rc.rs b/src/test/compile-fail/no_share-rc.rs
index 0d3e380d4a1..4917db602e1 100644
--- a/src/test/compile-fail/no_share-rc.rs
+++ b/src/test/compile-fail/no_share-rc.rs
@@ -17,5 +17,4 @@ fn main() {
     let x = Rc::new(RefCell::new(5is));
     bar(x);
     //~^ ERROR the trait `core::marker::Sync` is not implemented
-    //~^^ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/no_share-struct.rs b/src/test/compile-fail/no_share-struct.rs
index c7028ce9786..b5ccceb3b2a 100644
--- a/src/test/compile-fail/no_share-struct.rs
+++ b/src/test/compile-fail/no_share-struct.rs
@@ -8,14 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-struct Foo { a: isize, m: marker::NoSync }
+use std::marker::Sync;
+
+struct Foo { a: isize }
+impl !Sync for Foo {}
 
 fn bar<T: Sync>(_: T) {}
 
 fn main() {
-    let x = Foo { a: 5, m: marker::NoSync };
+    let x = Foo { a: 5 };
     bar(x);
     //~^ ERROR the trait `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/noexporttypeexe.rs b/src/test/compile-fail/noexporttypeexe.rs
index 8fa4e81c889..85a47492306 100644
--- a/src/test/compile-fail/noexporttypeexe.rs
+++ b/src/test/compile-fail/noexporttypeexe.rs
@@ -18,5 +18,9 @@ fn main() {
     // because the def_id associated with the type was
     // not convertible to a path.
   let x: isize = noexporttypelib::foo();
-    //~^ ERROR expected `isize`, found `core::option::Option<isize>`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `core::option::Option<isize>`
+    //~| expected isize
+    //~| found enum `core::option::Option`
 }
diff --git a/src/test/compile-fail/obsolete-tilde.rs b/src/test/compile-fail/obsolete-tilde.rs
deleted file mode 100644
index d290d5536a4..00000000000
--- a/src/test/compile-fail/obsolete-tilde.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that ~ pointers give an obsolescence message.
-
-fn foo(x: ~isize) {} //~ ERROR obsolete syntax: `~` notation for owned pointers
-fn bar(x: ~str) {} //~ ERROR obsolete syntax: `~` notation for owned pointers
-fn baz(x: ~[isize]) {} //~ ERROR obsolete syntax: `~[T]` is no longer a type
-
-fn main() {
-    let x = ~4is; //~ ERROR obsolete syntax: `~` notation for owned pointer allocation
-    let y = ~"hello"; //~ ERROR obsolete syntax: `~` notation for owned pointer allocation
-    let z = ~[1is, 2, 3]; //~ ERROR obsolete syntax: `~[T]` is no longer a type
-}
diff --git a/src/test/compile-fail/occurs-check-2.rs b/src/test/compile-fail/occurs-check-2.rs
index bfabcff5116..fd2903a85dd 100644
--- a/src/test/compile-fail/occurs-check-2.rs
+++ b/src/test/compile-fail/occurs-check-2.rs
@@ -14,5 +14,9 @@ fn main() {
     let f;
     let g;
     g = f;
-    f = box g; //~ ERROR cyclic type of infinite size
+    f = box g;
+    //~^  ERROR mismatched types
+    //~| expected `_`
+    //~| found `Box<_>`
+    //~| cyclic type of infinite size
 }
diff --git a/src/test/compile-fail/occurs-check.rs b/src/test/compile-fail/occurs-check.rs
index 417bd9b57ee..036fcc1b9d7 100644
--- a/src/test/compile-fail/occurs-check.rs
+++ b/src/test/compile-fail/occurs-check.rs
@@ -12,5 +12,9 @@
 
 fn main() {
     let f;
-    f = box f; //~ ERROR cyclic type of infinite size
+    f = box f;
+    //~^ ERROR mismatched types
+    //~| expected `_`
+    //~| found `Box<_>`
+    //~| cyclic type of infinite size
 }
diff --git a/src/test/compile-fail/on-unimplemented-bad-anno.rs b/src/test/compile-fail/on-unimplemented-bad-anno.rs
new file mode 100644
index 00000000000..dda534cc489
--- /dev/null
+++ b/src/test/compile-fail/on-unimplemented-bad-anno.rs
@@ -0,0 +1,37 @@
+// 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.
+// ignore-tidy-linelength
+
+#![feature(on_unimplemented)]
+
+#![allow(unused)]
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
+trait Foo<Bar, Baz, Quux>{}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Build a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+#[rustc_on_unimplemented] //~ ERROR this attribute must have a value
+trait BadAnnotation1 {}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
+//~^ ERROR there is no type parameter C on trait BadAnnotation2
+trait BadAnnotation2<A,B> {}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
+//~^ only named substitution parameters are allowed
+trait BadAnnotation3<A,B> {}
+
+pub fn main() {
+}
diff --git a/src/test/compile-fail/on-unimplemented.rs b/src/test/compile-fail/on-unimplemented.rs
new file mode 100644
index 00000000000..7b406afcf1f
--- /dev/null
+++ b/src/test/compile-fail/on-unimplemented.rs
@@ -0,0 +1,38 @@
+// 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.
+// ignore-tidy-linelength
+
+#![feature(on_unimplemented)]
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
+trait Foo<Bar, Baz, Quux>{}
+
+fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+
+}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Build a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+    MyFromIterator::my_from_iter(it)
+}
+
+pub fn main() {
+    let x = vec!(1u8, 2, 3, 4);
+    let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
+    //~^ ERROR
+    //~^^ NOTE a collection of type `core::option::Option<collections::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
+    let x: String = foobar(); //~ ERROR
+    //~^ NOTE test error `collections::string::String` with `u8` `_` `u32`
+}
diff --git a/src/test/compile-fail/pattern-error-continue.rs b/src/test/compile-fail/pattern-error-continue.rs
index c288429dcda..aa7202574ab 100644
--- a/src/test/compile-fail/pattern-error-continue.rs
+++ b/src/test/compile-fail/pattern-error-continue.rs
@@ -30,9 +30,18 @@ fn main() {
     }
     match 'c' {
         S { .. } => (),
-        //~^ ERROR mismatched types: expected `char`, found `S` (expected char, found struct S)
+        //~^ ERROR mismatched types
+        //~| expected `char`
+        //~| found `S`
+        //~| expected char
+        //~| found struct `S`
 
         _ => ()
     }
-    f(true);            //~ ERROR mismatched types: expected `char`, found `bool`
+    f(true);
+    //~^ ERROR mismatched types
+    //~| expected `char`
+    //~| found `bool`
+    //~| expected char
+    //~| found bool
 }
diff --git a/src/test/compile-fail/pptypedef.rs b/src/test/compile-fail/pptypedef.rs
index e3c440d61ce..9e5081ed550 100644
--- a/src/test/compile-fail/pptypedef.rs
+++ b/src/test/compile-fail/pptypedef.rs
@@ -12,8 +12,16 @@ fn let_in<T, F>(x: T, f: F) where F: FnOnce(T) {}
 
 fn main() {
     let_in(3us, |i| { assert!(i == 3is); });
-    //~^ ERROR expected `usize`, found `isize`
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `isize`
+    //~| expected usize
+    //~| found isize
 
     let_in(3is, |i| { assert!(i == 3us); });
-    //~^ ERROR expected `isize`, found `usize`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `usize`
+    //~| expected isize
+    //~| found usize
 }
diff --git a/src/test/compile-fail/ptr-coercion.rs b/src/test/compile-fail/ptr-coercion.rs
index 392a803b0dd..463754b29c7 100644
--- a/src/test/compile-fail/ptr-coercion.rs
+++ b/src/test/compile-fail/ptr-coercion.rs
@@ -14,11 +14,20 @@
 pub fn main() {
     // *const -> *mut
     let x: *const isize = &42is;
-    let x: *mut isize = x; //~ERROR values differ in mutability
+    let x: *mut isize = x; //~  ERROR mismatched types
+                           //~| expected `*mut isize`
+                           //~| found `*const isize`
+                           //~| values differ in mutability
 
     // & -> *mut
-    let x: *mut isize = &42; //~ERROR values differ in mutability
+    let x: *mut isize = &42; //~  ERROR mismatched types
+                             //~| expected `*mut isize`
+                             //~| found `&isize`
+                             //~| values differ in mutability
 
     let x: *const isize = &42;
-    let x: *mut isize = x; //~ERROR values differ in mutability
+    let x: *mut isize = x; //~  ERROR mismatched types
+                           //~| expected `*mut isize`
+                           //~| found `*const isize`
+                           //~| values differ in mutability
 }
diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs
index 5028ec89972..a3c38dff6b0 100644
--- a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs
+++ b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs
@@ -16,15 +16,16 @@ struct Inv<'a> { // invariant w/r/t 'a
     x: &'a mut &'a isize
 }
 
-pub trait Foo<'a> {
+pub trait Foo<'a, 't> {
     fn no_bound<'b>(self, b: Inv<'b>);
     fn has_bound<'b:'a>(self, b: Inv<'b>);
     fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
-    fn wrong_bound2<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn another_bound<'x: 'a>(self, x: Inv<'x>);
 }
 
 
-impl<'a> Foo<'a> for &'a isize {
+impl<'a, 't> Foo<'a, 't> for &'a isize {
     fn no_bound<'b:'a>(self, b: Inv<'b>) {
         //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
     }
@@ -47,9 +48,10 @@ impl<'a> Foo<'a> for &'a isize {
         // cases.
     }
 
-    fn wrong_bound2<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
-        //~^ ERROR distinct set of bounds from its counterpart
+    fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
     }
+
+    fn another_bound<'x: 't>(self, x: Inv<'x>) {}
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/regions-bounds.rs b/src/test/compile-fail/regions-bounds.rs
index c26740c9598..7f2889a327b 100644
--- a/src/test/compile-fail/regions-bounds.rs
+++ b/src/test/compile-fail/regions-bounds.rs
@@ -16,11 +16,17 @@ struct an_enum<'a>(&'a isize);
 struct a_class<'a> { x:&'a isize }
 
 fn a_fn1<'a,'b>(e: an_enum<'a>) -> an_enum<'b> {
-    return e; //~ ERROR mismatched types: expected `an_enum<'b>`, found `an_enum<'a>`
+    return e; //~  ERROR mismatched types
+              //~| expected `an_enum<'b>`
+              //~| found `an_enum<'a>`
+              //~| lifetime mismatch
 }
 
 fn a_fn3<'a,'b>(e: a_class<'a>) -> a_class<'b> {
-    return e; //~ ERROR mismatched types: expected `a_class<'b>`, found `a_class<'a>`
+    return e; //~  ERROR mismatched types
+              //~| expected `a_class<'b>`
+              //~| found `a_class<'a>`
+              //~| lifetime mismatch
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/regions-early-bound-error-method.rs b/src/test/compile-fail/regions-early-bound-error-method.rs
index 9de0ed070c7..4a3ca01c849 100644
--- a/src/test/compile-fail/regions-early-bound-error-method.rs
+++ b/src/test/compile-fail/regions-early-bound-error-method.rs
@@ -27,7 +27,13 @@ impl<'a> GetRef<'a> for Box<'a> {
 
 impl<'a> Box<'a> {
     fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
-        g2.get() //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+        g2.get()
+        //~^ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+        //~| ERROR mismatched types
+        //~| expected `&'a isize`
+        //~| found `&'b isize`
+        //~| lifetime mismatch
+
     }
 }
 
diff --git a/src/test/compile-fail/regions-early-bound-error.rs b/src/test/compile-fail/regions-early-bound-error.rs
index 37b74aea539..57c8e3f1170 100644
--- a/src/test/compile-fail/regions-early-bound-error.rs
+++ b/src/test/compile-fail/regions-early-bound-error.rs
@@ -26,7 +26,12 @@ impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
 }
 
 fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
-    g1.get() //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+    g1.get()
+    //~^ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+    //~| ERROR mismatched types
+    //~| expected `&'b isize`
+    //~| found `&'a isize`
+    //~| lifetime mismatch
 }
 
 fn main() {
diff --git a/src/test/compile-fail/regions-fn-subtyping-return-static.rs b/src/test/compile-fail/regions-fn-subtyping-return-static.rs
index ac56e8ce14d..ebf7ca289f8 100644
--- a/src/test/compile-fail/regions-fn-subtyping-return-static.rs
+++ b/src/test/compile-fail/regions-fn-subtyping-return-static.rs
@@ -53,7 +53,12 @@ fn supply_F() {
 fn supply_G() {
     want_G(foo);
     want_G(bar);
-    want_G(baz); //~ ERROR expected concrete lifetime
+    want_G(baz);
+    //~^ ERROR mismatched types
+    //~| expected `fn(&'cx S) -> &'static S`
+    //~| found `fn(&S) -> &S {baz}`
+    //~| expected concrete lifetime
+    //~| found bound lifetime parameter 'cx
 }
 
 pub fn main() {
diff --git a/src/test/compile-fail/regions-infer-paramd-indirect.rs b/src/test/compile-fail/regions-infer-paramd-indirect.rs
index 0d441380e81..1d32e8fe7b2 100644
--- a/src/test/compile-fail/regions-infer-paramd-indirect.rs
+++ b/src/test/compile-fail/regions-infer-paramd-indirect.rs
@@ -31,7 +31,10 @@ impl<'a> set_f<'a> for c<'a> {
 
     fn set_f_bad(&mut self, b: Box<b>) {
         self.f = b;
-        //~^ ERROR mismatched types: expected `Box<Box<&'a isize>>`, found `Box<Box<&isize>>`
+        //~^ ERROR mismatched types
+        //~| expected `Box<Box<&'a isize>>`
+        //~| found `Box<Box<&isize>>`
+        //~| lifetime mismatch
     }
 }
 
diff --git a/src/test/compile-fail/repeat_count.rs b/src/test/compile-fail/repeat_count.rs
index e94bf19955b..df69e13bf1e 100644
--- a/src/test/compile-fail/repeat_count.rs
+++ b/src/test/compile-fail/repeat_count.rs
@@ -14,14 +14,33 @@ fn main() {
     let n = 1;
     let a = [0; n]; //~ ERROR expected constant integer for repeat count, found variable
     let b = [0; ()];
-//~^ ERROR expected constant integer for repeat count, found non-constant expression
-//~^^ ERROR: expected `usize`, found `()`
-    let c = [0; true]; //~ ERROR expected positive integer for repeat count, found boolean
-    //~^ ERROR: expected `usize`, found `bool`
-    let d = [0; 0.5]; //~ ERROR expected positive integer for repeat count, found float
-    //~^ ERROR: expected `usize`, found `_`
-    let e = [0; "foo"]; //~ ERROR expected positive integer for repeat count, found string
-    //~^ ERROR: expected `usize`, found `&'static str`
+//~^ ERROR mismatched types
+//~| expected `usize`
+//~| found `()`
+//~| expected usize
+//~| found ()
+//~| ERROR expected constant integer for repeat count, found non-constant expression
+    let c = [0; true];
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `bool`
+    //~| expected usize
+    //~| found bool
+    //~| ERROR expected positive integer for repeat count, found boolean
+    let d = [0; 0.5];
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `_`
+    //~| expected usize
+    //~| found floating-point variable
+    //~| ERROR expected positive integer for repeat count, found float
+    let e = [0; "foo"];
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `&'static str`
+    //~| expected usize
+    //~| found &-ptr
+    //~| ERROR expected positive integer for repeat count, found string
     let f = [0; -4];
     //~^ ERROR expected positive integer for repeat count, found negative integer
     let f = [0us; -1];
diff --git a/src/test/compile-fail/shift-various-bad-types.rs b/src/test/compile-fail/shift-various-bad-types.rs
index 41788584049..66aef0ec3a1 100644
--- a/src/test/compile-fail/shift-various-bad-types.rs
+++ b/src/test/compile-fail/shift-various-bad-types.rs
@@ -36,7 +36,11 @@ fn foo(p: &Panolpy) {
 
     // Type of the result follows the LHS, not the RHS:
     let _: i32 = 22_i64 >> 1_i32;
-    //~^ ERROR mismatched types: expected `i32`, found `i64`
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i64`
+    //~| expected i32
+    //~| found i64)
 }
 
 fn main() {
diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
index a655a17c037..1203d622348 100644
--- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
+++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs
@@ -13,7 +13,11 @@ struct Foo<T,U>(T);
 fn main() {
     match Foo(1.1) {
         1 => {}
-    //~^ ERROR expected `Foo<_, _>`, found `_`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<_, _>`
+    //~| found `_`
+    //~| expected struct `Foo`
+    //~| found integral variable
     }
 
 }
diff --git a/src/test/compile-fail/std-uncopyable-atomics.rs b/src/test/compile-fail/std-uncopyable-atomics.rs
index f27fa6470a6..9807fc43140 100644
--- a/src/test/compile-fail/std-uncopyable-atomics.rs
+++ b/src/test/compile-fail/std-uncopyable-atomics.rs
@@ -17,9 +17,9 @@ use std::ptr;
 fn main() {
     let x = ATOMIC_BOOL_INIT;
     let x = *&x; //~ ERROR: cannot move out of borrowed content
-    let x = ATOMIC_INT_INIT;
+    let x = ATOMIC_ISIZE_INIT;
     let x = *&x; //~ ERROR: cannot move out of borrowed content
-    let x = ATOMIC_UINT_INIT;
+    let x = ATOMIC_USIZE_INIT;
     let x = *&x; //~ ERROR: cannot move out of borrowed content
     let x: AtomicPtr<usize> = AtomicPtr::new(ptr::null_mut());
     let x = *&x; //~ ERROR: cannot move out of borrowed content
diff --git a/src/test/compile-fail/struct-base-wrong-type.rs b/src/test/compile-fail/struct-base-wrong-type.rs
index 2bb8d32a7e3..71a2b50b612 100644
--- a/src/test/compile-fail/struct-base-wrong-type.rs
+++ b/src/test/compile-fail/struct-base-wrong-type.rs
@@ -12,11 +12,27 @@ struct Foo { a: isize, b: isize }
 struct Bar { x: isize }
 
 static bar: Bar = Bar { x: 5 };
-static foo: Foo = Foo { a: 2, ..bar }; //~ ERROR mismatched types: expected `Foo`, found `Bar`
-static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
+static foo: Foo = Foo { a: 2, ..bar }; //~  ERROR mismatched types
+                                       //~| expected `Foo`
+                                       //~| found `Bar`
+                                       //~| expected struct `Foo`
+                                       //~| found struct `Bar`
+static foo_i: Foo = Foo { a: 2, ..4 }; //~  ERROR mismatched types
+                                       //~| expected `Foo`
+                                       //~| found `_`
+                                       //~| expected struct `Foo`
+                                       //~| found integral variable
 
 fn main() {
     let b = Bar { x: 5 };
-    let f = Foo { a: 2, ..b }; //~ ERROR mismatched types: expected `Foo`, found `Bar`
-    let f_i = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
+    let f = Foo { a: 2, ..b }; //~  ERROR mismatched types
+                               //~| expected `Foo`
+                               //~| found `Bar`
+                               //~| expected struct `Foo`
+                               //~| found struct `Bar`
+    let f_i = Foo { a: 2, ..4 }; //~  ERROR mismatched types
+                                 //~| expected `Foo`
+                                 //~| found `_`
+                                 //~| expected struct `Foo`
+                                 //~| found integral variable
 }
diff --git a/src/test/compile-fail/structure-constructor-type-mismatch.rs b/src/test/compile-fail/structure-constructor-type-mismatch.rs
index fb84c1e2ebe..a22f390499f 100644
--- a/src/test/compile-fail/structure-constructor-type-mismatch.rs
+++ b/src/test/compile-fail/structure-constructor-type-mismatch.rs
@@ -24,25 +24,33 @@ type PairF<U> = Pair<f32,U>;
 
 fn main() {
     let pt = PointF {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 1is,
         y: 2is,
     };
 
     let pt2 = Point::<f32> {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 3is,
         y: 4is,
     };
 
     let pair = PairF {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 5is,
         y: 6is,
     };
 
     let pair2 = PairF::<isize> {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 7is,
         y: 8is,
     };
diff --git a/src/test/compile-fail/suppressed-error.rs b/src/test/compile-fail/suppressed-error.rs
index 27f50be528c..44de5d8cfe3 100644
--- a/src/test/compile-fail/suppressed-error.rs
+++ b/src/test/compile-fail/suppressed-error.rs
@@ -10,6 +10,10 @@
 
 fn main() {
     let (x, y) = ();
-//~^ ERROR expected `()`, found `(_, _)` (expected (), found tuple)
+//~^ ERROR mismatched types
+//~| expected `()`
+//~| found `(_, _)`
+//~| expected ()
+//~| found tuple
     return x;
 }
diff --git a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
index a9df449032e..660c1fa9a88 100644
--- a/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
+++ b/src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `char`, found
 // Issue #876
 
 #![no_implicit_prelude]
@@ -21,4 +20,9 @@ fn last<T>(v: Vec<&T> ) -> std::option::Option<T> {
 fn main() {
     let y;
     let x : char = last(y);
+    //~^ ERROR mismatched types
+    //~| expected `char`
+    //~| found `core::option::Option<_>`
+    //~| expected char
+    //~| found enum `core::option::Option`
 }
diff --git a/src/test/compile-fail/task-rng-isnt-sendable.rs b/src/test/compile-fail/task-rng-isnt-sendable.rs
index fe31d81983e..dc3385f4bb9 100644
--- a/src/test/compile-fail/task-rng-isnt-sendable.rs
+++ b/src/test/compile-fail/task-rng-isnt-sendable.rs
@@ -17,5 +17,4 @@ fn test_send<S: Send>() {}
 pub fn main() {
     test_send::<rand::ThreadRng>();
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/terr-in-field.rs b/src/test/compile-fail/terr-in-field.rs
index 1e5422a798e..60db35b879f 100644
--- a/src/test/compile-fail/terr-in-field.rs
+++ b/src/test/compile-fail/terr-in-field.rs
@@ -20,7 +20,11 @@ struct bar {
 
 fn want_foo(f: foo) {}
 fn have_bar(b: bar) {
-    want_foo(b); //~ ERROR (expected struct foo, found struct bar)
+    want_foo(b); //~  ERROR mismatched types
+                 //~| expected `foo`
+                 //~| found `bar`
+                 //~| expected struct `foo`
+                 //~| found struct `bar`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/terr-sorts.rs b/src/test/compile-fail/terr-sorts.rs
index d1a37c99c47..231d2366b48 100644
--- a/src/test/compile-fail/terr-sorts.rs
+++ b/src/test/compile-fail/terr-sorts.rs
@@ -18,7 +18,11 @@ type bar = Box<foo>;
 
 fn want_foo(f: foo) {}
 fn have_bar(b: bar) {
-    want_foo(b); //~ ERROR (expected struct foo, found box)
+    want_foo(b); //~  ERROR mismatched types
+                 //~| expected `foo`
+                 //~| found `Box<foo>`
+                 //~| expected struct `foo`
+                 //~| found box
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs
index 4f405e2558d..79174552ae0 100644
--- a/src/test/compile-fail/trait-bounds-cant-coerce.rs
+++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs
@@ -20,7 +20,11 @@ fn c(x: Box<Foo+Sync+Send>) {
 }
 
 fn d(x: Box<Foo>) {
-    a(x); //~ ERROR found no bounds
+    a(x); //~  ERROR mismatched types
+          //~| expected `Box<Foo + Send>`
+          //~| found `Box<Foo>`
+          //~| expected bounds `Send`
+          //~| found no bounds
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs
index 5fc80d5660d..477bd4f5be9 100644
--- a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs
+++ b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs
@@ -32,15 +32,15 @@ trait Foo {
 impl Foo for isize {
     // invalid bound for T, was defined as Eq in trait
     fn test_error1_fn<T: Ord>(&self) {}
-    //~^ ERROR in method `test_error1_fn`, type parameter 0 requires bound `core::cmp::Ord`
+    //~^ ERROR the requirement `T : core::cmp::Ord` appears on the impl
 
     // invalid bound for T, was defined as Eq + Ord in trait
     fn test_error2_fn<T: Eq + B>(&self) {}
-    //~^ ERROR in method `test_error2_fn`, type parameter 0 requires bound `B`
+    //~^ ERROR the requirement `T : B` appears on the impl
 
     // invalid bound for T, was defined as Eq + Ord in trait
     fn test_error3_fn<T: B + Eq>(&self) {}
-    //~^ ERROR in method `test_error3_fn`, type parameter 0 requires bound `B`
+    //~^ ERROR the requirement `T : B` appears on the impl
 
     // multiple bounds, same order as in trait
     fn test3_fn<T: Ord + Eq>(&self) {}
@@ -50,16 +50,16 @@ impl Foo for isize {
 
     // parameters in impls must be equal or more general than in the defining trait
     fn test_error5_fn<T: B>(&self) {}
-    //~^ ERROR in method `test_error5_fn`, type parameter 0 requires bound `B`
+    //~^ ERROR the requirement `T : B` appears on the impl
 
     // bound `std::cmp::Eq` not enforced by this implementation, but this is OK
     fn test6_fn<T: A>(&self) {}
 
     fn test_error7_fn<T: A + Eq>(&self) {}
-    //~^ ERROR in method `test_error7_fn`, type parameter 0 requires bound `core::cmp::Eq`
+    //~^ ERROR the requirement `T : core::cmp::Eq` appears on the impl
 
     fn test_error8_fn<T: C>(&self) {}
-    //~^ ERROR in method `test_error8_fn`, type parameter 0 requires bound `C`
+    //~^ ERROR the requirement `T : C` appears on the impl
 }
 
 
@@ -71,8 +71,7 @@ trait Trait {
 
 impl Trait for usize {
     fn method<G: Getter<usize>>() {}
-    //~^ ERROR in method `method`, type parameter 0 requires bound `Getter<usize>`
+    //~^ G : Getter<usize>` appears on the impl method but not on the corresponding trait method
 }
 
 fn main() {}
-
diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs
index a970a86408e..8ad19116e7b 100644
--- a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs
+++ b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs
@@ -20,7 +20,7 @@ trait IteratorUtil<A> {
 
 impl<A, T: Iterator<A>> IteratorUtil<A> for T {
     fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
-    //~^ ERROR in method `zip`, type parameter 1 requires bound `Iterator<B>`
+    //~^ ERROR the requirement `U : Iterator<B>` appears on the impl method
         ZipIterator{a: self, b: other}
     }
 }
diff --git a/src/test/compile-fail/traits-negative-impls.rs b/src/test/compile-fail/traits-negative-impls.rs
new file mode 100644
index 00000000000..3ef760053c7
--- /dev/null
+++ b/src/test/compile-fail/traits-negative-impls.rs
@@ -0,0 +1,58 @@
+// 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.
+
+// The dummy functions are used to avoid adding new cfail files.
+// What happens is that the compiler attempts to squash duplicates and some
+// errors are not reported. This way, we make sure that, for each function, different
+// typeck phases are involved and all errors are reported.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct Outer<T: Send>(T);
+
+struct TestType;
+impl !Send for TestType {}
+
+struct Outer2<T>(T);
+
+unsafe impl<T: Send> Sync for Outer2<T> {}
+
+fn is_send<T: Send>(_: T) {}
+fn is_sync<T: Sync>(_: T) {}
+
+fn dummy() {
+    Outer(TestType);
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+
+    is_send(TestType);
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+
+    is_send((8, TestType));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
+
+fn dummy2() {
+    is_send(Box::new(TestType));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
+
+fn dummy3() {
+    is_send(Box::new(Outer2(TestType)));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
+
+fn main() {
+    // This will complain about a missing Send impl because `Sync` is implement *just*
+    // for T that are `Send`. Look at #20366 and #19950
+    is_sync(Outer2(TestType));
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `TestType`
+}
diff --git a/src/test/compile-fail/tuple-arity-mismatch.rs b/src/test/compile-fail/tuple-arity-mismatch.rs
index 7f073a7bfdb..8ad9ca50e30 100644
--- a/src/test/compile-fail/tuple-arity-mismatch.rs
+++ b/src/test/compile-fail/tuple-arity-mismatch.rs
@@ -14,8 +14,16 @@ fn first((value, _): (isize, f64)) -> isize { value }
 
 fn main() {
     let y = first ((1,2.0,3));
-    //~^ ERROR expected a tuple with 2 elements, found one with 3 elements
+    //~^ ERROR mismatched types
+    //~| expected `(isize, f64)`
+    //~| found `(isize, f64, _)`
+    //~| expected a tuple with 2 elements
+    //~| found one with 3 elements
 
     let y = first ((1,));
-    //~^ ERROR expected `(isize, f64)`, found `(isize,)`
+    //~^ ERROR mismatched types
+    //~| expected `(isize, f64)`
+    //~| found `(isize,)`
+    //~| expected a tuple with 2 elements
+    //~| found one with 1 elements
 }
diff --git a/src/test/compile-fail/tutorial-suffix-inference-test.rs b/src/test/compile-fail/tutorial-suffix-inference-test.rs
index 1b44c7e8128..c8c596fdb4f 100644
--- a/src/test/compile-fail/tutorial-suffix-inference-test.rs
+++ b/src/test/compile-fail/tutorial-suffix-inference-test.rs
@@ -17,9 +17,17 @@ fn main() {
 
     identity_u8(x);  // after this, `x` is assumed to have type `u8`
     identity_u16(x);
-    //~^ ERROR mismatched types: expected `u16`, found `u8`
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u8`
+    //~| expected u16
+    //~| found u8
     identity_u16(y);
-    //~^ ERROR mismatched types: expected `u16`, found `i32`
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `i32`
+    //~| expected u16
+    //~| found i32
 
     let a = 3is;
 
@@ -27,6 +35,10 @@ fn main() {
 
     identity_i(a); // ok
     identity_u16(a);
-    //~^ ERROR mismatched types: expected `u16`, found `isize`
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `isize`
+    //~| expected u16
+    //~| found isize
 
 }
diff --git a/src/test/compile-fail/type-mismatch-multiple.rs b/src/test/compile-fail/type-mismatch-multiple.rs
index 8b0897565fb..4ab6bd53191 100644
--- a/src/test/compile-fail/type-mismatch-multiple.rs
+++ b/src/test/compile-fail/type-mismatch-multiple.rs
@@ -9,7 +9,15 @@
 // except according to those terms.
 
 // Checking that the compiler reports multiple type errors at once
-// error-pattern:mismatched types: expected `bool`
-// error-pattern:mismatched types: expected `isize`
 
 fn main() { let a: bool = 1is; let b: isize = true; }
+//~^ ERROR mismatched types
+//~| expected `bool`
+//~| found `isize`
+//~| expected bool
+//~| found isize
+//~| ERROR mismatched types
+//~| expected `isize`
+//~| found `bool`
+//~| expected isize
+//~| found bool
diff --git a/src/test/compile-fail/type-parameter-names.rs b/src/test/compile-fail/type-parameter-names.rs
index 42691fa5229..408bf72e97c 100644
--- a/src/test/compile-fail/type-parameter-names.rs
+++ b/src/test/compile-fail/type-parameter-names.rs
@@ -13,7 +13,11 @@
 
 fn foo<Foo, Bar>(x: Foo) -> Bar {
     x
-//~^ ERROR expected `Bar`, found `Foo` (expected type parameter, found a different type parameter)
+//~^ ERROR mismatched types
+//~| expected `Bar`
+//~| found `Foo`
+//~| expected type parameter
+//~| found a different type parameter
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/type-params-in-different-spaces-1.rs b/src/test/compile-fail/type-params-in-different-spaces-1.rs
index 66479202e12..de9623de7cd 100644
--- a/src/test/compile-fail/type-params-in-different-spaces-1.rs
+++ b/src/test/compile-fail/type-params-in-different-spaces-1.rs
@@ -12,7 +12,11 @@ use std::num::Int;
 
 trait BrokenAdd: Int {
     fn broken_add<T>(&self, rhs: T) -> Self {
-        *self + rhs //~ ERROR expected `Self`, found `T`
+        *self + rhs //~  ERROR mismatched types
+                    //~| expected `Self`
+                    //~| found `T`
+                    //~| expected Self
+                    //~| found type parameter
     }
 }
 
diff --git a/src/test/compile-fail/typeck-negative-impls-builtin.rs b/src/test/compile-fail/typeck-negative-impls-builtin.rs
new file mode 100644
index 00000000000..9da79b11cf0
--- /dev/null
+++ b/src/test/compile-fail/typeck-negative-impls-builtin.rs
@@ -0,0 +1,20 @@
+// 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.
+
+#![feature(optin_builtin_traits)]
+
+struct TestType;
+
+trait TestTrait {}
+
+impl !TestTrait for TestType {}
+//~^ ERROR  negative impls are currently allowed just for `Send` and `Sync`
+
+fn main() {}
diff --git a/src/test/compile-fail/typeck-unsafe-always-share.rs b/src/test/compile-fail/typeck-unsafe-always-share.rs
index a9113c6e99f..38e3b576348 100644
--- a/src/test/compile-fail/typeck-unsafe-always-share.rs
+++ b/src/test/compile-fail/typeck-unsafe-always-share.rs
@@ -10,29 +10,26 @@
 
 // Verify that UnsafeCell is *always* sync regardless if `T` is sync.
 
-// ignore-tidy-linelength
+#![feature(optin_builtin_traits)]
 
 use std::cell::UnsafeCell;
-use std::marker;
+use std::marker::Sync;
 
 struct MySync<T> {
     u: UnsafeCell<T>
 }
 
-struct NoSync {
-    m: marker::NoSync
-}
-
-fn test<T: Sync>(s: T){
+struct NoSync;
+impl !Sync for NoSync {}
 
-}
+fn test<T: Sync>(s: T) {}
 
 fn main() {
     let us = UnsafeCell::new(MySync{u: UnsafeCell::new(0is)});
     test(us);
     //~^ ERROR `core::marker::Sync` is not implemented
 
-    let uns = UnsafeCell::new(NoSync{m: marker::NoSync});
+    let uns = UnsafeCell::new(NoSync);
     test(uns);
     //~^ ERROR `core::marker::Sync` is not implemented
 
@@ -40,7 +37,6 @@ fn main() {
     test(ms);
     //~^ ERROR `core::marker::Sync` is not implemented
 
-    let ns = NoSync{m: marker::NoSync};
-    test(ns);
+    test(NoSync);
     //~^ ERROR `core::marker::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs
index 92740cf5082..a34be63ba6b 100644
--- a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs
+++ b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs
@@ -19,11 +19,19 @@ pub fn main() {
 
 fn test1() {
     let x: Foo<_> = Bar::<usize>;
-    //~^ ERROR mismatched types: expected `Foo<_>`, found `Bar<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<_>`
+    //~| found `Bar<usize>`
+    //~| expected struct `Foo`
+    //~| found struct `Bar`
     let y: Foo<usize> = x;
 }
 
 fn test2() {
     let x: Foo<_> = Bar::<usize>;
-    //~^ ERROR mismatched types: expected `Foo<_>`, found `Bar<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<_>`
+    //~| found `Bar<usize>`
+    //~| expected struct `Foo`
+    //~| found struct `Bar`
 }
diff --git a/src/test/compile-fail/ufcs-explicit-self-bad.rs b/src/test/compile-fail/ufcs-explicit-self-bad.rs
index 6c323e8c1ae..cbcf31b5b7e 100644
--- a/src/test/compile-fail/ufcs-explicit-self-bad.rs
+++ b/src/test/compile-fail/ufcs-explicit-self-bad.rs
@@ -42,8 +42,15 @@ trait SomeTrait {
 impl<'a, T> SomeTrait for &'a Bar<T> {
     fn dummy1(self: &&'a Bar<T>) { }
     fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched self type
-    fn dummy3(self: &&Bar<T>) {} //~ ERROR lifetime mismatch
-    //~^ ERROR lifetime mismatch
+    fn dummy3(self: &&Bar<T>) {}
+    //~^ ERROR mismatched types
+    //~| expected `&'a Bar<T>`
+    //~| found `&Bar<T>`
+    //~| lifetime mismatch
+    //~| ERROR mismatched types
+    //~| expected `&'a Bar<T>`
+    //~| found `&Bar<T>`
+    //~| lifetime mismatch
 }
 
 fn main() {
diff --git a/src/test/compile-fail/vec-matching-obsolete-syntax.rs b/src/test/compile-fail/ufcs-qpath-missing-params.rs
index 2715b31d196..5fa66eb98e1 100644
--- a/src/test/compile-fail/vec-matching-obsolete-syntax.rs
+++ b/src/test/compile-fail/ufcs-qpath-missing-params.rs
@@ -8,15 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::borrow::IntoCow;
+
 fn main() {
-    let x = [1is, 2, 3];
-    match x {
-        [a, b, ..c] => {    //~ ERROR obsolete syntax
-            assert_eq!(a, 1);
-            assert_eq!(b, 2);
-            let expected: &[_] = &[3];
-            assert_eq!(c, expected);
-        }
-    }
+    <String as IntoCow>::into_cow("foo".to_string());
+    //~^ ERROR wrong number of type arguments: expected 2, found 0
 }
 
diff --git a/src/test/compile-fail/ufcs-qpath-self-mismatch.rs b/src/test/compile-fail/ufcs-qpath-self-mismatch.rs
new file mode 100644
index 00000000000..868c1eae4a9
--- /dev/null
+++ b/src/test/compile-fail/ufcs-qpath-self-mismatch.rs
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::Add;
+
+fn main() {
+    <i32 as Add<u32>>::add(1, 2);
+    //~^ ERROR the trait `core::ops::Add<u32>` is not implemented for the type `i32`
+    <i32 as Add<i32>>::add(1u32, 2);
+    //~^ ERROR mismatched types
+    <i32 as Add<i32>>::add(1, 2u32);
+    //~^ ERROR mismatched types
+}
+
diff --git a/src/test/compile-fail/unique-unique-kind.rs b/src/test/compile-fail/unique-unique-kind.rs
index 4b7f11b0560..322de45daf0 100644
--- a/src/test/compile-fail/unique-unique-kind.rs
+++ b/src/test/compile-fail/unique-unique-kind.rs
@@ -19,5 +19,4 @@ fn main() {
     let i = box Rc::new(100is);
     f(i);
     //~^ ERROR `core::marker::Send` is not implemented
-    //~^^ ERROR `core::marker::Send` is not implemented
 }
diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs
index abd93fdfc6c..f51eee37934 100644
--- a/src/test/compile-fail/unsendable-class.rs
+++ b/src/test/compile-fail/unsendable-class.rs
@@ -31,6 +31,5 @@ fn main() {
   let cat = "kitty".to_string();
   let (tx, _) = channel();
   //~^ ERROR `core::marker::Send` is not implemented
-  //~^^ ERROR `core::marker::Send` is not implemented
   tx.send(foo(42, Rc::new(cat)));
 }
diff --git a/src/test/compile-fail/unsupported-cast.rs b/src/test/compile-fail/unsupported-cast.rs
index 205c912f5a0..ca17c898ec3 100644
--- a/src/test/compile-fail/unsupported-cast.rs
+++ b/src/test/compile-fail/unsupported-cast.rs
@@ -14,5 +14,5 @@
 extern crate libc;
 
 fn main() {
-  println!("{}", 1.0 as *libc::FILE); // Can't cast float to foreign.
+  println!("{:?}", 1.0 as *const libc::FILE); // Can't cast float to foreign.
 }
diff --git a/src/test/compile-fail/unused-attr.rs b/src/test/compile-fail/unused-attr.rs
index 635ceec73a3..b04f2edd142 100644
--- a/src/test/compile-fail/unused-attr.rs
+++ b/src/test/compile-fail/unused-attr.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 #![deny(unused_attributes)]
 #![allow(dead_code, unused_imports)]
+#![allow(unstable)]
 
 #![foo] //~ ERROR unused attribute
 
diff --git a/src/test/compile-fail/variadic-ffi.rs b/src/test/compile-fail/variadic-ffi.rs
index 702702990c2..86271f670ce 100644
--- a/src/test/compile-fail/variadic-ffi.rs
+++ b/src/test/compile-fail/variadic-ffi.rs
@@ -24,14 +24,18 @@ fn main() {
         foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
 
         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
-        //~^ ERROR: mismatched types: expected `unsafe extern "C" fn(isize, u8)`
-        //         , found `unsafe extern "C" fn(isize, u8, ...)`
-        //          (expected non-variadic fn, found variadic function)
+        //~^ ERROR: mismatched types
+        //~| expected `unsafe extern "C" fn(isize, u8)`
+        //~| found `unsafe extern "C" fn(isize, u8, ...)`
+        //~| expected non-variadic fn
+        //~| found variadic function
 
         let y: unsafe extern "C" fn(f: isize, x: u8, ...) = bar;
-        //~^ ERROR: mismatched types: expected `unsafe extern "C" fn(isize, u8, ...)`
-        //         , found `extern "C" extern fn(isize, u8)`
-        //          (expected variadic fn, found non-variadic function)
+        //~^ ERROR: mismatched types
+        //~| expected `unsafe extern "C" fn(isize, u8, ...)`
+        //~| found `extern "C" fn(isize, u8) {bar}`
+        //~| expected variadic fn
+        //~| found non-variadic function
 
         foo(1, 2, 3f32); //~ ERROR: can't pass an f32 to variadic function, cast to c_double
         foo(1, 2, true); //~ ERROR: can't pass bool to variadic function, cast to c_int
diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs
index e6fbcf2d38f..21c249c0e1f 100644
--- a/src/test/compile-fail/wrong-mul-method-signature.rs
+++ b/src/test/compile-fail/wrong-mul-method-signature.rs
@@ -24,7 +24,7 @@ impl Mul<f64> for Vec1 {
     type Output = Vec1;
 
     fn mul(self, s: &f64) -> Vec1 {
-    //~^ ERROR: method `mul` has an incompatible type for trait: expected f64, found &-ptr
+    //~^ ERROR method `mul` has an incompatible type for trait
         Vec1 {
             x: self.x * *s
         }
@@ -41,7 +41,7 @@ impl Mul<Vec2> for Vec2 {
     type Output = f64;
 
     fn mul(self, s: f64) -> Vec2 {
-    //~^ ERROR: method `mul` has an incompatible type for trait: expected struct Vec2, found f64
+    //~^ ERROR method `mul` has an incompatible type for trait
         Vec2 {
             x: self.x * s,
             y: self.y * s
@@ -60,7 +60,7 @@ impl Mul<f64> for Vec3 {
     type Output = i32;
 
     fn mul(self, s: f64) -> f64 {
-    //~^ ERROR: method `mul` has an incompatible type for trait: expected i32, found f64
+    //~^ ERROR method `mul` has an incompatible type for trait
         s
     }
 }
@@ -72,7 +72,15 @@ pub fn main() {
 
     let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
     //~^ ERROR mismatched types
-    //~^^ ERROR mismatched types
+    //~| expected `Vec2`
+    //~| found `_`
+    //~| expected struct `Vec2`
+    //~| found floating-point variable
+    //~| ERROR mismatched types
+    //~| expected `Vec2`
+    //~| found `f64`
+    //~| expected struct `Vec2`
+    //~| found f64
 
     let x: i32 = Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0;
 }
diff --git a/src/test/debuginfo/limited-debuginfo.rs b/src/test/debuginfo/limited-debuginfo.rs
index 35889ff8133..00de4497ced 100644
--- a/src/test/debuginfo/limited-debuginfo.rs
+++ b/src/test/debuginfo/limited-debuginfo.rs
@@ -48,7 +48,11 @@ fn zzz() {()}
 fn some_function(a: int, b: int) {
     let some_variable = Struct { a: 11, b: 22 };
     let some_other_variable = 23i;
-    zzz(); // #break
+
+    for x in range(0, 1) {
+        zzz(); // #break
+    }
 }
 
 fn some_other_function(a: int, b: int) -> bool { true }
+
diff --git a/src/test/pretty/trait-polarity.rs b/src/test/pretty/trait-polarity.rs
index 47c36ac7a40..7d3a921301e 100644
--- a/src/test/pretty/trait-polarity.rs
+++ b/src/test/pretty/trait-polarity.rs
@@ -12,12 +12,8 @@
 
 // pp-exact
 
-trait UnsafeTrait {
-    fn foo(&self);
-}
+struct Test;
 
-impl !UnsafeTrait for int {
-    fn foo(&self) { }
-}
+impl !Send for Test { }
 
 pub fn main() { }
diff --git a/src/test/run-make/compiler-lookup-paths-2/Makefile b/src/test/run-make/compiler-lookup-paths-2/Makefile
new file mode 100644
index 00000000000..bd7f62d5c2d
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths-2/Makefile
@@ -0,0 +1,8 @@
+-include ../tools.mk
+
+all:
+	mkdir -p $(TMPDIR)/a $(TMPDIR)/b
+	$(RUSTC) a.rs && mv $(TMPDIR)/liba.rlib $(TMPDIR)/a
+	$(RUSTC) b.rs -L $(TMPDIR)/a && mv $(TMPDIR)/libb.rlib $(TMPDIR)/b
+	$(RUSTC) c.rs -L crate=$(TMPDIR)/b -L dependency=$(TMPDIR)/a \
+		&& exit 1 || exit 0
diff --git a/src/librustc_driver/mod.rs b/src/test/run-make/compiler-lookup-paths-2/a.rs
index 1fbbc9c0521..e7572a5f615 100644
--- a/src/librustc_driver/mod.rs
+++ b/src/test/run-make/compiler-lookup-paths-2/a.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,3 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![crate_type = "lib"]
diff --git a/src/test/compile-fail/marker-no-share.rs b/src/test/run-make/compiler-lookup-paths-2/b.rs
index b29f7fab2cc..fee0da9b4c1 100644
--- a/src/test/compile-fail/marker-no-share.rs
+++ b/src/test/run-make/compiler-lookup-paths-2/b.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,11 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
-
-fn foo<P: Sync>(p: P) { }
-
-fn main()
-{
-    foo(marker::NoSync); //~ ERROR the trait `core::marker::Sync` is not implemented
-}
+#![crate_type = "lib"]
+extern crate a;
diff --git a/src/test/run-make/compiler-lookup-paths-2/c.rs b/src/test/run-make/compiler-lookup-paths-2/c.rs
new file mode 100644
index 00000000000..66fe51d1099
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths-2/c.rs
@@ -0,0 +1,13 @@
+// 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.
+
+#![crate_type = "lib"]
+extern crate b;
+extern crate a;
diff --git a/src/test/run-make/extern-flag-disambiguates/Makefile b/src/test/run-make/extern-flag-disambiguates/Makefile
index 9b86bf97549..049b76c1b64 100644
--- a/src/test/run-make/extern-flag-disambiguates/Makefile
+++ b/src/test/run-make/extern-flag-disambiguates/Makefile
@@ -17,8 +17,10 @@ all:
 	$(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs
 	$(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib
 	$(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib
+	@echo before
 	$(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib
 	$(call RUN,d)
+	@echo after
 	$(RUSTC) --cfg after  d.rs --extern a=$(TMPDIR)/liba-1.rlib
 	$(call RUN,d)
 
diff --git a/src/test/run-make/extern-flag-disambiguates/a.rs b/src/test/run-make/extern-flag-disambiguates/a.rs
index 11b9ba6fce3..ac92aede789 100644
--- a/src/test/run-make/extern-flag-disambiguates/a.rs
+++ b/src/test/run-make/extern-flag-disambiguates/a.rs
@@ -11,6 +11,6 @@
 #![crate_name = "a"]
 #![crate_type = "rlib"]
 
-static FOO: uint = 3;
+static FOO: usize = 3;
 
-pub fn token() -> &'static uint { &FOO }
+pub fn token() -> &'static usize { &FOO }
diff --git a/src/test/run-make/extern-flag-disambiguates/b.rs b/src/test/run-make/extern-flag-disambiguates/b.rs
index 3156cf0ba72..8ae238f5a48 100644
--- a/src/test/run-make/extern-flag-disambiguates/b.rs
+++ b/src/test/run-make/extern-flag-disambiguates/b.rs
@@ -13,7 +13,7 @@
 
 extern crate a;
 
-static FOO: uint = 3;
+static FOO: usize = 3;
 
-pub fn token() -> &'static uint { &FOO }
-pub fn a_token() -> &'static uint { a::token() }
+pub fn token() -> &'static usize { &FOO }
+pub fn a_token() -> &'static usize { a::token() }
diff --git a/src/test/run-make/extern-flag-disambiguates/c.rs b/src/test/run-make/extern-flag-disambiguates/c.rs
index d3bbc762ef2..6eccdf7e5c8 100644
--- a/src/test/run-make/extern-flag-disambiguates/c.rs
+++ b/src/test/run-make/extern-flag-disambiguates/c.rs
@@ -13,7 +13,7 @@
 
 extern crate a;
 
-static FOO: uint = 3;
+static FOO: usize = 3;
 
-pub fn token() -> &'static uint { &FOO }
-pub fn a_token() -> &'static uint { a::token() }
+pub fn token() -> &'static usize { &FOO }
+pub fn a_token() -> &'static usize { a::token() }
diff --git a/src/test/run-make/extern-flag-disambiguates/d.rs b/src/test/run-make/extern-flag-disambiguates/d.rs
index d850daffc39..90e1330d4ae 100644
--- a/src/test/run-make/extern-flag-disambiguates/d.rs
+++ b/src/test/run-make/extern-flag-disambiguates/d.rs
@@ -13,7 +13,7 @@ extern crate b;
 extern crate c;
 #[cfg(after)] extern crate a;
 
-fn t(a: &'static uint) -> uint { a as *const _ as uint }
+fn t(a: &'static usize) -> usize { a as *const _ as usize }
 
 fn main() {
     assert!(t(a::token()) == t(b::a_token()));
diff --git a/src/test/run-make/graphviz-flowgraph/Makefile b/src/test/run-make/graphviz-flowgraph/Makefile
index 0562e000e56..4ac8cb7ae1d 100644
--- a/src/test/run-make/graphviz-flowgraph/Makefile
+++ b/src/test/run-make/graphviz-flowgraph/Makefile
@@ -28,7 +28,7 @@ $(TMPDIR)/%.pp: %.rs
 
 $(TMPDIR)/%.dot: %.rs
 	$(eval $(call FIND_LAST_BLOCK,$<))
-	$(RUSTC_LIB) -Z unstable-options --xpretty flowgraph=$(LASTBLOCKNUM_$<) $< -o $@.tmp
+	$(RUSTC_LIB) -Z unstable-options --xpretty flowgraph,unlabelled=$(LASTBLOCKNUM_$<) $< -o $@.tmp
 	cat $@.tmp | sed -e 's@ (id=[0-9]*)@@g' \
                          -e 's@\[label=""\]@@' \
                          -e 's@digraph [a-zA-Z0-9_]* @digraph block @' \
diff --git a/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot
index e9cd07c0356..12b16cc9f8c 100644
--- a/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f12.dot-expected.dot
@@ -34,7 +34,7 @@ digraph block {
     N11 -> N12;
     N12 -> N13;
     N13 -> N14;
-    N14 -> N6[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 2is { break ; \"unreachable\"; },\lexiting scope_4 block { x -= 1is; if x == 2is { break ; \"unreachable\"; } }"];
+    N14 -> N6;
     N15 -> N16;
     N16 -> N17;
     N17 -> N18;
diff --git a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot
index 7b01c606083..47e9b3f6cbe 100644
--- a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot
@@ -61,7 +61,7 @@ digraph block {
     N12 -> N13;
     N13 -> N14;
     N14 -> N15;
-    N15 -> N9[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1is { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1is { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1is { break \'outer ; \"unreachable\"; }\l    if y >= 2is { break ; \"unreachable\"; }\l    y -= 3is;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1is { break \'outer ; \"unreachable\"; }\l        if y >= 2is { break ; \"unreachable\"; }\l        y -= 3is;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1is { break \'outer ; \"unreachable\"; }\l        if y >= 2is { break ; \"unreachable\"; }\l        y -= 3is;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1is { break \'outer ; \"unreachable\"; }\l            if y >= 2is { break ; \"unreachable\"; }\l            y -= 3is;\l        }\l    y -= 4is;\l    x -= 5is;\l}\l"];
+    N15 -> N9;
     N16 -> N17;
     N17 -> N18;
     N18 -> N19;
@@ -73,7 +73,7 @@ digraph block {
     N23 -> N24;
     N24 -> N25;
     N25 -> N26;
-    N26 -> N11[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y >= 2is { break ; \"unreachable\"; },\lexiting scope_4 stmt if y >= 2is { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1is { break \'outer ; \"unreachable\"; }\l    if y >= 2is { break ; \"unreachable\"; }\l    y -= 3is;\l}\l"];
+    N26 -> N11;
     N27 -> N28;
     N28 -> N29;
     N29 -> N30;
diff --git a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot
index 2123185a083..a37869b2264 100644
--- a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot
@@ -64,7 +64,7 @@ digraph block {
     N12 -> N13;
     N13 -> N14;
     N14 -> N15;
-    N15 -> N8[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1is { continue \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1is { continue \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1is { continue \'outer ; \"unreachable\"; }\l    if y >= 1is { break ; \"unreachable\"; }\l    y -= 1is;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1is { continue \'outer ; \"unreachable\"; }\l        if y >= 1is { break ; \"unreachable\"; }\l        y -= 1is;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1is { continue \'outer ; \"unreachable\"; }\l        if y >= 1is { break ; \"unreachable\"; }\l        y -= 1is;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1is { continue \'outer ; \"unreachable\"; }\l            if y >= 1is { break ; \"unreachable\"; }\l            y -= 1is;\l        }\l    y -= 1is;\l    x -= 1is;\l}\l"];
+    N15 -> N8;
     N16 -> N17;
     N17 -> N18;
     N18 -> N19;
@@ -76,7 +76,7 @@ digraph block {
     N23 -> N24;
     N24 -> N25;
     N25 -> N26;
-    N26 -> N11[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y >= 1is { break ; \"unreachable\"; },\lexiting scope_4 stmt if y >= 1is { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1is { continue \'outer ; \"unreachable\"; }\l    if y >= 1is { break ; \"unreachable\"; }\l    y -= 1is;\l}\l"];
+    N26 -> N11;
     N27 -> N28;
     N28 -> N29;
     N29 -> N30;
diff --git a/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot
index e7a2cf2ff73..46f1634416e 100644
--- a/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f21.dot-expected.dot
@@ -59,7 +59,7 @@ digraph block {
     N12 -> N13;
     N13 -> N14;
     N14 -> N15;
-    N15 -> N9[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1is { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1is { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1is { break \'outer ; \"unreachable\"; }\l    if y >= 2is { return; \"unreachable\"; }\l    y -= 3is;\l    x -= 5is;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1is { break \'outer ; \"unreachable\"; }\l        if y >= 2is { return; \"unreachable\"; }\l        y -= 3is;\l        x -= 5is;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1is { break \'outer ; \"unreachable\"; }\l        if y >= 2is { return; \"unreachable\"; }\l        y -= 3is;\l        x -= 5is;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1is { break \'outer ; \"unreachable\"; }\l            if y >= 2is { return; \"unreachable\"; }\l            y -= 3is;\l            x -= 5is;\l        }\l    \"unreachable\";\l}\l"];
+    N15 -> N9;
     N16 -> N17;
     N17 -> N18;
     N18 -> N19;
@@ -71,7 +71,7 @@ digraph block {
     N23 -> N24;
     N24 -> N25;
     N25 -> N26;
-    N26 -> N1[label="exiting scope_0 expr \'inner:\l    loop  {\l        if x == 1is { break \'outer ; \"unreachable\"; }\l        if y >= 2is { return; \"unreachable\"; }\l        y -= 3is;\l        x -= 5is;\l    }\l,\lexiting scope_1 expr \'outer:\l    loop  {\l        \'inner:\l            loop  {\l                if x == 1is { break \'outer ; \"unreachable\"; }\l                if y >= 2is { return; \"unreachable\"; }\l                y -= 3is;\l                x -= 5is;\l            }\l        \"unreachable\";\l    }\l"];
+    N26 -> N1;
     N27 -> N28;
     N28 -> N29;
     N29 -> N30;
diff --git a/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot
index edd39b40b36..3f35a9b0f9a 100644
--- a/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f22.dot-expected.dot
@@ -62,7 +62,7 @@ digraph block {
     N12 -> N13;
     N13 -> N14;
     N14 -> N15;
-    N15 -> N8[label="exiting scope_0 expr continue \'outer,\lexiting scope_1 stmt continue \'outer ;,\lexiting scope_2 block { continue \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1is { continue \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1is { continue \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 1is { continue \'outer ; \"unreachable\"; }\l    if y >= 2is { return; \"unreachable\"; }\l    x -= 1is;\l    y -= 3is;\l}\l,\lexiting scope_6 expr \'inner:\l    loop  {\l        if x == 1is { continue \'outer ; \"unreachable\"; }\l        if y >= 2is { return; \"unreachable\"; }\l        x -= 1is;\l        y -= 3is;\l    }\l,\lexiting scope_7 stmt \'inner:\l    loop  {\l        if x == 1is { continue \'outer ; \"unreachable\"; }\l        if y >= 2is { return; \"unreachable\"; }\l        x -= 1is;\l        y -= 3is;\l    }\l,\lexiting scope_8 block {\l    \'inner:\l        loop  {\l            if x == 1is { continue \'outer ; \"unreachable\"; }\l            if y >= 2is { return; \"unreachable\"; }\l            x -= 1is;\l            y -= 3is;\l        }\l    \"unreachable\";\l}\l"];
+    N15 -> N8;
     N16 -> N17;
     N17 -> N18;
     N18 -> N19;
@@ -74,7 +74,7 @@ digraph block {
     N23 -> N24;
     N24 -> N25;
     N25 -> N26;
-    N26 -> N1[label="exiting scope_0 expr \'inner:\l    loop  {\l        if x == 1is { continue \'outer ; \"unreachable\"; }\l        if y >= 2is { return; \"unreachable\"; }\l        x -= 1is;\l        y -= 3is;\l    }\l,\lexiting scope_1 expr \'outer:\l    loop  {\l        \'inner:\l            loop  {\l                if x == 1is { continue \'outer ; \"unreachable\"; }\l                if y >= 2is { return; \"unreachable\"; }\l                x -= 1is;\l                y -= 3is;\l            }\l        \"unreachable\";\l    }\l"];
+    N26 -> N1;
     N27 -> N28;
     N28 -> N29;
     N29 -> N30;
diff --git a/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot
index 2b5c5cdff44..c9f7d4cdf0a 100644
--- a/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f23.dot-expected.dot
@@ -95,7 +95,7 @@ digraph block {
     N40 -> N41;
     N41 -> N42;
     N42 -> N43;
-    N43 -> N1[label="exiting scope_0 expr while y > 0is {\l    y -= 1is;\l    while z > 0is { z -= 1is; }\l    if x > 10is { return; \"unreachable\"; }\l}\l,\lexiting scope_1 expr while x > 0is {\l    x -= 1is;\l    while y > 0is {\l        y -= 1is;\l        while z > 0is { z -= 1is; }\l        if x > 10is { return; \"unreachable\"; }\l    }\l}\l"];
+    N43 -> N1;
     N44 -> N45;
     N45 -> N46;
     N46 -> N47;
diff --git a/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot
index ee3fe7ced6c..a5373bda39b 100644
--- a/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f24.dot-expected.dot
@@ -90,7 +90,7 @@ digraph block {
     N13 -> N14;
     N14 -> N15;
     N15 -> N16;
-    N16 -> N12[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 0is { break ; \"unreachable\"; },\lexiting scope_4 stmt if x == 0is { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 0is { break ; \"unreachable\"; }\l    x -= 1is;\l    loop  {\l        if y == 0is { break ; \"unreachable\"; }\l        y -= 1is;\l        loop  { if z == 0is { break ; \"unreachable\"; } z -= 1is; }\l        if x > 10is { return; \"unreachable\"; }\l    }\l}\l"];
+    N16 -> N12;
     N17 -> N18;
     N18 -> N19;
     N19 -> N20;
@@ -107,7 +107,7 @@ digraph block {
     N30 -> N31;
     N31 -> N32;
     N32 -> N33;
-    N33 -> N29[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y == 0is { break ; \"unreachable\"; },\lexiting scope_4 stmt if y == 0is { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if y == 0is { break ; \"unreachable\"; }\l    y -= 1is;\l    loop  { if z == 0is { break ; \"unreachable\"; } z -= 1is; }\l    if x > 10is { return; \"unreachable\"; }\l}\l"];
+    N33 -> N29;
     N34 -> N35;
     N35 -> N36;
     N36 -> N37;
@@ -124,7 +124,7 @@ digraph block {
     N47 -> N48;
     N48 -> N49;
     N49 -> N50;
-    N50 -> N46[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if z == 0is { break ; \"unreachable\"; },\lexiting scope_4 stmt if z == 0is { break ; \"unreachable\"; },\lexiting scope_5 block { if z == 0is { break ; \"unreachable\"; } z -= 1is; }"];
+    N50 -> N46;
     N51 -> N52;
     N52 -> N53;
     N53 -> N54;
@@ -143,7 +143,7 @@ digraph block {
     N64 -> N65;
     N65 -> N66;
     N66 -> N67;
-    N67 -> N1[label="exiting scope_0 expr loop  {\l    if y == 0is { break ; \"unreachable\"; }\l    y -= 1is;\l    loop  { if z == 0is { break ; \"unreachable\"; } z -= 1is; }\l    if x > 10is { return; \"unreachable\"; }\l}\l,\lexiting scope_1 expr loop  {\l    if x == 0is { break ; \"unreachable\"; }\l    x -= 1is;\l    loop  {\l        if y == 0is { break ; \"unreachable\"; }\l        y -= 1is;\l        loop  { if z == 0is { break ; \"unreachable\"; } z -= 1is; }\l        if x > 10is { return; \"unreachable\"; }\l    }\l}\l"];
+    N67 -> N1;
     N68 -> N69;
     N69 -> N70;
     N70 -> N71;
diff --git a/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot
index 82799c724b0..2611219e816 100644
--- a/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot
+++ b/src/test/run-make/graphviz-flowgraph/f25.dot-expected.dot
@@ -90,7 +90,7 @@ digraph block {
     N13 -> N14;
     N14 -> N15;
     N15 -> N16;
-    N16 -> N12[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if x == 0is { break ; \"unreachable\"; },\lexiting scope_4 stmt if x == 0is { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if x == 0is { break ; \"unreachable\"; }\l    x -= 1is;\l    \'a:\l        loop  {\l            if y == 0is { break ; \"unreachable\"; }\l            y -= 1is;\l            \'a: loop  { if z == 0is { break ; \"unreachable\"; } z -= 1is; }\l            if x > 10is { continue \'a ; \"unreachable\"; }\l        }\l}\l"];
+    N16 -> N12;
     N17 -> N18;
     N18 -> N19;
     N19 -> N20;
@@ -107,7 +107,7 @@ digraph block {
     N30 -> N31;
     N31 -> N32;
     N32 -> N33;
-    N33 -> N29[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if y == 0is { break ; \"unreachable\"; },\lexiting scope_4 stmt if y == 0is { break ; \"unreachable\"; },\lexiting scope_5 block {\l    if y == 0is { break ; \"unreachable\"; }\l    y -= 1is;\l    \'a: loop  { if z == 0is { break ; \"unreachable\"; } z -= 1is; }\l    if x > 10is { continue \'a ; \"unreachable\"; }\l}\l"];
+    N33 -> N29;
     N34 -> N35;
     N35 -> N36;
     N36 -> N37;
@@ -124,7 +124,7 @@ digraph block {
     N47 -> N48;
     N48 -> N49;
     N49 -> N50;
-    N50 -> N46[label="exiting scope_0 expr break,\lexiting scope_1 stmt break ;,\lexiting scope_2 block { break ; \"unreachable\"; },\lexiting scope_3 expr if z == 0is { break ; \"unreachable\"; },\lexiting scope_4 stmt if z == 0is { break ; \"unreachable\"; },\lexiting scope_5 block { if z == 0is { break ; \"unreachable\"; } z -= 1is; }"];
+    N50 -> N46;
     N51 -> N52;
     N52 -> N53;
     N53 -> N54;
@@ -143,7 +143,7 @@ digraph block {
     N64 -> N65;
     N65 -> N66;
     N66 -> N67;
-    N67 -> N28[label="exiting scope_0 expr continue \'a,\lexiting scope_1 stmt continue \'a ;,\lexiting scope_2 block { continue \'a ; \"unreachable\"; },\lexiting scope_3 expr if x > 10is { continue \'a ; \"unreachable\"; },\lexiting scope_4 block {\l    if y == 0is { break ; \"unreachable\"; }\l    y -= 1is;\l    \'a: loop  { if z == 0is { break ; \"unreachable\"; } z -= 1is; }\l    if x > 10is { continue \'a ; \"unreachable\"; }\l}\l"];
+    N67 -> N28;
     N68 -> N69;
     N69 -> N70;
     N70 -> N71;
diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs
index 8a0c14d2d7e..fe7df641159 100644
--- a/src/test/run-make/issue-19371/foo.rs
+++ b/src/test/run-make/issue-19371/foo.rs
@@ -14,7 +14,7 @@ extern crate syntax;
 
 use rustc::session::{build_session, Session};
 use rustc::session::config::{basic_options, build_configuration, Input, OutputTypeExe};
-use rustc_driver::driver::{compile_input};
+use rustc_driver::driver::{compile_input, CompileController};
 use syntax::diagnostics::registry::Registry;
 
 fn main() {
@@ -52,11 +52,13 @@ fn basic_sess(sysroot: Path) -> Session {
 fn compile(code: String, output: Path, sysroot: Path) {
     let sess = basic_sess(sysroot);
     let cfg = build_configuration(&sess);
+    let control = CompileController::basic();
 
     compile_input(sess,
             cfg,
             &Input::Str(code),
             &None,
             &Some(output),
-            None);
+            None,
+            control);
 }
diff --git a/src/test/run-make/simd-ffi/Makefile b/src/test/run-make/simd-ffi/Makefile
new file mode 100644
index 00000000000..68a6a5fbfe8
--- /dev/null
+++ b/src/test/run-make/simd-ffi/Makefile
@@ -0,0 +1,33 @@
+-include ../tools.mk
+
+# construct a fairly exhaustive list of platforms that we
+# support. These ones don't follow a pattern
+TARGETS=arm-linux-androideabi arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabi
+
+# these ones do, each OS lists the architectures it supports
+LINUX=aarch64 i686 x86_64 mips mipsel
+WINDOWS=i686 x86_64
+# fails with: failed to get iphonesimulator SDK path: no such file or directory
+#IOS=i386 aarch64 armv7
+DARWIN=i686 x86_64
+
+$(foreach arch,$(LINUX),$(eval TARGETS += $(arch)-unknown-linux-gnu))
+$(foreach arch,$(WINDOWS),$(eval TARGETS += $(arch)-pc-windows-gnu))
+#$(foreach arch,$(IOS),$(eval TARGETS += $(arch)-apple-ios))
+$(foreach arch,$(DARWIN),$(eval TARGETS += $(arch)-apple-darwin))
+
+all: $(TARGETS)
+
+define MK_TARGETS
+# compile the rust file to the given target, but only to asm and IR
+# form, to avoid having to have an appropriate linker.
+#
+# we need some features because the integer SIMD instructions are not
+# enabled by-default for i686 and ARM; these features will be invalid
+# on some platforms, but LLVM just prints a warning so that's fine for
+# now.
+$(1): simd.rs
+	$$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs -C target-feature='+neon,+sse2'
+endef
+
+$(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx))))
diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs
new file mode 100755
index 00000000000..76079ddb8bd
--- /dev/null
+++ b/src/test/run-make/simd-ffi/simd.rs
@@ -0,0 +1,81 @@
+// 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.
+
+// ensures that public symbols are not removed completely
+#![crate_type = "lib"]
+// we can compile to a variety of platforms, because we don't need
+// cross-compiled standard libraries.
+#![no_std]
+
+#![feature(simd, simd_ffi, link_llvm_intrinsics, lang_items)]
+
+
+#[repr(C)]
+#[derive(Copy)]
+#[simd]
+pub struct f32x4(f32, f32, f32, f32);
+
+
+extern {
+    #[link_name = "llvm.sqrt.v4f32"]
+    fn vsqrt(x: f32x4) -> f32x4;
+}
+
+pub fn foo(x: f32x4) -> f32x4 {
+    unsafe {vsqrt(x)}
+}
+
+#[repr(C)]
+#[derive(Copy)]
+#[simd]
+pub struct i32x4(i32, i32, i32, i32);
+
+
+extern {
+    // _mm_sll_epi32
+    #[cfg(any(target_arch = "x86",
+              target_arch = "x86-64"))]
+    #[link_name = "llvm.x86.sse2.psll.d"]
+    fn integer(a: i32x4, b: i32x4) -> i32x4;
+
+    // vmaxq_s32
+    #[cfg(any(target_arch = "arm"))]
+    #[link_name = "llvm.arm.neon.vmaxs.v4i32"]
+    fn integer(a: i32x4, b: i32x4) -> i32x4;
+    // vmaxq_s32
+    #[cfg(any(target_arch = "aarch64"))]
+    #[link_name = "llvm.aarch64.neon.maxs.v4i32"]
+    fn integer(a: i32x4, b: i32x4) -> i32x4;
+
+    // just some substitute foreign symbol, not an LLVM intrinsic; so
+    // we still get type checking, but not as detailed as (ab)using
+    // LLVM.
+    #[cfg(not(any(target_arch = "x86",
+                  target_arch = "x86-64",
+                  target_arch = "arm",
+                  target_arch = "aarch64")))]
+    fn integer(a: i32x4, b: i32x4) -> i32x4;
+}
+
+pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
+    unsafe {integer(a, b)}
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+mod std {
+    pub mod marker {
+        pub use Copy;
+    }
+}
diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk
index f5027618814..365cbf93da2 100644
--- a/src/test/run-make/tools.mk
+++ b/src/test/run-make/tools.mk
@@ -51,7 +51,7 @@ endif
 
 # Extra flags needed to compile a working executable with the standard library
 ifdef IS_WINDOWS
-	EXTRACFLAGS :=
+	EXTRACFLAGS := -lws2_32
 else
 ifeq ($(shell uname),Darwin)
 else
diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs
index 4ffb8a3f74d..5236b35d4d2 100644
--- a/src/test/run-pass-fulldeps/macro-crate.rs
+++ b/src/test/run-pass-fulldeps/macro-crate.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -20,12 +20,36 @@ extern crate macro_crate_test;
 #[derive(PartialEq, Clone, Show)]
 fn foo() -> AFakeTypeThatHadBetterGoAway {}
 
+#[into_multi_foo]
+#[derive(PartialEq, Clone, Show)]
+fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
+
+trait Qux {
+    #[into_multi_foo]
+    fn bar();
+}
+
+impl Qux for i32 {
+    #[into_multi_foo]
+    fn bar() {}
+}
+
+impl Qux for u8 {}
+
 pub fn main() {
     assert_eq!(1, make_a_1!());
     assert_eq!(2, exported_macro!());
 
     assert_eq!(Foo::Bar, Foo::Bar);
     test(None::<Foo>);
+
+    assert_eq!(Foo2::Bar2, Foo2::Bar2);
+    test(None::<Foo2>);
+
+    let x = 10i32;
+    assert_eq!(x.foo(), 42);
+    let x = 10u8;
+    assert_eq!(x.foo(), 0);
 }
 
 fn test<T: PartialEq+Clone>(_: Option<T>) {}
diff --git a/src/test/run-pass/associated-types-enum-field-named.rs b/src/test/run-pass/associated-types-enum-field-named.rs
new file mode 100644
index 00000000000..a499aa6733a
--- /dev/null
+++ b/src/test/run-pass/associated-types-enum-field-named.rs
@@ -0,0 +1,43 @@
+// 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 associated types appearing in struct-like enum variants.
+
+use self::VarValue::*;
+
+pub trait UnifyKey {
+    type Value;
+    fn to_index(&self) -> usize;
+}
+
+pub enum VarValue<K:UnifyKey> {
+    Redirect { to: K },
+    Root { value: K::Value, rank: usize },
+}
+
+fn get<'a,K:UnifyKey<Value=Option<V>>,V>(table: &'a Vec<VarValue<K>>, key: &K) -> &'a Option<V> {
+    match table[key.to_index()] {
+        VarValue::Redirect { to: ref k } => get(table, k),
+        VarValue::Root { value: ref v, rank: _ } => v,
+    }
+}
+
+impl UnifyKey for usize {
+    type Value = Option<char>;
+    fn to_index(&self) -> usize { *self }
+}
+
+fn main() {
+    let table = vec![/* 0 */ Redirect { to: 1 },
+                     /* 1 */ Redirect { to: 3 },
+                     /* 2 */ Root { value: Some('x'), rank: 0 },
+                     /* 3 */ Redirect { to: 2 }];
+    assert_eq!(get(&table, &0), &Some('x'));
+}
diff --git a/src/test/run-pass/associated-types-enum-field-numbered.rs b/src/test/run-pass/associated-types-enum-field-numbered.rs
new file mode 100644
index 00000000000..e710c53327e
--- /dev/null
+++ b/src/test/run-pass/associated-types-enum-field-numbered.rs
@@ -0,0 +1,43 @@
+// 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 associated types appearing in tuple-like enum variants.
+
+use self::VarValue::*;
+
+pub trait UnifyKey {
+    type Value;
+    fn to_index(&self) -> usize;
+}
+
+pub enum VarValue<K:UnifyKey> {
+    Redirect(K),
+    Root(K::Value, usize),
+}
+
+fn get<'a,K:UnifyKey<Value=Option<V>>,V>(table: &'a Vec<VarValue<K>>, key: &K) -> &'a Option<V> {
+    match table[key.to_index()] {
+        VarValue::Redirect(ref k) => get(table, k),
+        VarValue::Root(ref v, _) => v,
+    }
+}
+
+impl UnifyKey for usize {
+    type Value = Option<char>;
+    fn to_index(&self) -> usize { *self }
+}
+
+fn main() {
+    let table = vec![/* 0 */ Redirect(1),
+                     /* 1 */ Redirect(3),
+                     /* 2 */ Root(Some('x'), 0),
+                     /* 3 */ Redirect(2)];
+    assert_eq!(get(&table, &0), &Some('x'));
+}
diff --git a/src/test/run-pass/associated-types-normalize-unifield-struct.rs b/src/test/run-pass/associated-types-normalize-unifield-struct.rs
new file mode 100644
index 00000000000..c517f61de0c
--- /dev/null
+++ b/src/test/run-pass/associated-types-normalize-unifield-struct.rs
@@ -0,0 +1,32 @@
+// 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.
+
+// Regression test for issue #21010: Normalize associated types in
+// various special paths in the `type_is_immediate` function.
+
+#![allow(unstable)]
+
+pub trait OffsetState: Sized {}
+pub trait Offset { type State: OffsetState; }
+
+#[derive(Copy)] pub struct X;
+impl Offset for X { type State = Y; }
+
+#[derive(Copy)] pub struct Y;
+impl OffsetState for Y {}
+
+pub fn now() -> DateTime<X> { from_utc(Y) }
+
+pub struct DateTime<Off: Offset> { pub offset: Off::State }
+pub fn from_utc<Off: Offset>(offset: Off::State) -> DateTime<Off> { DateTime { offset: offset } }
+
+pub fn main() {
+    let _x = now();
+}
diff --git a/src/test/run-pass/associated-types-projection-in-object-type.rs b/src/test/run-pass/associated-types-projection-in-object-type.rs
new file mode 100644
index 00000000000..44dd49b7297
--- /dev/null
+++ b/src/test/run-pass/associated-types-projection-in-object-type.rs
@@ -0,0 +1,43 @@
+// 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.
+
+// Corrected regression test for #20831. The original did not compile.
+// When fixed, it revealed another problem concerning projections that
+// appear in associated type bindings in object types, which were not
+// being properly flagged.
+
+use std::ops::{Shl, Shr};
+use std::cell::RefCell;
+
+pub trait Subscriber {
+    type Input;
+}
+
+pub trait Publisher<'a> {
+    type Output;
+    fn subscribe(&mut self, Box<Subscriber<Input=Self::Output> + 'a>);
+}
+
+pub trait Processor<'a> : Subscriber + Publisher<'a> { }
+
+impl<'a, P> Processor<'a> for P where P : Subscriber + Publisher<'a> { }
+
+struct MyStruct<'a> {
+    sub: Box<Subscriber<Input=u64> + 'a>
+}
+
+impl<'a> Publisher<'a> for MyStruct<'a> {
+    type Output = u64;
+    fn subscribe(&mut self, t : Box<Subscriber<Input=u64> + 'a>) {
+        self.sub = t;
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/associated-types-projection-in-where-clause.rs b/src/test/run-pass/associated-types-projection-in-where-clause.rs
new file mode 100644
index 00000000000..10a459f3c36
--- /dev/null
+++ b/src/test/run-pass/associated-types-projection-in-where-clause.rs
@@ -0,0 +1,34 @@
+// 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 a where clause that uses a non-normalized projection type.
+
+trait Int
+{
+    type T;
+}
+
+trait NonZero
+{
+    fn non_zero(self) -> bool;
+}
+
+fn foo<I:Int<T=J>,J>(t: I) -> bool
+    where <I as Int>::T : NonZero
+    //    ^~~~~~~~~~~~~ canonical form is just J
+{
+    bar::<J>()
+}
+
+fn bar<NZ:NonZero>() -> bool { true }
+
+fn main ()
+{
+}
diff --git a/src/test/run-pass/associated-types-struct-field-named.rs b/src/test/run-pass/associated-types-struct-field-named.rs
new file mode 100644
index 00000000000..1ded34ff3ff
--- /dev/null
+++ b/src/test/run-pass/associated-types-struct-field-named.rs
@@ -0,0 +1,41 @@
+// 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 that we correctly normalize the type of a struct field
+// which has an associated type.
+
+pub trait UnifyKey {
+    type Value;
+}
+
+pub struct Node<K:UnifyKey> {
+    pub key: K,
+    pub value: K::Value,
+}
+
+fn foo<K : UnifyKey<Value=Option<V>>,V : Clone>(node: &Node<K>) -> Option<V> {
+    node.value.clone()
+}
+
+impl UnifyKey for i32 {
+    type Value = Option<u32>;
+}
+
+impl UnifyKey for u32 {
+    type Value = Option<i32>;
+}
+
+pub fn main() {
+    let node: Node<i32> = Node { key: 1, value: Some(22) };
+    assert_eq!(foo(&node), Some(22_u32));
+
+    let node: Node<u32> = Node { key: 1, value: Some(22) };
+    assert_eq!(foo(&node), Some(22_i32));
+}
diff --git a/src/test/run-pass/associated-types-struct-field-numbered.rs b/src/test/run-pass/associated-types-struct-field-numbered.rs
new file mode 100644
index 00000000000..3669dec4fbd
--- /dev/null
+++ b/src/test/run-pass/associated-types-struct-field-numbered.rs
@@ -0,0 +1,38 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we correctly normalize the type of a struct field
+// which has an associated type.
+
+pub trait UnifyKey {
+    type Value;
+}
+
+pub struct Node<K:UnifyKey>(K, K::Value);
+
+fn foo<K : UnifyKey<Value=Option<V>>,V : Clone>(node: &Node<K>) -> Option<V> {
+    node.1.clone()
+}
+
+impl UnifyKey for i32 {
+    type Value = Option<u32>;
+}
+
+impl UnifyKey for u32 {
+    type Value = Option<i32>;
+}
+
+pub fn main() {
+    let node: Node<i32> = Node(1, Some(22));
+    assert_eq!(foo(&node), Some(22_u32));
+
+    let node: Node<u32> = Node(1, Some(22));
+    assert_eq!(foo(&node), Some(22_i32));
+}
diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs
index da5fa19f816..320ad0bf4d1 100644
--- a/src/test/run-pass/backtrace.rs
+++ b/src/test/run-pass/backtrace.rs
@@ -12,11 +12,12 @@
 // ignore-windows FIXME #13259
 
 #![feature(unboxed_closures)]
+#![feature(unsafe_destructor)]
 
 use std::os;
 use std::io::process::Command;
-use std::finally::Finally;
 use std::str;
+use std::ops::{Drop, FnMut, FnOnce};
 
 #[inline(never)]
 fn foo() {
@@ -28,11 +29,15 @@ fn foo() {
 
 #[inline(never)]
 fn double() {
-    (|&mut:| {
-        panic!("once");
-    }).finally(|| {
-        panic!("twice");
-    })
+    struct Double;
+
+    impl Drop for Double {
+        fn drop(&mut self) { panic!("twice") }
+    }
+
+    let _d = Double;
+
+    panic!("once");
 }
 
 fn runtest(me: &str) {
diff --git a/src/test/run-pass/coerce-expect-unsized.rs b/src/test/run-pass/coerce-expect-unsized.rs
index 3964d54f860..f590e6e0728 100644
--- a/src/test/run-pass/coerce-expect-unsized.rs
+++ b/src/test/run-pass/coerce-expect-unsized.rs
@@ -30,4 +30,7 @@ pub fn main() {
     let _: &Fn(int) -> _ = &{ |x| (x as u8) };
     let _: &Show = &if true { false } else { true };
     let _: &Show = &match true { true => 'a', false => 'b' };
+
+    let _: Box<[int]> = Box::new([1, 2, 3]);
+    let _: Box<Fn(int) -> _> = Box::new(|x| (x as u8));
 }
diff --git a/src/test/run-pass/coerce-unify-return.rs b/src/test/run-pass/coerce-unify-return.rs
new file mode 100644
index 00000000000..eeba9042f7c
--- /dev/null
+++ b/src/test/run-pass/coerce-unify-return.rs
@@ -0,0 +1,26 @@
+// 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.
+
+// Check that coercions unify the expected return type of a polymorphic
+// function call, instead of leaving the type variables as they were.
+
+struct Foo;
+impl Foo {
+    fn foo<T>(self, x: T) -> Option<T> { Some(x) }
+}
+
+pub fn main() {
+    let _: Option<fn()> = Some(main);
+    let _: Option<fn()> = Foo.foo(main);
+
+    // The same two cases, with implicit type variables made explicit.
+    let _: Option<fn()> = Some::<_>(main);
+    let _: Option<fn()> = Foo.foo::<_>(main);
+}
diff --git a/src/test/compile-fail/marker-no-send.rs b/src/test/run-pass/coherence-negative-impls-safe.rs
index 032718d7e9a..7844ef3faca 100644
--- a/src/test/compile-fail/marker-no-send.rs
+++ b/src/test/run-pass/coherence-negative-impls-safe.rs
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::marker;
+#![feature(optin_builtin_traits)]
 
-fn foo<P:Send>(p: P) { }
+use std::marker::Send;
 
-fn main()
-{
-    foo(marker::NoSend); //~ ERROR the trait `core::marker::Send` is not implemented
-}
+struct TestType;
+
+impl !Send for TestType {}
+
+fn main() {}
diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs
index 28b346c9ed4..f8f92a56adb 100644
--- a/src/test/run-pass/const-polymorphic-paths.rs
+++ b/src/test/run-pass/const-polymorphic-paths.rs
@@ -10,9 +10,11 @@
 
 #![feature(macro_rules)]
 
+use std::borrow::{Cow, IntoCow};
 use std::collections::Bitv;
 use std::default::Default;
 use std::iter::FromIterator;
+use std::ops::Add;
 use std::option::IntoIter as OptionIter;
 use std::rand::Rand;
 use std::rand::XorShiftRng as DummyRng;
@@ -28,6 +30,11 @@ fn u8_as_i8(x: u8) -> i8 { x as i8 }
 fn odd(x: uint) -> bool { x % 2 == 1 }
 fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
 
+trait Size: Sized {
+    fn size() -> uint { std::mem::size_of::<Self>() }
+}
+impl<T> Size for T {}
+
 macro_rules! tests {
     ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
         const C: $ty = $expr;
@@ -70,14 +77,31 @@ tests! {
     //    , (vec![b'f', b'o', b'o'], u8_as_i8);
 
     // Trait static methods.
-    // FIXME qualified path expressions aka UFCS i.e. <T as Trait>::method.
+    <bool as Size>::size, fn() -> uint, ();
     Default::default, fn() -> int, ();
+    <int as Default>::default, fn() -> int, ();
     Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
+    <int as Rand>::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
     Rand::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
+    <int as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
 
     // Trait non-static methods.
     Clone::clone, fn(&int) -> int, (&5);
+    <int as Clone>::clone, fn(&int) -> int, (&5);
     FromIterator::from_iter, fn(OptionIter<int>) -> Vec<int>, (Some(5).into_iter());
-    FromIterator::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>
-       , (Some(5).into_iter());
+    <Vec<_> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    <Vec<int> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    FromIterator::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    <Vec<int> as FromIterator<_>>::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    Add::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
+    <String as IntoCow<_, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
+        ("foo".to_string());
+    <String as IntoCow<'static, _, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
+        ("foo".to_string());
 }
diff --git a/src/test/run-pass/huge-largest-array.rs b/src/test/run-pass/huge-largest-array.rs
index e1b0c115365..5083bd23207 100644
--- a/src/test/run-pass/huge-largest-array.rs
+++ b/src/test/run-pass/huge-largest-array.rs
@@ -10,12 +10,12 @@
 
 use std::mem::size_of;
 
-#[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
+#[cfg(target_pointer_width = "32")]
 pub fn main() {
     assert_eq!(size_of::<[u8; (1 << 31) - 1]>(), (1 << 31) - 1);
 }
 
-#[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
+#[cfg(target_pointer_width = "64")]
 pub fn main() {
     assert_eq!(size_of::<[u8; (1 << 47) - 1]>(), (1 << 47) - 1);
 }
diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs
index dbc23a63bba..c22fb811a7b 100644
--- a/src/test/run-pass/ifmt.rs
+++ b/src/test/run-pass/ifmt.rs
@@ -14,6 +14,7 @@
 #![deny(warnings)]
 #![allow(unused_must_use)]
 #![allow(unknown_features)]
+#![allow(unstable)]
 #![feature(box_syntax)]
 
 use std::fmt;
diff --git a/src/test/run-pass/issue-11958.rs b/src/test/run-pass/issue-11958.rs
index 13177880c5a..f557f662e81 100644
--- a/src/test/run-pass/issue-11958.rs
+++ b/src/test/run-pass/issue-11958.rs
@@ -12,6 +12,7 @@
 
 // Pretty printing tests complain about `use std::predule::*`
 #![allow(unused_imports)]
+#![allow(unstable)]
 
 // We shouldn't need to rebind a moved upvar as mut if it's already
 // marked as mut
diff --git a/src/test/run-pass/issue-16530.rs b/src/test/run-pass/issue-16530.rs
new file mode 100644
index 00000000000..7e3b796235d
--- /dev/null
+++ b/src/test/run-pass/issue-16530.rs
@@ -0,0 +1,18 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::hash::{SipHasher, hash};
+
+#[derive(Hash)]
+struct Empty;
+
+pub fn main() {
+    assert!(hash::<_, SipHasher>(&Empty) == hash::<_, SipHasher>(&Empty));
+}
diff --git a/src/test/run-pass/issue-16671.rs b/src/test/run-pass/issue-16671.rs
index e25b3e8e89c..4c72e4fdb73 100644
--- a/src/test/run-pass/issue-16671.rs
+++ b/src/test/run-pass/issue-16671.rs
@@ -14,6 +14,7 @@
 
 // Pretty printing tests complain about `use std::predule::*`
 #![allow(unused_imports)]
+#![allow(unstable)]
 
 // A var moved into a proc, that has a mutable loan path should
 // not trigger a misleading unused_mut warning.
diff --git a/src/test/run-pass/issue-17503.rs b/src/test/run-pass/issue-17503.rs
index 65bf088786e..a071224999b 100644
--- a/src/test/run-pass/issue-17503.rs
+++ b/src/test/run-pass/issue-17503.rs
@@ -13,7 +13,7 @@ fn main() {
     let ss: &&[int] = &s;
     let sss: &&&[int] = &ss;
 
-    println!("{:?}", &s[0..3]);
+    println!("{:?}", &s[..3]);
     println!("{:?}", &ss[3..]);
     println!("{:?}", &sss[2..4]);
 }
diff --git a/src/test/run-pass/issue-17718.rs b/src/test/run-pass/issue-17718.rs
index 44cf0dd8b8e..e4782e28928 100644
--- a/src/test/run-pass/issue-17718.rs
+++ b/src/test/run-pass/issue-17718.rs
@@ -12,10 +12,10 @@
 
 extern crate "issue-17718" as other;
 
-use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
 const C1: uint = 1;
-const C2: AtomicUint = ATOMIC_UINT_INIT;
+const C2: AtomicUsize = ATOMIC_USIZE_INIT;
 const C3: fn() = foo;
 const C4: uint = C1 * C1 + C1 / C1;
 const C5: &'static uint = &C4;
@@ -25,7 +25,7 @@ const C6: uint = {
 };
 
 static S1: uint = 3;
-static S2: AtomicUint = ATOMIC_UINT_INIT;
+static S2: AtomicUsize = ATOMIC_USIZE_INIT;
 
 mod test {
     static A: uint = 4;
diff --git a/src/test/run-pass/issue-20575.rs b/src/test/run-pass/issue-20575.rs
new file mode 100644
index 00000000000..f83150b9518
--- /dev/null
+++ b/src/test/run-pass/issue-20575.rs
@@ -0,0 +1,19 @@
+// 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 that overloaded calls work with zero arity closures
+
+#![feature(box_syntax)]
+
+fn main() {
+    let functions: [Box<Fn() -> Option<()>>; 1] = [box || None];
+
+    let _: Option<Vec<()>> = functions.iter().map(|f| (*f)()).collect();
+}
diff --git a/src/test/run-pass/issue-20676.rs b/src/test/run-pass/issue-20676.rs
new file mode 100644
index 00000000000..fd99fc01a23
--- /dev/null
+++ b/src/test/run-pass/issue-20676.rs
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #20676. Error was that we didn't support
+// UFCS-style calls to a method in `Trait` where `Self` was bound to a
+// trait object of type `Trait`. See also `ufcs-trait-object.rs`.
+
+use std::fmt;
+
+fn main() {
+    let a: &fmt::Show = &1_i32;
+    format!("{:?}", a);
+}
diff --git a/src/test/run-pass/issue-21058.rs b/src/test/run-pass/issue-21058.rs
new file mode 100644
index 00000000000..cbce577451f
--- /dev/null
+++ b/src/test/run-pass/issue-21058.rs
@@ -0,0 +1,30 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unstable)]
+
+struct NT(str);
+struct DST { a: u32, b: str }
+
+fn main() {
+    // get_tydesc should support unsized types
+    assert!(unsafe {(
+        // Slice
+        (*std::intrinsics::get_tydesc::<[u8]>()).name,
+        // str
+        (*std::intrinsics::get_tydesc::<str>()).name,
+        // Trait
+        (*std::intrinsics::get_tydesc::<Copy>()).name,
+        // Newtype
+        (*std::intrinsics::get_tydesc::<NT>()).name,
+        // DST
+        (*std::intrinsics::get_tydesc::<DST>()).name
+    )} == ("[u8]", "str", "core::marker::Copy + 'static", "NT", "DST"));
+}
diff --git a/src/test/run-pass/issue-8898.rs b/src/test/run-pass/issue-8898.rs
index 42739628eed..f845db9c421 100644
--- a/src/test/run-pass/issue-8898.rs
+++ b/src/test/run-pass/issue-8898.rs
@@ -16,7 +16,7 @@ pub fn main() {
     let abc = [1i, 2, 3];
     let tf = [true, false];
     let x  = [(), ()];
-    let slice = &x[0..1];
+    let slice = &x[..1];
 
     assert_repr_eq(&abc[], "[1i, 2i, 3i]".to_string());
     assert_repr_eq(&tf[], "[true, false]".to_string());
diff --git a/src/test/run-pass/regions-debruijn-of-object.rs b/src/test/run-pass/regions-debruijn-of-object.rs
new file mode 100644
index 00000000000..b9d3ed49c62
--- /dev/null
+++ b/src/test/run-pass/regions-debruijn-of-object.rs
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct ctxt<'tcx> {
+    x: &'tcx i32
+}
+
+trait AstConv<'tcx> {
+    fn tcx<'a>(&'a self) -> &'a ctxt<'tcx>;
+}
+
+fn foo(conv: &AstConv) { }
+
+fn bar<'tcx>(conv: &AstConv<'tcx>) {
+    foo(conv)
+}
+
+fn main() { }
diff --git a/src/test/run-pass/slice-2.rs b/src/test/run-pass/slice-2.rs
index 8f031d2e97e..43e517404cb 100644
--- a/src/test/run-pass/slice-2.rs
+++ b/src/test/run-pass/slice-2.rs
@@ -17,7 +17,7 @@ fn main() {
     let cmp: &[int] = &[3, 4, 5];
     assert!(&x[2..] == cmp);
     let cmp: &[int] = &[1, 2, 3];
-    assert!(&x[0..3] == cmp);
+    assert!(&x[..3] == cmp);
     let cmp: &[int] = &[2, 3, 4];
     assert!(&x[1..4] == cmp);
 
@@ -27,7 +27,7 @@ fn main() {
     let cmp: &[int] = &[3, 4, 5];
     assert!(&x[2..] == cmp);
     let cmp: &[int] = &[1, 2, 3];
-    assert!(&x[0..3] == cmp);
+    assert!(&x[..3] == cmp);
     let cmp: &[int] = &[2, 3, 4];
     assert!(&x[1..4] == cmp);
 
diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs
index a91e5da1537..3344844d49f 100644
--- a/src/test/run-pass/syntax-trait-polarity.rs
+++ b/src/test/run-pass/syntax-trait-polarity.rs
@@ -18,14 +18,12 @@ impl TestType {}
 
 trait TestTrait {}
 
-unsafe impl !Send for TestType {}
-impl !TestTrait for TestType {}
+impl !Send for TestType {}
 
 struct TestType2<T>;
 
 impl<T> TestType2<T> {}
 
-unsafe impl<T> !Send for TestType2<T> {}
-impl<T> !TestTrait for TestType2<T> {}
+impl<T> !Send for TestType2<T> {}
 
 fn main() {}
diff --git a/src/test/run-pass/tcp-accept-stress.rs b/src/test/run-pass/tcp-accept-stress.rs
index cad71732034..c7149fa503b 100644
--- a/src/test/run-pass/tcp-accept-stress.rs
+++ b/src/test/run-pass/tcp-accept-stress.rs
@@ -15,7 +15,7 @@
 
 use std::io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream};
 use std::sync::Arc;
-use std::sync::atomic::{AtomicUint, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::mpsc::channel;
 use std::thread::Thread;
 
@@ -30,7 +30,7 @@ fn test() {
     let mut l = TcpListener::bind("127.0.0.1:0").unwrap();
     let addr = l.socket_name().unwrap();
     let mut a = l.listen().unwrap();
-    let cnt = Arc::new(AtomicUint::new(0));
+    let cnt = Arc::new(AtomicUsize::new(0));
 
     let (srv_tx, srv_rx) = channel();
     let (cli_tx, cli_rx) = channel();
diff --git a/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs b/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs
new file mode 100644
index 00000000000..ca66a106c43
--- /dev/null
+++ b/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs
@@ -0,0 +1,23 @@
+// 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 that we do not error out because of a (False) ambiguity
+// between the builtin rules for Sized and the where clause. Issue
+// #20959.
+
+fn foo<K>(x: Option<K>)
+    where Option<K> : Sized
+{
+    let _y = x;
+}
+
+fn main() {
+    foo(Some(22));
+}
diff --git a/src/test/run-pass/traits-negative-impls.rs b/src/test/run-pass/traits-negative-impls.rs
new file mode 100644
index 00000000000..09c7d077705
--- /dev/null
+++ b/src/test/run-pass/traits-negative-impls.rs
@@ -0,0 +1,29 @@
+// 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(optin_builtin_traits)]
+
+use std::marker::Send;
+
+pub struct WaitToken;
+impl !Send for WaitToken {}
+
+pub struct Test<T>(T);
+unsafe impl<T: 'static> Send for Test<T> {}
+
+pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {}
+
+fn main() {
+    let wt = Test(WaitToken);
+    spawn(move || {
+        let x = wt;
+        println!("Hello, World!");
+    });
+}
diff --git a/src/test/run-pass/ufcs-trait-object.rs b/src/test/run-pass/ufcs-trait-object.rs
new file mode 100644
index 00000000000..2ae63040d17
--- /dev/null
+++ b/src/test/run-pass/ufcs-trait-object.rs
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that when you use ufcs form to invoke a trait method (on a
+// trait object) everything works fine.
+
+trait Foo {
+    fn test(&self) -> i32;
+}
+
+impl Foo for i32 {
+    fn test(&self) -> i32 { *self }
+}
+
+fn main() {
+    let a: &Foo = &22_i32;
+    assert_eq!(Foo::test(a), 22);
+}
diff --git a/src/test/run-pass/unwind-unique.rs b/src/test/run-pass/unwind-unique.rs
index 371fd677bd9..74802c156a2 100644
--- a/src/test/run-pass/unwind-unique.rs
+++ b/src/test/run-pass/unwind-unique.rs
@@ -19,5 +19,5 @@ fn f() {
 }
 
 pub fn main() {
-    let _t = Thread::spawn(f);
+    let _t = Thread::scoped(f);
 }
diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs
index 29bf82a81d6..9e74c6da548 100644
--- a/src/test/run-pass/vector-sort-panic-safe.rs
+++ b/src/test/run-pass/vector-sort-panic-safe.rs
@@ -8,27 +8,29 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 use std::rand::{thread_rng, Rng, Rand};
 use std::thread::Thread;
 
 const REPEATS: uint = 5;
 const MAX_LEN: uint = 32;
-static drop_counts: [AtomicUint;  MAX_LEN] =
-    // FIXME #5244: AtomicUint is not Copy.
+static drop_counts: [AtomicUsize;  MAX_LEN] =
+    // FIXME #5244: AtomicUsize is not Copy.
     [
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
      ];
 
-static creation_count: AtomicUint = ATOMIC_UINT_INIT;
+static creation_count: AtomicUsize = ATOMIC_USIZE_INIT;
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
 struct DropCounter { x: uint, creation_id: uint }
diff --git a/src/test/run-pass/weak-lang-item.rs b/src/test/run-pass/weak-lang-item.rs
index 08dac5c7c82..b1c65d322ab 100644
--- a/src/test/run-pass/weak-lang-item.rs
+++ b/src/test/run-pass/weak-lang-item.rs
@@ -15,7 +15,7 @@ extern crate "weak-lang-items" as other;
 use std::thread::Thread;
 
 fn main() {
-    let _ = Thread::spawn(move|| {
+    let _ = Thread::scoped(move|| {
         other::foo()
     });
 }
diff --git a/src/test/run-pass/where-clause-bounds-inconsistency.rs b/src/test/run-pass/where-clause-bounds-inconsistency.rs
new file mode 100644
index 00000000000..a1a61127f68
--- /dev/null
+++ b/src/test/run-pass/where-clause-bounds-inconsistency.rs
@@ -0,0 +1,28 @@
+// 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.
+
+trait Bound {}
+
+trait Trait {
+    fn a<T>(&self, T) where T: Bound;
+    fn b<T>(&self, T) where T: Bound;
+    fn c<T: Bound>(&self, T);
+    fn d<T: Bound>(&self, T);
+}
+
+impl Trait for bool {
+    fn a<T: Bound>(&self, _: T) {}
+    //^~ This gets rejected but should be accepted
+    fn b<T>(&self, _: T) where T: Bound {}
+    fn c<T: Bound>(&self, _: T) {}
+    fn d<T>(&self, _: T) where T: Bound {}
+}
+
+fn main() {}
diff --git a/src/test/run-pass/zero_sized_subslice_match.rs b/src/test/run-pass/zero_sized_subslice_match.rs
new file mode 100644
index 00000000000..65882d39375
--- /dev/null
+++ b/src/test/run-pass/zero_sized_subslice_match.rs
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = [(), ()];
+
+    // The subslice used to go out of bounds for zero-sized array items, check that this doesn't
+    // happen anymore
+    match x {
+        [_, y..] => assert_eq!(&x[1] as *const _, &y[0] as *const _)
+    }
+}