about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in2
-rw-r--r--mk/clean.mk5
-rw-r--r--mk/crates.mk7
-rw-r--r--mk/debuggers.mk101
-rw-r--r--mk/dist.mk99
-rw-r--r--mk/docs.mk3
-rw-r--r--mk/grammar.mk2
-rw-r--r--mk/install.mk6
-rw-r--r--mk/main.mk18
-rw-r--r--mk/prepare.mk28
-rw-r--r--mk/tests.mk9
-rw-r--r--src/compiletest/runtest.rs43
-rw-r--r--src/doc/guide-tasks.md112
-rw-r--r--src/doc/guide.md109
-rw-r--r--src/doc/index.md2
-rw-r--r--src/doc/intro.md2
-rw-r--r--src/doc/reference.md123
-rw-r--r--src/etc/gdb_load_rust_pretty_printers.py12
-rw-r--r--src/etc/kate/rust.xml3
-rw-r--r--src/etc/make-win-dist.py6
-rwxr-xr-xsrc/etc/rust-gdb23
-rw-r--r--src/grammar/README.md4
-rw-r--r--src/grammar/RustLexer.g459
-rwxr-xr-xsrc/grammar/check.sh17
-rw-r--r--src/grammar/verify.rs62
-rw-r--r--src/liballoc/arc.rs56
-rw-r--r--src/liballoc/boxed.rs6
-rw-r--r--src/liballoc/heap.rs4
-rw-r--r--src/liballoc/rc.rs19
-rw-r--r--src/libarena/lib.rs2
-rw-r--r--src/libcollections/binary_heap.rs48
-rw-r--r--src/libcollections/bit.rs190
-rw-r--r--src/libcollections/btree/map.rs67
-rw-r--r--src/libcollections/btree/node.rs101
-rw-r--r--src/libcollections/btree/set.rs64
-rw-r--r--src/libcollections/dlist.rs193
-rw-r--r--src/libcollections/enum_set.rs10
-rw-r--r--src/libcollections/lib.rs13
-rw-r--r--src/libcollections/ring_buf.rs100
-rw-r--r--src/libcollections/slice.rs1570
-rw-r--r--src/libcollections/str.rs341
-rw-r--r--src/libcollections/string.rs191
-rw-r--r--src/libcollections/vec.rs1459
-rw-r--r--src/libcollections/vec_map.rs136
-rw-r--r--src/libcore/array.rs48
-rw-r--r--src/libcore/atomic.rs2
-rw-r--r--src/libcore/borrow.rs4
-rw-r--r--src/libcore/cell.rs27
-rw-r--r--src/libcore/char.rs5
-rw-r--r--src/libcore/clone.rs2
-rw-r--r--src/libcore/cmp.rs148
-rw-r--r--src/libcore/fmt/float.rs19
-rw-r--r--src/libcore/fmt/mod.rs93
-rw-r--r--src/libcore/fmt/num.rs2
-rw-r--r--src/libcore/hash/mod.rs2
-rw-r--r--src/libcore/hash/sip.rs4
-rw-r--r--src/libcore/iter.rs97
-rw-r--r--src/libcore/macros.rs65
-rw-r--r--src/libcore/ops.rs111
-rw-r--r--src/libcore/panicking.rs49
-rw-r--r--src/libcore/prelude.rs8
-rw-r--r--src/libcore/ptr.rs151
-rw-r--r--src/libcore/result.rs2
-rw-r--r--src/libcore/slice.rs365
-rw-r--r--src/libcore/str/mod.rs (renamed from src/libcore/str.rs)259
-rw-r--r--src/libcore/tuple.rs8
-rw-r--r--src/libcoretest/any.rs6
-rw-r--r--src/libcoretest/atomic.rs1
-rw-r--r--src/libcoretest/char.rs4
-rw-r--r--src/libcoretest/hash/sip.rs4
-rw-r--r--src/libcoretest/iter.rs4
-rw-r--r--src/libcoretest/ops.rs8
-rw-r--r--src/libcoretest/ptr.rs4
-rw-r--r--src/libcoretest/slice.rs22
-rw-r--r--src/libflate/lib.rs2
-rw-r--r--src/libgetopts/lib.rs4
-rw-r--r--src/libgraphviz/lib.rs4
-rw-r--r--src/liblibc/lib.rs102
-rw-r--r--src/liblog/directive.rs2
-rw-r--r--src/liblog/lib.rs38
-rw-r--r--src/liblog/macros.rs57
-rw-r--r--src/librand/chacha.rs20
-rw-r--r--src/librand/distributions/exponential.rs2
-rw-r--r--src/librand/distributions/gamma.rs8
-rw-r--r--src/librand/distributions/mod.rs2
-rw-r--r--src/librand/distributions/normal.rs4
-rw-r--r--src/librand/distributions/range.rs2
-rw-r--r--src/librand/distributions/ziggurat_tables.rs10
-rw-r--r--src/librand/isaac.rs36
-rw-r--r--src/librand/lib.rs47
-rw-r--r--src/librand/rand_impls.rs6
-rw-r--r--src/librbml/io.rs5
-rw-r--r--src/librbml/lib.rs2
-rw-r--r--src/libregex/compile.rs3
-rw-r--r--src/libregex/parse.rs13
-rw-r--r--src/libregex/re.rs7
-rw-r--r--src/libregex/test/bench.rs23
-rw-r--r--src/libregex/vm.rs18
-rw-r--r--src/libregex_macros/lib.rs6
-rw-r--r--src/librustc/lint/builtin.rs39
-rw-r--r--src/librustc/metadata/common.rs3
-rw-r--r--src/librustc/metadata/creader.rs23
-rw-r--r--src/librustc/metadata/csearch.rs10
-rw-r--r--src/librustc/metadata/decoder.rs73
-rw-r--r--src/librustc/metadata/encoder.rs26
-rw-r--r--src/librustc/metadata/filesearch.rs21
-rw-r--r--src/librustc/metadata/tydecode.rs134
-rw-r--r--src/librustc/metadata/tyencode.rs45
-rw-r--r--src/librustc/middle/astconv_util.rs10
-rw-r--r--src/librustc/middle/astencode.rs73
-rw-r--r--src/librustc/middle/cfg/construct.rs9
-rw-r--r--src/librustc/middle/check_const.rs2
-rw-r--r--src/librustc/middle/check_match.rs24
-rw-r--r--src/librustc/middle/check_rvalues.rs14
-rw-r--r--src/librustc/middle/check_static.rs22
-rw-r--r--src/librustc/middle/dataflow.rs9
-rw-r--r--src/librustc/middle/def.rs5
-rw-r--r--src/librustc/middle/expr_use_visitor.rs58
-rw-r--r--src/librustc/middle/fast_reject.rs5
-rw-r--r--src/librustc/middle/graph.rs4
-rw-r--r--src/librustc/middle/infer/coercion.rs13
-rw-r--r--src/librustc/middle/infer/combine.rs100
-rw-r--r--src/librustc/middle/infer/error_reporting.rs25
-rw-r--r--src/librustc/middle/infer/freshen.rs1
-rw-r--r--src/librustc/middle/infer/mod.rs53
-rw-r--r--src/librustc/middle/infer/region_inference/graphviz.rs2
-rw-r--r--src/librustc/middle/infer/region_inference/mod.rs9
-rw-r--r--src/librustc/middle/infer/resolve.rs6
-rw-r--r--src/librustc/middle/infer/sub.rs2
-rw-r--r--src/librustc/middle/infer/unify.rs14
-rw-r--r--src/librustc/middle/intrinsicck.rs249
-rw-r--r--src/librustc/middle/lang_items.rs1
-rw-r--r--src/librustc/middle/liveness.rs43
-rw-r--r--src/librustc/middle/mem_categorization.rs96
-rw-r--r--src/librustc/middle/privacy.rs25
-rw-r--r--src/librustc/middle/region.rs3
-rw-r--r--src/librustc/middle/resolve_lifetime.rs8
-rw-r--r--src/librustc/middle/subst.rs76
-rw-r--r--src/librustc/middle/traits/coherence.rs11
-rw-r--r--src/librustc/middle/traits/error_reporting.rs306
-rw-r--r--src/librustc/middle/traits/fulfill.rs173
-rw-r--r--src/librustc/middle/traits/mod.rs120
-rw-r--r--src/librustc/middle/traits/project.rs674
-rw-r--r--src/librustc/middle/traits/select.rs535
-rw-r--r--src/librustc/middle/traits/util.rs135
-rw-r--r--src/librustc/middle/ty.rs1471
-rw-r--r--src/librustc/middle/ty_fold.rs89
-rw-r--r--src/librustc/session/config.rs15
-rw-r--r--src/librustc/session/mod.rs14
-rw-r--r--src/librustc/session/search_paths.rs69
-rw-r--r--src/librustc/util/lev_distance.rs2
-rw-r--r--src/librustc/util/ppaux.rs82
-rw-r--r--src/librustc_back/arm.rs12
-rw-r--r--src/librustc_back/mips.rs12
-rw-r--r--src/librustc_back/mipsel.rs12
-rw-r--r--src/librustc_back/sha2.rs63
-rw-r--r--src/librustc_back/svh.rs2
-rw-r--r--src/librustc_back/target/arm_apple_ios.rs2
-rw-r--r--src/librustc_back/target/arm_linux_androideabi.rs2
-rw-r--r--src/librustc_back/target/arm_unknown_linux_gnueabi.rs2
-rw-r--r--src/librustc_back/target/arm_unknown_linux_gnueabihf.rs2
-rw-r--r--src/librustc_back/target/i386_apple_ios.rs2
-rw-r--r--src/librustc_back/target/i686_apple_darwin.rs2
-rw-r--r--src/librustc_back/target/mips_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_back/target/mipsel_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_back/target/mod.rs2
-rw-r--r--src/librustc_back/target/x86_64_apple_darwin.rs2
-rw-r--r--src/librustc_back/target/x86_64_pc_windows_gnu.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_dragonfly.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_freebsd.rs2
-rw-r--r--src/librustc_back/target/x86_64_unknown_linux_gnu.rs2
-rw-r--r--src/librustc_back/x86.rs4
-rw-r--r--src/librustc_back/x86_64.rs14
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs2
-rw-r--r--src/librustc_borrowck/borrowck/doc.rs6
-rw-r--r--src/librustc_borrowck/borrowck/fragments.rs25
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs2
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs2
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs16
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_driver/driver.rs45
-rw-r--r--src/librustc_driver/lib.rs18
-rw-r--r--src/librustc_driver/pretty.rs4
-rw-r--r--src/librustc_driver/test.rs103
-rw-r--r--src/librustc_llvm/lib.rs3
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs1283
-rw-r--r--src/librustc_resolve/lib.rs1621
-rw-r--r--src/librustc_resolve/record_exports.rs4
-rw-r--r--src/librustc_trans/back/link.rs25
-rw-r--r--src/librustc_trans/back/write.rs15
-rw-r--r--src/librustc_trans/save/mod.rs126
-rw-r--r--src/librustc_trans/save/recorder.rs2
-rw-r--r--src/librustc_trans/save/span_utils.rs4
-rw-r--r--src/librustc_trans/trans/_match.rs28
-rw-r--r--src/librustc_trans/trans/adt.rs39
-rw-r--r--src/librustc_trans/trans/base.rs116
-rw-r--r--src/librustc_trans/trans/builder.rs6
-rw-r--r--src/librustc_trans/trans/cabi_x86_64.rs3
-rw-r--r--src/librustc_trans/trans/callee.rs14
-rw-r--r--src/librustc_trans/trans/cleanup.rs28
-rw-r--r--src/librustc_trans/trans/closure.rs57
-rw-r--r--src/librustc_trans/trans/common.rs278
-rw-r--r--src/librustc_trans/trans/consts.rs7
-rw-r--r--src/librustc_trans/trans/context.rs14
-rw-r--r--src/librustc_trans/trans/controlflow.rs2
-rw-r--r--src/librustc_trans/trans/datum.rs8
-rw-r--r--src/librustc_trans/trans/debuginfo.rs164
-rw-r--r--src/librustc_trans/trans/expr.rs151
-rw-r--r--src/librustc_trans/trans/foreign.rs13
-rw-r--r--src/librustc_trans/trans/glue.rs42
-rw-r--r--src/librustc_trans/trans/intrinsic.rs83
-rw-r--r--src/librustc_trans/trans/meth.rs32
-rw-r--r--src/librustc_trans/trans/monomorphize.rs67
-rw-r--r--src/librustc_trans/trans/tvec.rs2
-rw-r--r--src/librustc_trans/trans/type_.rs5
-rw-r--r--src/librustc_trans/trans/type_of.rs13
-rw-r--r--src/librustc_trans/trans/value.rs10
-rw-r--r--src/librustc_typeck/astconv.rs562
-rw-r--r--src/librustc_typeck/check/_match.rs66
-rw-r--r--src/librustc_typeck/check/assoc.rs41
-rw-r--r--src/librustc_typeck/check/closure.rs38
-rw-r--r--src/librustc_typeck/check/method/confirm.rs102
-rw-r--r--src/librustc_typeck/check/method/doc.rs18
-rw-r--r--src/librustc_typeck/check/method/mod.rs27
-rw-r--r--src/librustc_typeck/check/method/probe.rs26
-rw-r--r--src/librustc_typeck/check/mod.rs1201
-rw-r--r--src/librustc_typeck/check/regionck.rs14
-rw-r--r--src/librustc_typeck/check/regionmanip.rs22
-rw-r--r--src/librustc_typeck/check/vtable.rs186
-rw-r--r--src/librustc_typeck/check/wf.rs38
-rw-r--r--src/librustc_typeck/check/writeback.rs4
-rw-r--r--src/librustc_typeck/coherence/mod.rs21
-rw-r--r--src/librustc_typeck/coherence/orphan.rs4
-rw-r--r--src/librustc_typeck/collect.rs1160
-rw-r--r--src/librustc_typeck/lib.rs12
-rw-r--r--src/librustc_typeck/rscope.rs5
-rw-r--r--src/librustc_typeck/variance.rs129
-rw-r--r--src/librustdoc/clean/inline.rs5
-rw-r--r--src/librustdoc/clean/mod.rs107
-rw-r--r--src/librustdoc/core.rs5
-rw-r--r--src/librustdoc/doctree.rs1
-rw-r--r--src/librustdoc/html/format.rs26
-rw-r--r--src/librustdoc/html/highlight.rs2
-rw-r--r--src/librustdoc/html/markdown.rs2
-rw-r--r--src/librustdoc/html/render.rs11
-rw-r--r--src/librustdoc/html/static/main.css5
-rw-r--r--src/librustdoc/lib.rs19
-rw-r--r--src/librustdoc/markdown.rs4
-rw-r--r--src/librustdoc/test.rs16
-rw-r--r--src/librustdoc/visit_ast.rs3
-rw-r--r--src/libserialize/base64.rs8
-rw-r--r--src/libserialize/json.rs16
-rw-r--r--src/libstd/ascii.rs4
-rw-r--r--src/libstd/bitflags.rs15
-rw-r--r--src/libstd/c_str.rs6
-rw-r--r--src/libstd/c_vec.rs2
-rw-r--r--src/libstd/collections/hash/map.rs127
-rw-r--r--src/libstd/collections/hash/set.rs72
-rw-r--r--src/libstd/collections/hash/table.rs33
-rw-r--r--src/libstd/error.rs10
-rw-r--r--src/libstd/fmt.rs27
-rw-r--r--src/libstd/hash.rs2
-rw-r--r--src/libstd/io/buffered.rs15
-rw-r--r--src/libstd/io/comm_adapters.rs6
-rw-r--r--src/libstd/io/extensions.rs16
-rw-r--r--src/libstd/io/fs.rs34
-rw-r--r--src/libstd/io/mem.rs44
-rw-r--r--src/libstd/io/mod.rs57
-rw-r--r--src/libstd/io/net/addrinfo.rs11
-rw-r--r--src/libstd/io/net/ip.rs12
-rw-r--r--src/libstd/io/net/pipe.rs8
-rw-r--r--src/libstd/io/net/tcp.rs10
-rw-r--r--src/libstd/io/net/udp.rs8
-rw-r--r--src/libstd/io/pipe.rs2
-rw-r--r--src/libstd/io/process.rs1
-rw-r--r--src/libstd/io/stdio.rs42
-rw-r--r--src/libstd/io/test.rs2
-rw-r--r--src/libstd/io/timer.rs2
-rw-r--r--src/libstd/io/util.rs12
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libstd/macros.rs140
-rw-r--r--src/libstd/num/strconv.rs6
-rw-r--r--src/libstd/num/uint_macros.rs2
-rw-r--r--src/libstd/os.rs17
-rw-r--r--src/libstd/path/posix.rs20
-rw-r--r--src/libstd/path/windows.rs19
-rw-r--r--src/libstd/prelude/v1.rs7
-rw-r--r--src/libstd/rand/mod.rs90
-rw-r--r--src/libstd/rand/os.rs27
-rw-r--r--src/libstd/rand/reader.rs4
-rw-r--r--src/libstd/rt/args.rs4
-rw-r--r--src/libstd/rt/backtrace.rs6
-rw-r--r--src/libstd/rt/libunwind.rs2
-rw-r--r--src/libstd/rt/macros.rs18
-rw-r--r--src/libstd/rt/mod.rs6
-rw-r--r--src/libstd/rt/task.rs132
-rw-r--r--src/libstd/rt/unwind.rs73
-rw-r--r--src/libstd/rt/util.rs20
-rw-r--r--src/libstd/sync/atomic.rs2
-rw-r--r--src/libstd/sync/barrier.rs4
-rw-r--r--src/libstd/sync/condvar.rs124
-rw-r--r--src/libstd/sync/mod.rs7
-rw-r--r--src/libstd/sync/mpsc/mod.rs2
-rw-r--r--src/libstd/sync/mpsc/shared.rs4
-rw-r--r--src/libstd/sync/mpsc/sync.rs28
-rw-r--r--src/libstd/sync/mutex.rs236
-rw-r--r--src/libstd/sync/poison.rs122
-rw-r--r--src/libstd/sync/rwlock.rs310
-rw-r--r--src/libstd/sync/semaphore.rs6
-rw-r--r--src/libstd/sync/task_pool.rs34
-rw-r--r--src/libstd/sys/common/backtrace.rs8
-rw-r--r--src/libstd/sys/common/helper_thread.rs11
-rw-r--r--src/libstd/sys/common/net.rs44
-rw-r--r--src/libstd/sys/common/thread_info.rs4
-rw-r--r--src/libstd/sys/unix/backtrace.rs6
-rw-r--r--src/libstd/sys/unix/c.rs18
-rw-r--r--src/libstd/sys/unix/fs.rs2
-rw-r--r--src/libstd/sys/unix/mod.rs3
-rw-r--r--src/libstd/sys/unix/os.rs6
-rw-r--r--src/libstd/sys/unix/pipe.rs2
-rw-r--r--src/libstd/sys/unix/process.rs8
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs4
-rw-r--r--src/libstd/sys/unix/sync.rs28
-rw-r--r--src/libstd/sys/unix/timer.rs10
-rw-r--r--src/libstd/sys/windows/backtrace.rs24
-rw-r--r--src/libstd/sys/windows/c.rs14
-rw-r--r--src/libstd/sys/windows/fs.rs4
-rw-r--r--src/libstd/sys/windows/mod.rs4
-rw-r--r--src/libstd/sys/windows/os.rs29
-rw-r--r--src/libstd/sys/windows/process.rs5
-rw-r--r--src/libstd/sys/windows/stack_overflow.rs2
-rw-r--r--src/libstd/sys/windows/timer.rs5
-rw-r--r--src/libstd/sys/windows/tty.rs21
-rw-r--r--src/libstd/thread.rs9
-rw-r--r--src/libstd/thread_local/mod.rs36
-rw-r--r--src/libstd/thread_local/scoped.rs18
-rw-r--r--src/libstd/time/duration.rs14
-rw-r--r--src/libsyntax/ast.rs20
-rw-r--r--src/libsyntax/ast_map/mod.rs8
-rw-r--r--src/libsyntax/ast_util.rs54
-rw-r--r--src/libsyntax/codemap.rs32
-rw-r--r--src/libsyntax/config.rs4
-rw-r--r--src/libsyntax/diagnostics/plugin.rs2
-rw-r--r--src/libsyntax/ext/base.rs6
-rw-r--r--src/libsyntax/ext/build.rs5
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs4
-rw-r--r--src/libsyntax/ext/deriving/default.rs2
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs3
-rw-r--r--src/libsyntax/ext/deriving/generic/ty.rs17
-rw-r--r--src/libsyntax/ext/deriving/hash.rs4
-rw-r--r--src/libsyntax/ext/deriving/mod.rs4
-rw-r--r--src/libsyntax/ext/deriving/rand.rs1
-rw-r--r--src/libsyntax/ext/deriving/zero.rs2
-rw-r--r--src/libsyntax/ext/expand.rs6
-rw-r--r--src/libsyntax/ext/format.rs16
-rw-r--r--src/libsyntax/ext/quote.rs4
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs5
-rw-r--r--src/libsyntax/feature_gate.rs127
-rw-r--r--src/libsyntax/fold.rs16
-rw-r--r--src/libsyntax/parse/mod.rs10
-rw-r--r--src/libsyntax/parse/parser.rs147
-rw-r--r--src/libsyntax/parse/token.rs2
-rw-r--r--src/libsyntax/print/pp.rs7
-rw-r--r--src/libsyntax/print/pprust.rs49
-rw-r--r--src/libsyntax/std_inject.rs2
-rw-r--r--src/libsyntax/test.rs6
-rw-r--r--src/libsyntax/visit.rs32
-rw-r--r--src/libterm/lib.rs2
-rw-r--r--src/libterm/terminfo/parm.rs11
-rw-r--r--src/libterm/win.rs8
-rw-r--r--src/libtest/lib.rs6
-rw-r--r--src/libtime/lib.rs5
-rw-r--r--src/libunicode/normalize.rs41
-rw-r--r--src/libunicode/tables.rs36
-rw-r--r--src/libunicode/u_str.rs15
m---------src/rust-installer0
-rw-r--r--src/rustllvm/RustWrapper.cpp12
-rw-r--r--src/snapshots.txt9
-rw-r--r--src/test/auxiliary/associated-types-cc-lib.rs27
-rw-r--r--src/test/bench/core-std.rs8
-rw-r--r--src/test/bench/msgsend-ring-mutex-arcs.rs6
-rw-r--r--src/test/bench/shootout-fannkuch-redux.rs4
-rw-r--r--src/test/bench/shootout-fasta-redux.rs2
-rw-r--r--src/test/bench/shootout-reverse-complement.rs17
-rw-r--r--src/test/bench/shootout-spectralnorm.rs1
-rw-r--r--src/test/compile-fail/array-old-syntax-1.rs15
-rw-r--r--src/test/compile-fail/array-old-syntax-2.rs15
-rw-r--r--src/test/compile-fail/associated-types-bound-failure.rs39
-rw-r--r--src/test/compile-fail/associated-types-eq-1.rs (renamed from src/test/compile-fail/assoc-eq-1.rs)0
-rw-r--r--src/test/compile-fail/associated-types-eq-2.rs (renamed from src/test/compile-fail/assoc-eq-2.rs)3
-rw-r--r--src/test/compile-fail/associated-types-eq-3.rs (renamed from src/test/compile-fail/assoc-eq-3.rs)4
-rw-r--r--src/test/compile-fail/associated-types-eq-expr-path.rs (renamed from src/test/compile-fail/assoc-eq-expr-path.rs)0
-rw-r--r--src/test/compile-fail/associated-types-eq-hr.rs72
-rw-r--r--src/test/compile-fail/associated-types-for-unimpl-trait.rs25
-rw-r--r--src/test/compile-fail/associated-types-in-ambiguous-context.rs10
-rw-r--r--src/test/compile-fail/associated-types-incomplete-object.rs44
-rw-r--r--src/test/compile-fail/associated-types-issue-20346.rs46
-rw-r--r--src/test/compile-fail/associated-types-no-suitable-bound.rs (renamed from src/test/compile-fail/associated-types-in-wrong-context.rs)5
-rw-r--r--src/test/compile-fail/associated-types-no-suitable-supertrait.rs31
-rw-r--r--src/test/compile-fail/associated-types-path-1.rs (renamed from src/test/compile-fail/assoc-path-1.rs)0
-rw-r--r--src/test/compile-fail/associated-types-path-2.rs (renamed from src/test/compile-fail/assoc-path-2.rs)30
-rw-r--r--src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs28
-rw-r--r--src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs38
-rw-r--r--src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs47
-rw-r--r--src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs36
-rw-r--r--src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs35
-rw-r--r--src/test/compile-fail/associated-types-unconstrained.rs28
-rw-r--r--src/test/compile-fail/better-expected.rs2
-rw-r--r--src/test/compile-fail/double-type-import.rs24
-rw-r--r--src/test/compile-fail/duplicate-trait-bounds.rs15
-rw-r--r--src/test/compile-fail/feature-gated-feature-in-macro-arg.rs24
-rw-r--r--src/test/compile-fail/import-shadow-1.rs31
-rw-r--r--src/test/compile-fail/import-shadow-2.rs31
-rw-r--r--src/test/compile-fail/import-shadow-3.rs31
-rw-r--r--src/test/compile-fail/import-shadow-4.rs31
-rw-r--r--src/test/compile-fail/import-shadow-5.rs31
-rw-r--r--src/test/compile-fail/import-shadow-6.rs31
-rw-r--r--src/test/compile-fail/import-shadow-7.rs31
-rw-r--r--src/test/compile-fail/issue-12028.rs (renamed from src/test/run-pass/issue-12028.rs)7
-rw-r--r--src/test/compile-fail/issue-13853-2.rs16
-rw-r--r--src/test/compile-fail/issue-13853-3.rs33
-rw-r--r--src/test/compile-fail/issue-13853-4.rs21
-rw-r--r--src/test/compile-fail/issue-13853-5.rs23
-rw-r--r--src/test/compile-fail/issue-13853.rs45
-rw-r--r--src/test/compile-fail/issue-14227.rs16
-rw-r--r--src/test/compile-fail/issue-15034.rs32
-rw-r--r--src/test/compile-fail/issue-15756.rs4
-rw-r--r--src/test/compile-fail/issue-15965.rs2
-rw-r--r--src/test/compile-fail/issue-16538.rs25
-rw-r--r--src/test/compile-fail/issue-16966.rs3
-rw-r--r--src/test/compile-fail/issue-17728.rs132
-rw-r--r--src/test/compile-fail/issue-17740.rs22
-rw-r--r--src/test/compile-fail/issue-17913.rs4
-rw-r--r--src/test/compile-fail/issue-18345.rs1
-rw-r--r--src/test/compile-fail/issue-18532.rs1
-rw-r--r--src/test/compile-fail/issue-18611.rs7
-rw-r--r--src/test/compile-fail/issue-19707.rs20
-rw-r--r--src/test/compile-fail/issue-5543.rs16
-rw-r--r--src/test/compile-fail/issue-6977.rs2
-rw-r--r--src/test/compile-fail/issue-7364.rs5
-rw-r--r--src/test/compile-fail/mut-not-freeze.rs1
-rw-r--r--src/test/compile-fail/range-1.rs1
-rw-r--r--src/test/compile-fail/range-2.rs1
-rw-r--r--src/test/compile-fail/removed-syntax-fixed-vec.rs2
-rw-r--r--src/test/compile-fail/removed-syntax-mut-vec-ty.rs2
-rw-r--r--src/test/compile-fail/resolve-conflict-type-vs-import.rs1
-rw-r--r--src/test/compile-fail/resolve-label.rs21
-rw-r--r--src/test/compile-fail/slice-2.rs4
-rw-r--r--src/test/compile-fail/slice-mut-2.rs3
-rw-r--r--src/test/compile-fail/slice-mut.rs5
-rw-r--r--src/test/compile-fail/task-rng-isnt-sendable.rs4
-rw-r--r--src/test/compile-fail/trait-bounds-on-structs-and-enums.rs8
-rw-r--r--src/test/compile-fail/trait-object-safety.rs25
-rw-r--r--src/test/compile-fail/trait-static-method-generic-inference.rs37
-rw-r--r--src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs2
-rw-r--r--src/test/compile-fail/transmute-different-sizes.rs2
-rw-r--r--src/test/compile-fail/transmute-fat-pointers.rs41
-rw-r--r--src/test/compile-fail/transmute-impl.rs33
-rw-r--r--src/test/compile-fail/unsized-inherent-impl-self-type.rs20
-rw-r--r--src/test/compile-fail/unsized-trait-impl-self-type.rs22
-rw-r--r--src/test/compile-fail/unsized-trait-impl-trait-arg.rs21
-rw-r--r--src/test/compile-fail/unsized4.rs3
-rw-r--r--src/test/compile-fail/unsized7.rs19
-rw-r--r--src/test/compile-fail/variance-regions-direct.rs14
-rw-r--r--src/test/compile-fail/variance-regions-indirect.rs10
-rw-r--r--src/test/compile-fail/variance-trait-object-bound.rs2
-rw-r--r--src/test/debuginfo/basic-types-globals-metadata.rs1
-rw-r--r--src/test/debuginfo/basic-types-globals.rs1
-rw-r--r--src/test/debuginfo/basic-types-metadata.rs1
-rw-r--r--src/test/debuginfo/basic-types-mut-globals.rs1
-rw-r--r--src/test/debuginfo/basic-types.rs1
-rw-r--r--src/test/debuginfo/borrowed-basic.rs1
-rw-r--r--src/test/debuginfo/borrowed-c-style-enum.rs1
-rw-r--r--src/test/debuginfo/borrowed-enum.rs1
-rw-r--r--src/test/debuginfo/borrowed-struct.rs1
-rw-r--r--src/test/debuginfo/borrowed-tuple.rs1
-rw-r--r--src/test/debuginfo/borrowed-unique-basic.rs2
-rw-r--r--src/test/debuginfo/box.rs1
-rw-r--r--src/test/debuginfo/boxed-struct.rs1
-rw-r--r--src/test/debuginfo/by-value-non-immediate-argument.rs2
-rw-r--r--src/test/debuginfo/by-value-self-argument-in-trait-impl.rs2
-rw-r--r--src/test/debuginfo/c-style-enum-in-composite.rs1
-rw-r--r--src/test/debuginfo/c-style-enum.rs1
-rw-r--r--src/test/debuginfo/closure-in-generic-function.rs2
-rw-r--r--src/test/debuginfo/destructured-fn-argument.rs1
-rw-r--r--src/test/debuginfo/destructured-for-loop-variable.rs3
-rw-r--r--src/test/debuginfo/destructured-local.rs1
-rw-r--r--src/test/debuginfo/evec-in-struct.rs1
-rw-r--r--src/test/debuginfo/function-arg-initialization.rs4
-rw-r--r--src/test/debuginfo/function-arguments.rs3
-rw-r--r--src/test/debuginfo/function-prologue-stepping-no-stack-check.rs1
-rw-r--r--src/test/debuginfo/function-prologue-stepping-regular.rs1
-rw-r--r--src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs1
-rw-r--r--src/test/debuginfo/gdb-pretty-struct-and-enums.rs1
-rw-r--r--src/test/debuginfo/generic-function.rs1
-rw-r--r--src/test/debuginfo/generic-functions-nested.rs3
-rw-r--r--src/test/debuginfo/generic-method-on-generic-struct.rs1
-rw-r--r--src/test/debuginfo/generic-static-method-on-struct-and-enum.rs3
-rw-r--r--src/test/debuginfo/generic-struct-style-enum.rs3
-rw-r--r--src/test/debuginfo/generic-struct.rs3
-rw-r--r--src/test/debuginfo/generic-trait-generic-static-default-method.rs1
-rw-r--r--src/test/debuginfo/generic-tuple-style-enum.rs2
-rw-r--r--src/test/debuginfo/include_string.rs1
-rw-r--r--src/test/debuginfo/issue12886.rs4
-rw-r--r--src/test/debuginfo/lexical-scope-in-for-loop.rs2
-rw-r--r--src/test/debuginfo/lexical-scope-in-if.rs1
-rw-r--r--src/test/debuginfo/lexical-scope-in-match.rs1
-rw-r--r--src/test/debuginfo/lexical-scope-in-stack-closure.rs2
-rw-r--r--src/test/debuginfo/lexical-scope-in-unconditional-loop.rs2
-rw-r--r--src/test/debuginfo/lexical-scope-in-unique-closure.rs3
-rw-r--r--src/test/debuginfo/lexical-scope-in-while.rs1
-rw-r--r--src/test/debuginfo/lexical-scope-with-macro.rs1
-rw-r--r--src/test/debuginfo/lexical-scopes-in-block-expression.rs1
-rw-r--r--src/test/debuginfo/limited-debuginfo.rs1
-rw-r--r--src/test/debuginfo/method-on-enum.rs2
-rw-r--r--src/test/debuginfo/method-on-generic-struct.rs2
-rw-r--r--src/test/debuginfo/method-on-struct.rs3
-rw-r--r--src/test/debuginfo/method-on-trait.rs3
-rw-r--r--src/test/debuginfo/method-on-tuple-struct.rs3
-rw-r--r--src/test/debuginfo/multiple-functions-equal-var-names.rs1
-rw-r--r--src/test/debuginfo/multiple-functions.rs1
-rw-r--r--src/test/debuginfo/name-shadowing-and-scope-nesting.rs2
-rw-r--r--src/test/debuginfo/nil-enum.rs1
-rw-r--r--src/test/debuginfo/no-debug-attribute.rs1
-rw-r--r--src/test/debuginfo/option-like-enum.rs2
-rw-r--r--src/test/debuginfo/packed-struct-with-destructor.rs1
-rw-r--r--src/test/debuginfo/packed-struct.rs1
-rw-r--r--src/test/debuginfo/recursive-enum.rs1
-rw-r--r--src/test/debuginfo/recursive-struct.rs1
-rw-r--r--src/test/debuginfo/self-in-default-method.rs1
-rw-r--r--src/test/debuginfo/self-in-generic-default-method.rs1
-rw-r--r--src/test/debuginfo/shadowed-argument.rs3
-rw-r--r--src/test/debuginfo/shadowed-variable.rs2
-rw-r--r--src/test/debuginfo/simd.rs1
-rw-r--r--src/test/debuginfo/simple-lexical-scope.rs3
-rw-r--r--src/test/debuginfo/simple-struct.rs5
-rw-r--r--src/test/debuginfo/simple-tuple.rs1
-rw-r--r--src/test/debuginfo/static-method-on-struct-and-enum.rs2
-rw-r--r--src/test/debuginfo/struct-in-enum.rs1
-rw-r--r--src/test/debuginfo/struct-in-struct.rs1
-rw-r--r--src/test/debuginfo/struct-style-enum.rs1
-rw-r--r--src/test/debuginfo/struct-with-destructor.rs1
-rw-r--r--src/test/debuginfo/trait-generic-static-default-method.rs2
-rw-r--r--src/test/debuginfo/trait-pointers.rs1
-rw-r--r--src/test/debuginfo/tuple-in-struct.rs1
-rw-r--r--src/test/debuginfo/tuple-in-tuple.rs1
-rw-r--r--src/test/debuginfo/tuple-struct.rs3
-rw-r--r--src/test/debuginfo/tuple-style-enum.rs1
-rw-r--r--src/test/debuginfo/type-names.rs2
-rw-r--r--src/test/debuginfo/unique-enum.rs1
-rw-r--r--src/test/debuginfo/var-captured-in-nested-closure.rs1
-rw-r--r--src/test/debuginfo/var-captured-in-sendable-closure.rs1
-rw-r--r--src/test/debuginfo/var-captured-in-stack-closure.rs1
-rw-r--r--src/test/debuginfo/vec-slices.rs1
-rw-r--r--src/test/debuginfo/vec.rs1
-rw-r--r--src/test/pretty/issue-4264.rs18
-rw-r--r--src/test/run-fail/issue-6458-1.rs (renamed from src/test/compile-fail/issue-6458-1.rs)3
-rw-r--r--src/test/run-make/compiler-lookup-paths/Makefile30
-rw-r--r--src/test/run-make/compiler-lookup-paths/a.rs11
-rw-r--r--src/test/run-make/compiler-lookup-paths/b.rs12
-rw-r--r--src/test/run-make/compiler-lookup-paths/c.rs13
-rw-r--r--src/test/run-make/compiler-lookup-paths/d.rs14
-rw-r--r--src/test/run-make/compiler-lookup-paths/e.rs12
-rw-r--r--src/test/run-make/compiler-lookup-paths/f.rs12
-rw-r--r--src/test/run-make/compiler-lookup-paths/native.c0
-rw-r--r--src/test/run-make/staticlib-blank-lib/Makefile4
-rw-r--r--src/test/run-make/unicode-input/multiple_files.rs4
-rw-r--r--src/test/run-make/unicode-input/span_length.rs6
-rw-r--r--src/test/run-pass/associated-types-basic.rs26
-rw-r--r--src/test/run-pass/associated-types-binding-in-where-clause.rs47
-rw-r--r--src/test/run-pass/associated-types-bound.rs53
-rw-r--r--src/test/run-pass/associated-types-cc.rs28
-rw-r--r--src/test/run-pass/associated-types-constant-type.rs42
-rw-r--r--src/test/run-pass/associated-types-eq-obj.rs34
-rw-r--r--src/test/run-pass/associated-types-impl-redirect.rs58
-rw-r--r--src/test/run-pass/associated-types-issue-20371.rs17
-rw-r--r--src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs41
-rw-r--r--src/test/run-pass/associated-types-normalize-in-bounds.rs41
-rw-r--r--src/test/run-pass/associated-types-projection-bound-in-supertraits.rs33
-rw-r--r--src/test/run-pass/associated-types-return.rs (renamed from src/test/run-pass/assoc-eq.rs)11
-rw-r--r--src/test/run-pass/associated-types-sugar-path.rs (renamed from src/test/run-pass/assoc-sugar-path.rs)0
-rw-r--r--src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs54
-rw-r--r--src/test/run-pass/dst-raw.rs2
-rw-r--r--src/test/run-pass/dst-struct-sole.rs2
-rw-r--r--src/test/run-pass/dst-struct.rs2
-rw-r--r--src/test/run-pass/dst-trait.rs2
-rw-r--r--src/test/run-pass/enum-null-pointer-opt.rs2
-rw-r--r--src/test/run-pass/foreach-external-iterators-break.rs2
-rw-r--r--src/test/run-pass/foreach-external-iterators-loop.rs2
-rw-r--r--src/test/run-pass/foreach-external-iterators-nested.rs4
-rw-r--r--src/test/run-pass/foreach-external-iterators.rs2
-rw-r--r--src/test/run-pass/inconsistent-lifetime-mismatch.rs21
-rw-r--r--src/test/run-pass/integer-literal-suffix-inference-2.rs (renamed from src/test/compile-fail/integer-literal-suffix-inference-2.rs)2
-rw-r--r--src/test/run-pass/integer-literal-suffix-inference-3.rs (renamed from src/test/compile-fail/integer-literal-suffix-inference-3.rs)1
-rw-r--r--src/test/run-pass/issue-11382.rs (renamed from src/test/compile-fail/issue-11382.rs)5
-rw-r--r--src/test/run-pass/issue-12684.rs3
-rw-r--r--src/test/run-pass/issue-13655.rs (renamed from src/test/run-pass/multidispatch-infer-from-single-impl.rs)25
-rw-r--r--src/test/run-pass/issue-13665.rs22
-rw-r--r--src/test/run-pass/issue-13808.rs (renamed from src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs)24
-rw-r--r--src/test/run-pass/issue-15155.rs2
-rw-r--r--src/test/run-pass/issue-15730.rs (renamed from src/test/compile-fail/issue-15730.rs)1
-rw-r--r--src/test/run-pass/issue-16783.rs (renamed from src/test/compile-fail/issue-16783.rs)1
-rw-r--r--src/test/run-pass/issue-17361.rs2
-rw-r--r--src/test/run-pass/issue-18906.rs36
-rw-r--r--src/test/run-pass/issue-19081.rs (renamed from src/test/compile-fail/issue-19081.rs)8
-rw-r--r--src/test/run-pass/issue-19121.rs (renamed from src/test/compile-fail/issue-19121.rs)4
-rw-r--r--src/test/run-pass/issue-7663.rs16
-rw-r--r--src/test/run-pass/match-ref-binding-in-guard-3256.rs14
-rw-r--r--src/test/run-pass/method-recursive-blanket-impl.rs2
-rw-r--r--src/test/run-pass/range.rs4
-rw-r--r--src/test/run-pass/tcp-connect-timeouts.rs1
-rw-r--r--src/test/run-pass/tcp-stress.rs11
-rw-r--r--src/test/run-pass/trait-object-safety.rs11
-rw-r--r--src/test/run-pass/traits-multidispatch-infer-convert-target.rs7
-rw-r--r--src/test/run-pass/transmute-non-immediate-to-immediate.rs2
-rw-r--r--src/test/run-pass/type-sizes.rs2
-rw-r--r--src/test/run-pass/unsized.rs29
-rw-r--r--src/test/run-pass/unsized2.rs24
-rw-r--r--src/test/run-pass/vector-sort-panic-safe.rs4
-rw-r--r--src/test/run-pass/writealias.rs14
622 files changed, 15778 insertions, 11031 deletions
diff --git a/Makefile.in b/Makefile.in
index 17ae845bf07..a2394101f3a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -99,7 +99,7 @@
 # This is hardly all there is to know of The Rust Build System's
 # mysteries. The tale continues on the wiki[1][2].
 #
-# [1]: https://github.com/rust-lang/rust/wiki/Note-build-system
+# [1]: https://github.com/rust-lang/rust/wiki/Note-getting-started-developing-Rust
 # [2]: https://github.com/rust-lang/rust/wiki/Note-testsuite
 #
 # If you really feel like getting your hands dirty, then:
diff --git a/mk/clean.mk b/mk/clean.mk
index aadc55ba6c4..5b90d41ceec 100644
--- a/mk/clean.mk
+++ b/mk/clean.mk
@@ -64,6 +64,7 @@ clean-generic-$(2)-$(1):
          -name '*.dll' -o \
          -name '*.def' -o \
          -name '*.py' -o \
+         -name '*.pyc' -o \
          -name '*.bc' \
          \) \
          | xargs rm -f
@@ -79,7 +80,7 @@ define CLEAN_HOST_STAGE_N
 
 clean$(1)_H_$(2): \
 	    $$(foreach crate,$$(CRATES),clean$(1)_H_$(2)-lib-$$(crate)) \
-	    $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS),clean$(1)_H_$(2)-tool-$$(tool))
+	    $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS_ALL),clean$(1)_H_$(2)-tool-$$(tool))
 	$$(Q)rm -fr $(2)/rt/libbacktrace
 
 clean$(1)_H_$(2)-tool-%:
@@ -99,7 +100,7 @@ define CLEAN_TARGET_STAGE_N
 
 clean$(1)_T_$(2)_H_$(3): \
 	    $$(foreach crate,$$(CRATES),clean$(1)_T_$(2)_H_$(3)-lib-$$(crate)) \
-	    $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS),clean$(1)_T_$(2)_H_$(3)-tool-$$(tool))
+	    $$(foreach tool,$$(TOOLS) $$(DEBUGGER_BIN_SCRIPTS_ALL),clean$(1)_T_$(2)_H_$(3)-tool-$$(tool))
 	$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a
 	$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a
 	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/librun_pass_stage* # For unix
diff --git a/mk/crates.mk b/mk/crates.mk
index e20cb06e3a8..c3b31e60f19 100644
--- a/mk/crates.mk
+++ b/mk/crates.mk
@@ -122,7 +122,12 @@ DOC_CRATES := $(filter-out rustc, \
               $(filter-out rustc_borrowck, \
               $(filter-out rustc_resolve, \
               $(filter-out rustc_driver, \
-              $(filter-out syntax, $(CRATES))))))))
+              $(filter-out log, \
+              $(filter-out regex, \
+              $(filter-out regex_macros, \
+              $(filter-out getopts, \
+              $(filter-out time, \
+              $(filter-out syntax, $(CRATES)))))))))))))
 COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \
                        rustc_typeck rustc_driver syntax
 
diff --git a/mk/debuggers.mk b/mk/debuggers.mk
index 54955f06295..899cc42d066 100644
--- a/mk/debuggers.mk
+++ b/mk/debuggers.mk
@@ -12,26 +12,77 @@
 # Copy debugger related scripts
 ######################################################################
 
-DEBUGGER_RUSTLIB_ETC_SCRIPTS=lldb_rust_formatters.py
-DEBUGGER_BIN_SCRIPTS=rust-lldb
 
-DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS=$(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS), \
-                                     $(CFG_SRC_DIR)src/etc/$(script))
-DEBUGGER_BIN_SCRIPTS_ABS=$(foreach script,$(DEBUGGER_BIN_SCRIPTS), \
-                             $(CFG_SRC_DIR)src/etc/$(script))
+## GDB ##
+DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB=gdb_load_rust_pretty_printers.py \
+                                 gdb_rust_pretty_printing.py
+DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS=\
+    $(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB), \
+        $(CFG_SRC_DIR)src/etc/$(script))
+
+DEBUGGER_BIN_SCRIPTS_GDB=rust-gdb
+DEBUGGER_BIN_SCRIPTS_GDB_ABS=\
+    $(foreach script,$(DEBUGGER_BIN_SCRIPTS_GDB), \
+        $(CFG_SRC_DIR)src/etc/$(script))
+
+
+## LLDB ##
+DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB=lldb_rust_formatters.py
+DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS=\
+    $(foreach script,$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB), \
+        $(CFG_SRC_DIR)src/etc/$(script))
+
+DEBUGGER_BIN_SCRIPTS_LLDB=rust-lldb
+DEBUGGER_BIN_SCRIPTS_LLDB_ABS=\
+    $(foreach script,$(DEBUGGER_BIN_SCRIPTS_LLDB), \
+        $(CFG_SRC_DIR)src/etc/$(script))
+
+
+## ALL ##
+DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL=$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB) \
+                                 $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB)
+DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS=$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \
+                                     $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS)
+DEBUGGER_BIN_SCRIPTS_ALL=$(DEBUGGER_BIN_SCRIPTS_GDB) \
+                         $(DEBUGGER_BIN_SCRIPTS_LLDB)
+DEBUGGER_BIN_SCRIPTS_ALL_ABS=$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) \
+                             $(DEBUGGER_BIN_SCRIPTS_LLDB_ABS)
 
-DEBUGGER_SCRIPTS_ALL=$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $(DEBUGGER_BIN_SCRIPTS_ABS)
 
 # $(1) - the stage to copy to
 # $(2) - the host triple
 define DEF_INSTALL_DEBUGGER_SCRIPTS_HOST
 
-tmp/install-debugger-scripts$(1)_H_$(2).done: $$(DEBUGGER_SCRIPTS_ALL)
+tmp/install-debugger-scripts$(1)_H_$(2)-gdb.done: \
+  $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \
+  $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS)
+	$(Q)mkdir -p $$(HBIN$(1)_H_$(2))
+	$(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc
+	$(Q)install $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $$(HBIN$(1)_H_$(2))
+	$(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc
+	$(Q)touch $$@
+
+tmp/install-debugger-scripts$(1)_H_$(2)-lldb.done: \
+  $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) \
+  $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS)
+	$(Q)mkdir -p $$(HBIN$(1)_H_$(2))
+	$(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc
+	$(Q)install $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $$(HBIN$(1)_H_$(2))
+	$(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc
+	$(Q)touch $$@
+
+tmp/install-debugger-scripts$(1)_H_$(2)-all.done: \
+  $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) \
+  $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS)
 	$(Q)mkdir -p $$(HBIN$(1)_H_$(2))
 	$(Q)mkdir -p $$(HLIB$(1)_H_$(2))/rustlib/etc
-	$(Q)install $(DEBUGGER_BIN_SCRIPTS_ABS) $$(HBIN$(1)_H_$(2))
-	$(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc
+	$(Q)install $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) $$(HBIN$(1)_H_$(2))
+	$(Q)install $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) $$(HLIB$(1)_H_$(2))/rustlib/etc
 	$(Q)touch $$@
+
+tmp/install-debugger-scripts$(1)_H_$(2)-none.done:
+	$(Q)touch $$@
+
 endef
 
 # Expand host make-targets for all stages
@@ -44,12 +95,36 @@ $(foreach stage,$(STAGES), \
 # $(3) is the host triple
 define DEF_INSTALL_DEBUGGER_SCRIPTS_TARGET
 
-tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3).done: $$(DEBUGGER_SCRIPTS_ALL)
+tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-gdb.done: \
+  $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) \
+  $$(DEBUGGER_BIN_SCRIPTS_GDB_ABS)
+	$(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3))
+	$(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc
+	$(Q)install $(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $$(TBIN$(1)_T_$(2)_H_$(3))
+	$(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc
+	$(Q)touch $$@
+
+tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-lldb.done: \
+  $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) \
+  $$(DEBUGGER_BIN_SCRIPTS_LLDB_ABS)
 	$(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3))
 	$(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc
-	$(Q)install $(DEBUGGER_BIN_SCRIPTS_ABS) $$(TBIN$(1)_T_$(2)_H_$(3))
-	$(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc
+	$(Q)install $(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $$(TBIN$(1)_T_$(2)_H_$(3))
+	$(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc
 	$(Q)touch $$@
+
+tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-all.done: \
+  $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) \
+  $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS)
+	$(Q)mkdir -p $$(TBIN$(1)_T_$(2)_H_$(3))
+	$(Q)mkdir -p $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc
+	$(Q)install $(DEBUGGER_BIN_SCRIPTS_ALL_ABS) $$(TBIN$(1)_T_$(2)_H_$(3))
+	$(Q)install $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS) $$(TLIB$(1)_T_$(2)_H_$(3))/rustlib/etc
+	$(Q)touch $$@
+
+tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-none.done:
+	$(Q)touch $$@
+
 endef
 
 # Expand target make-targets for all stages
diff --git a/mk/dist.mk b/mk/dist.mk
index bdda15dcc18..a8b331c6cc2 100644
--- a/mk/dist.mk
+++ b/mk/dist.mk
@@ -23,6 +23,8 @@
 # * dist-docs - Stage docs for upload
 
 PKG_NAME := $(CFG_PACKAGE_NAME)
+DOC_PKG_NAME := rust-docs-$(CFG_PACKAGE_VERS)
+MINGW_PKG_NAME := rust-mingw-$(CFG_PACKAGE_VERS)
 
 # License suitable for displaying in a popup
 LICENSE.txt: $(S)COPYRIGHT $(S)LICENSE-APACHE $(S)LICENSE-MIT
@@ -33,7 +35,7 @@ LICENSE.txt: $(S)COPYRIGHT $(S)LICENSE-APACHE $(S)LICENSE-MIT
 # Source tarball
 ######################################################################
 
-PKG_TAR = dist/$(PKG_NAME).tar.gz
+PKG_TAR = dist/$(PKG_NAME)-src.tar.gz
 
 PKG_GITMODULES := $(S)src/llvm $(S)src/compiler-rt \
 		  $(S)src/rt/hoedown $(S)src/jemalloc
@@ -229,10 +231,20 @@ dist-install-dir-$(1): prepare-base-dir-$(1) docs compiler-docs
 	$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)
 	$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-MIT $$(PREPARE_DEST_DIR)
 	$$(Q)$$(PREPARE_MAN_CMD) $$(S)README.md $$(PREPARE_DEST_DIR)
-	$$(Q)[ ! -d doc ] || cp -r doc $$(PREPARE_DEST_DIR)
+	$$(Q)mkdir -p $$(PREPARE_DEST_DIR)/share/doc/rust
+	$$(Q)$$(PREPARE_MAN_CMD) $$(S)COPYRIGHT $$(PREPARE_DEST_DIR)/share/doc/rust
+	$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)/share/doc/rust
+	$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-MIT $$(PREPARE_DEST_DIR)/share/doc/rust
+	$$(Q)$$(PREPARE_MAN_CMD) $$(S)README.md $$(PREPARE_DEST_DIR)/share/doc/rust
 
 dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)
 	@$(call E, build: $$@)
+# Copy essential gcc components into installer
+ifdef CFG_WINDOWSY_$(1)
+	$$(Q)rm -Rf tmp/dist/win-rust-gcc-$(1)
+	$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image tmp/dist/win-rust-gcc-$(1) $(1)
+	$$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
+endif
 	$$(Q)$$(S)src/rust-installer/gen-installer.sh \
 		--product-name=Rust \
 		--verify-bin=rustc \
@@ -242,9 +254,50 @@ dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)
 		--work-dir=tmp/dist \
 		--output-dir=dist \
 		--non-installed-prefixes=$$(NON_INSTALLED_PREFIXES) \
-		--package-name=$$(PKG_NAME)-$(1)
+		--package-name=$$(PKG_NAME)-$(1) \
+		--component-name=rustc \
+		--legacy-manifest-dirs=rustlib,cargo
 	$$(Q)rm -R tmp/dist/$$(PKG_NAME)-$(1)-image
 
+dist-doc-install-dir-$(1): docs compiler-docs
+	$$(Q)mkdir -p tmp/dist/$$(DOC_PKG_NAME)-$(1)-image/share/doc/rust
+	$$(Q)cp -r doc tmp/dist/$$(DOC_PKG_NAME)-$(1)-image/share/doc/rust/html
+
+dist/$$(DOC_PKG_NAME)-$(1).tar.gz: dist-doc-install-dir-$(1)
+	@$(call E, build: $$@)
+	$$(Q)$$(S)src/rust-installer/gen-installer.sh \
+		--product-name=Rust-Documentation \
+		--rel-manifest-dir=rustlib \
+		--success-message=Rust-documentation-is-installed. \
+		--image-dir=tmp/dist/$$(DOC_PKG_NAME)-$(1)-image \
+		--work-dir=tmp/dist \
+		--output-dir=dist \
+		--package-name=$$(DOC_PKG_NAME)-$(1) \
+		--component-name=rust-docs \
+		--legacy-manifest-dirs=rustlib,cargo \
+		--bulk-dirs=share/doc/rust/html
+	$$(Q)rm -R tmp/dist/$$(DOC_PKG_NAME)-$(1)-image
+
+dist-mingw-install-dir-$(1):
+	$$(Q)mkdir -p tmp/dist/rust-mingw-tmp-$(1)-image
+	$$(Q)rm -Rf tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
+	$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
+		tmp/dist/rust-mingw-tmp-$(1)-image tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
+
+dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
+	@$(call E, build: $$@)
+	$$(Q)$$(S)src/rust-installer/gen-installer.sh \
+		--product-name=Rust-MinGW \
+		--rel-manifest-dir=rustlib \
+		--success-message=Rust-MinGW-is-installed. \
+		--image-dir=tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image \
+		--work-dir=tmp/dist \
+		--output-dir=dist \
+		--package-name=$$(MINGW_PKG_NAME)-$(1) \
+		--component-name=rust-mingw \
+		--legacy-manifest-dirs=rustlib,cargo
+	$$(Q)rm -R tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
+
 endef
 
 ifneq ($(CFG_ENABLE_DIST_HOST_ONLY),)
@@ -257,7 +310,16 @@ endif
 
 dist-install-dirs: $(foreach host,$(CFG_HOST),dist-install-dir-$(host))
 
-dist-tar-bins: $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz)
+ifdef CFG_WINDOWSY_$(CFG_BUILD)
+MAYBE_MINGW_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(MINGW_PKG_NAME)-$(host).tar.gz)
+endif
+
+ifeq ($(CFG_DISABLE_DOCS),)
+MAYBE_DOC_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(DOC_PKG_NAME)-$(host).tar.gz)
+endif
+
+dist-tar-bins: $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
+	$(MAYBE_DOC_TARBALLS) $(MAYBE_MINGW_TARBALLS)
 
 # Just try to run the compiler for the build host
 distcheck-tar-bins: dist-tar-bins
@@ -289,27 +351,20 @@ distcheck-docs: dist-docs
 # Primary targets (dist, distcheck)
 ######################################################################
 
-ifdef CFG_WINDOWSY_$(CFG_BUILD)
-
-dist: dist-win dist-tar-bins
-
-distcheck: distcheck-win
-	$(Q)rm -Rf tmp/distcheck
-	@echo
-	@echo -----------------------------------------------
-	@echo "Rust ready for distribution (see ./dist)"
-	@echo -----------------------------------------------
-
-else
+MAYBE_DIST_TAR_SRC=dist-tar-src
+MAYBE_DISTCHECK_TAR_SRC=distcheck-tar-src
 
 # FIXME #13224: On OS X don't produce tarballs simply because --exclude-vcs don't work.
 # This is a huge hack because I just don't have time to figure out another solution.
 ifeq ($(CFG_OSTYPE), apple-darwin)
 MAYBE_DIST_TAR_SRC=
 MAYBE_DISTCHECK_TAR_SRC=
-else
-MAYBE_DIST_TAR_SRC=dist-tar-src
-MAYBE_DISTCHECK_TAR_SRC=distcheck-tar-src
+endif
+
+# Don't bother with source tarballs on windows just because we historically haven't.
+ifeq ($(CFG_OSTYPE), pc-windows-gnu)
+MAYBE_DIST_TAR_SRC=
+MAYBE_DISTCHECK_TAR_SRC=
 endif
 
 ifneq ($(CFG_DISABLE_DOCS),)
@@ -320,15 +375,13 @@ MAYBE_DIST_DOCS=dist-docs
 MAYBE_DISTCHECK_DOCS=distcheck-docs
 endif
 
-dist: $(MAYBE_DIST_TAR_SRC) dist-osx dist-tar-bins $(MAYBE_DIST_DOCS)
+dist: $(MAYBE_DIST_TAR_SRC) dist-osx dist-win dist-tar-bins $(MAYBE_DIST_DOCS)
 
-distcheck: $(MAYBE_DISTCHECK_TAR_SRC) distcheck-osx distcheck-tar-bins $(MAYBE_DISTCHECK_DOCS)
+distcheck: $(MAYBE_DISTCHECK_TAR_SRC) distcheck-osx distcheck-win distcheck-tar-bins $(MAYBE_DISTCHECK_DOCS)
 	$(Q)rm -Rf tmp/distcheck
 	@echo
 	@echo -----------------------------------------------
 	@echo "Rust ready for distribution (see ./dist)"
 	@echo -----------------------------------------------
 
-endif
-
 .PHONY: dist distcheck
diff --git a/mk/docs.mk b/mk/docs.mk
index 9a924916ec8..2a7ef5164f0 100644
--- a/mk/docs.mk
+++ b/mk/docs.mk
@@ -236,7 +236,8 @@ LIB_DOC_DEP_$(1) = \
 	$$(RSINPUTS_$(1)) \
 	$$(RUSTDOC_EXE) \
 	$$(foreach dep,$$(RUST_DEPS_$(1)), \
-		$$(TLIB2_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.$$(dep) \
+		$$(TLIB2_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.$$(dep)) \
+	$$(foreach dep,$$(filter $$(DOC_CRATES), $$(RUST_DEPS_$(1))), \
 		doc/$$(dep)/)
 else
 LIB_DOC_DEP_$(1) = $$(CRATEFILE_$(1)) $$(RSINPUTS_$(1))
diff --git a/mk/grammar.mk b/mk/grammar.mk
index a9f45907b81..08461f9dcc2 100644
--- a/mk/grammar.mk
+++ b/mk/grammar.mk
@@ -31,7 +31,7 @@ $(BG):
 	$(Q)mkdir -p $(BG)
 
 $(BG)RustLexer.class: $(BG) $(SG)RustLexer.g4
-	$(Q)$(CFG_ANTLR4) -o $(B)grammar $(SG)RustLexer.g4
+	$(Q)$(CFG_ANTLR4) -o $(BG) $(SG)RustLexer.g4
 	$(Q)$(CFG_JAVAC) -d $(BG) $(BG)RustLexer.java
 
 check-build-lexer-verifier: $(BG)verify
diff --git a/mk/install.mk b/mk/install.mk
index 632df3c754b..f36ca4db7ca 100644
--- a/mk/install.mk
+++ b/mk/install.mk
@@ -21,6 +21,9 @@ ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
 else
 	$(Q)$(MAKE) prepare_install
 endif
+ifeq ($(CFG_DISABLE_DOCS),)
+	$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)" "$(MAYBE_DISABLE_VERIFY)"
+endif
 	$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)" "$(MAYBE_DISABLE_VERIFY)"
 # Remove tmp files because it's a decent amount of disk space
 	$(Q)rm -R tmp/dist
@@ -34,6 +37,9 @@ ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
 else
 	$(Q)$(MAKE) prepare_uninstall
 endif
+ifeq ($(CFG_DISABLE_DOCS),)
+	$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+endif
 	$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
 # Remove tmp files because it's a decent amount of disk space
 	$(Q)rm -R tmp/dist
diff --git a/mk/main.mk b/mk/main.mk
index 4aed1cea9ca..32167dfd899 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -15,6 +15,9 @@
 # The version number
 CFG_RELEASE_NUM=0.13.0
 
+# An optional number to put after the label, e.g. '2' -> '-beta2'
+CFG_BETA_CYCLE=
+
 CFG_FILENAME_EXTRA=4e7c5e5c
 
 ifeq ($(CFG_RELEASE_CHANNEL),stable)
@@ -24,12 +27,13 @@ CFG_RELEASE=$(CFG_RELEASE_NUM)
 CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)
 endif
 ifeq ($(CFG_RELEASE_CHANNEL),beta)
-CFG_RELEASE=$(CFG_RELEASE_NUM)-beta
+# The beta channel is temporarily called 'alpha'
+CFG_RELEASE=$(CFG_RELEASE_NUM)-alpha$(CFG_BETA_CYCLE)
 # When building beta/nightly distributables just reuse the same "beta"
 # name so when we upload we'll always override the previous
 # nighly. This doesn't actually impact the version reported by rustc -
 # it's just for file naming.
-CFG_PACKAGE_VERS=beta
+CFG_PACKAGE_VERS=alpha
 endif
 ifeq ($(CFG_RELEASE_CHANNEL),nightly)
 CFG_RELEASE=$(CFG_RELEASE_NUM)-nightly
@@ -325,6 +329,12 @@ export CFG_DISABLE_INJECT_STD_VERSION
 # Per-stage targets and runner
 ######################################################################
 
+# Valid setting-strings are 'all', 'none', 'gdb', 'lldb'
+# This 'function' will determine which debugger scripts to copy based on a
+# target triple. See debuggers.mk for more information.
+TRIPLE_TO_DEBUGGER_SCRIPT_SETTING=\
+ $(if $(findstring windows,$(1)),none,$(if $(findstring darwin,$(1)),lldb,gdb))
+
 STAGES = 0 1 2 3
 
 define SREQ
@@ -357,7 +367,7 @@ else
 HSREQ$(1)_H_$(3) = \
 	$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
 	$$(MKFILE_DEPS) \
-	tmp/install-debugger-scripts$(1)_H_$(3).done
+	tmp/install-debugger-scripts$(1)_H_$(3)-$$(call TRIPLE_TO_DEBUGGER_SCRIPT_SETTING,$(3)).done
 endif
 
 # Prerequisites for using the stageN compiler to build target artifacts
@@ -372,7 +382,7 @@ SREQ$(1)_T_$(2)_H_$(3) = \
 	$$(TSREQ$(1)_T_$(2)_H_$(3)) \
 	$$(foreach dep,$$(TARGET_CRATES), \
 	    $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \
-	tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3).done
+	tmp/install-debugger-scripts$(1)_T_$(2)_H_$(3)-$$(call TRIPLE_TO_DEBUGGER_SCRIPT_SETTING,$(2)).done
 
 # Prerequisites for a working stageN compiler and complete set of target
 # libraries
diff --git a/mk/prepare.mk b/mk/prepare.mk
index d404d3d2950..52fbbef81bd 100644
--- a/mk/prepare.mk
+++ b/mk/prepare.mk
@@ -144,6 +144,27 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
           $$(call PREPARE_LIB,libcompiler-rt.a),),),)
 endef
 
+define INSTALL_GDB_DEBUGGER_SCRIPTS_COMMANDS
+	$(Q)$(PREPARE_BIN_CMD) $(DEBUGGER_BIN_SCRIPTS_GDB_ABS) $(PREPARE_DEST_BIN_DIR)
+	$(Q)$(PREPARE_LIB_CMD) $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_GDB_ABS) $(PREPARE_DEST_LIB_DIR)/rustlib/etc
+endef
+
+define INSTALL_LLDB_DEBUGGER_SCRIPTS_COMMANDS
+	$(Q)$(PREPARE_BIN_CMD) $(DEBUGGER_BIN_SCRIPTS_LLDB_ABS) $(PREPARE_DEST_BIN_DIR)
+	$(Q)$(PREPARE_LIB_CMD) $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_LLDB_ABS) $(PREPARE_DEST_LIB_DIR)/rustlib/etc
+endef
+
+define INSTALL_NO_DEBUGGER_SCRIPTS_COMMANDS
+	$(Q)echo "No debugger scripts will be installed for host $(PREPARE_HOST)"
+endef
+
+# $(1) is PREPARE_HOST
+INSTALL_DEBUGGER_SCRIPT_COMMANDS=$(if $(findstring windows,$(1)),\
+                                   $(INSTALL_NO_DEBUGGER_SCRIPTS_COMMANDS),\
+                                   $(if $(findstring darwin,$(1)),\
+                                     $(INSTALL_LLDB_DEBUGGER_SCRIPTS_COMMANDS),\
+                                     $(INSTALL_GDB_DEBUGGER_SCRIPTS_COMMANDS)))
+
 define DEF_PREPARE
 
 prepare-base-$(1): PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE)
@@ -170,9 +191,10 @@ prepare-host-dirs-$(1): prepare-maybe-clean-$(1)
 	$$(call PREPARE_DIR,$$(PREPARE_DEST_LIB_DIR)/rustlib/etc)
 	$$(call PREPARE_DIR,$$(PREPARE_DEST_MAN_DIR))
 
-prepare-debugger-scripts-$(1): prepare-host-dirs-$(1) $(DEBUGGER_SCRIPTS_ALL)
-	$$(Q)$$(PREPARE_BIN_CMD) $(DEBUGGER_BIN_SCRIPTS_ABS) $$(PREPARE_DEST_BIN_DIR)
-	$$(Q)$$(PREPARE_LIB_CMD) $(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ABS) $$(PREPARE_DEST_LIB_DIR)/rustlib/etc
+prepare-debugger-scripts-$(1): prepare-host-dirs-$(1) \
+                               $$(DEBUGGER_BIN_SCRIPTS_ALL_ABS) \
+                               $$(DEBUGGER_RUSTLIB_ETC_SCRIPTS_ALL_ABS)
+	$$(call INSTALL_DEBUGGER_SCRIPT_COMMANDS,$$(PREPARE_HOST))
 
 $$(foreach tool,$$(PREPARE_TOOLS), \
   $$(foreach host,$$(CFG_HOST), \
diff --git a/mk/tests.mk b/mk/tests.mk
index 1a122572e43..bf07d6de0e0 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -74,14 +74,6 @@ endif
 TEST_LOG_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).log
 TEST_OK_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).ok
 
-# If we're sharding the testsuite between parallel testers,
-# pass this argument along to the compiletest and crate test
-# invocations.
-ifdef TEST_SHARD
-  CTEST_TESTARGS += --test-shard=$(TEST_SHARD)
-  CRATE_TEST_EXTRA_ARGS += --test-shard=$(TEST_SHARD)
-endif
-
 define DEF_TARGET_COMMANDS
 
 ifdef CFG_UNIXY_$(1)
@@ -297,6 +289,7 @@ tidy:
 		| grep '^$(S)src/doc' -v \
 		| grep '^$(S)src/compiler-rt' -v \
 		| grep '^$(S)src/libbacktrace' -v \
+		| grep '^$(S)src/rust-installer' -v \
 		| xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py
 
 endif
diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs
index 1abcd8bd214..c513aec0b84 100644
--- a/src/compiletest/runtest.rs
+++ b/src/compiletest/runtest.rs
@@ -32,6 +32,7 @@ use std::io::process;
 use std::io::timer;
 use std::io;
 use std::os;
+use std::iter::repeat;
 use std::str;
 use std::string::String;
 use std::thread::Thread;
@@ -367,7 +368,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
     let DebuggerCommands {
         commands,
         check_lines,
-        use_gdb_pretty_printer,
         breakpoint_lines
     } = parse_debugger_commands(testfile, "gdb");
     let mut cmds = commands.connect("\n");
@@ -521,16 +521,11 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
                     if header::gdb_version_to_int(version.as_slice()) >
                         header::gdb_version_to_int("7.4") {
                         // Add the directory containing the pretty printers to
-                        // GDB's script auto loading safe path ...
+                        // GDB's script auto loading safe path
                         script_str.push_str(
                             format!("add-auto-load-safe-path {}\n",
                                     rust_pp_module_abs_path.replace("\\", "\\\\").as_slice())
                                 .as_slice());
-                        // ... and also the test directory
-                        script_str.push_str(
-                            format!("add-auto-load-safe-path {}\n",
-                                    config.build_base.as_str().unwrap().replace("\\", "\\\\"))
-                                .as_slice());
                     }
                 }
                 _ => {
@@ -543,6 +538,9 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
             // pretty printing, it just tells GDB to print values on one line:
             script_str.push_str("set print pretty off\n");
 
+            // Add the pretty printer directory to GDB's source-file search path
+            script_str.push_str(format!("directory {}\n", rust_pp_module_abs_path)[]);
+
             // Load the target executable
             script_str.push_str(format!("file {}\n",
                                         exe_file.as_str().unwrap().replace("\\", "\\\\"))
@@ -564,12 +562,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
                              script_str.as_slice(),
                              "debugger.script");
 
-            if use_gdb_pretty_printer {
-                // Only emit the gdb auto-loading script if pretty printers
-                // should actually be loaded
-                dump_gdb_autoload_script(config, testfile);
-            }
-
             // run debugger script with gdb
             #[cfg(windows)]
             fn debugger() -> String {
@@ -611,19 +603,6 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
     }
 
     check_debugger_output(&debugger_run_result, check_lines.as_slice());
-
-    fn dump_gdb_autoload_script(config: &Config, testfile: &Path) {
-        let mut script_path = output_base_name(config, testfile);
-        let mut script_file_name = script_path.filename().unwrap().to_vec();
-        script_file_name.push_all("-gdb.py".as_bytes());
-        script_path.set_filename(script_file_name.as_slice());
-
-        let script_content = "import gdb_rust_pretty_printing\n\
-                              gdb_rust_pretty_printing.register_printers(gdb.current_objfile())\n"
-                             .as_bytes();
-
-        File::create(&script_path).write(script_content).unwrap();
-    }
 }
 
 fn find_rust_src_root(config: &Config) -> Option<Path> {
@@ -781,7 +760,6 @@ struct DebuggerCommands {
     commands: Vec<String>,
     check_lines: Vec<String>,
     breakpoint_lines: Vec<uint>,
-    use_gdb_pretty_printer: bool
 }
 
 fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
@@ -794,7 +772,6 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
     let mut breakpoint_lines = vec!();
     let mut commands = vec!();
     let mut check_lines = vec!();
-    let mut use_gdb_pretty_printer = false;
     let mut counter = 1;
     let mut reader = BufferedReader::new(File::open(file_path).unwrap());
     for line in reader.lines() {
@@ -804,10 +781,6 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
                     breakpoint_lines.push(counter);
                 }
 
-                if line.as_slice().contains("gdb-use-pretty-printer") {
-                    use_gdb_pretty_printer = true;
-                }
-
                 header::parse_name_value_directive(
                         line.as_slice(),
                         command_directive.as_slice()).map(|cmd| {
@@ -832,7 +805,6 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str)
         commands: commands,
         check_lines: check_lines,
         breakpoint_lines: breakpoint_lines,
-        use_gdb_pretty_printer: use_gdb_pretty_printer,
     }
 }
 
@@ -976,8 +948,7 @@ fn check_expected_errors(expected_errors: Vec<errors::ExpectedError> ,
                          proc_res: &ProcRes) {
 
     // true if we found the error in question
-    let mut found_flags = Vec::from_elem(
-        expected_errors.len(), false);
+    let mut found_flags: Vec<_> = repeat(false).take(expected_errors.len()).collect();
 
     if proc_res.status.success() {
         fatal("process did not return an error status");
@@ -1337,7 +1308,7 @@ fn make_run_args(config: &Config, props: &TestProps, testfile: &Path) ->
     // Add the arguments in the run_flags directive
     args.extend(split_maybe_args(&props.run_flags).into_iter());
 
-    let prog = args.remove(0).unwrap();
+    let prog = args.remove(0);
     return ProcArgs {
         prog: prog,
         args: args,
diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md
index 87a3abd8f22..29c98e22ee9 100644
--- a/src/doc/guide-tasks.md
+++ b/src/doc/guide-tasks.md
@@ -1,6 +1,6 @@
-% The Rust Tasks and Communication Guide
+% The Rust Threads and Communication Guide
 
-**NOTE** This guide is badly out of date an needs to be rewritten.
+**NOTE** This guide is badly out of date and needs to be rewritten.
 
 # Introduction
 
@@ -9,36 +9,36 @@ primitives. This guide will describe the concurrency model in Rust, how it
 relates to the Rust type system, and introduce the fundamental library
 abstractions for constructing concurrent programs.
 
-Tasks provide failure isolation and recovery. When a fatal error occurs in Rust
+Threads provide failure isolation and recovery. When a fatal error occurs in Rust
 code as a result of an explicit call to `panic!()`, an assertion failure, or
-another invalid operation, the runtime system destroys the entire task. Unlike
+another invalid operation, the runtime system destroys the entire thread. Unlike
 in languages such as Java and C++, there is no way to `catch` an exception.
-Instead, tasks may monitor each other to see if they panic.
+Instead, threads may monitor each other to see if they panic.
 
-Tasks use Rust's type system to provide strong memory safety guarantees.  In
-particular, the type system guarantees that tasks cannot induce a data race
+Threads use Rust's type system to provide strong memory safety guarantees.  In
+particular, the type system guarantees that threads cannot induce a data race
 from shared mutable state.
 
 # Basics
 
-At its simplest, creating a task is a matter of calling the `spawn` function
-with a closure argument. `spawn` executes the closure in the new task.
+At its simplest, creating a thread is a matter of calling the `spawn` function
+with a closure argument. `spawn` executes the closure in the new thread.
 
 ```{rust,ignore}
-# use std::task::spawn;
+# use std::thread::spawn;
 
-// Print something profound in a different task using a named function
-fn print_message() { println!("I am running in a different task!"); }
+// Print something profound in a different thread using a named function
+fn print_message() { println!("I am running in a different thread!"); }
 spawn(print_message);
 
 // Alternatively, use a `move ||` expression instead of a named function.
 // `||` expressions evaluate to an unnamed closure. The `move` keyword
 // indicates that the closure should take ownership of any variables it
 // touches.
-spawn(move || println!("I am also running in a different task!"));
+spawn(move || println!("I am also running in a different thread!"));
 ```
 
-In Rust, a task is not a concept that appears in the language semantics.
+In Rust, a thread is not a concept that appears in the language semantics.
 Instead, Rust's type system provides all the tools necessary to implement safe
 concurrency: particularly, ownership. The language leaves the implementation
 details to the standard library.
@@ -49,26 +49,26 @@ argument a closure (of type `F`) that it will run exactly once. This
 closure is limited to capturing `Send`-able data from its environment
 (that is, data which is deeply owned). Limiting the closure to `Send`
 ensures that `spawn` can safely move the entire closure and all its
-associated state into an entirely different task for execution.
+associated state into an entirely different thread for execution.
 
 ```{rust,ignore}
-# use std::task::spawn;
-# fn generate_task_number() -> int { 0 }
+# use std::thread::spawn;
+# fn generate_thread_number() -> int { 0 }
 // Generate some state locally
-let child_task_number = generate_task_number();
+let child_thread_number = generate_thread_number();
 
 spawn(move || {
-    // Capture it in the remote task. The `move` keyword indicates
-    // that this closure should move `child_task_number` into its
+    // 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
     // enclosing stack frame.
-    println!("I am child number {}", child_task_number);
+    println!("I am child number {}", child_thread_number);
 });
 ```
 
 ## Communication
 
-Now that we have spawned a new task, it would be nice if we could communicate
+Now that we have spawned a new thread, it would be nice if we could communicate
 with it. For this, we use *channels*. A channel is simply a pair of endpoints:
 one for sending messages and another for receiving messages.
 
@@ -78,7 +78,7 @@ of a channel, and a **receiver** is the receiving endpoint. Consider the followi
 example of calculating two results concurrently:
 
 ```{rust,ignore}
-# use std::task::spawn;
+# use std::thread::spawn;
 
 let (tx, rx): (Sender<int>, Receiver<int>) = channel();
 
@@ -102,12 +102,12 @@ into its component parts).
 let (tx, rx): (Sender<int>, Receiver<int>) = channel();
 ```
 
-The child task will use the sender to send data to the parent task, which will
+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
-task.
+thread.
 
 ```{rust,ignore}
-# use std::task::spawn;
+# use std::thread::spawn;
 # fn some_expensive_computation() -> int { 42 }
 # let (tx, rx) = channel();
 spawn(move || {
@@ -116,10 +116,10 @@ spawn(move || {
 });
 ```
 
-Notice that the creation of the task closure transfers `tx` to the child task
+Notice that the creation of the thread closure transfers `tx` to the child thread
 implicitly: the closure captures `tx` in its environment. Both `Sender` and
-`Receiver` are sendable types and may be captured into tasks or otherwise
-transferred between them. In the example, the child task runs an expensive
+`Receiver` are sendable types and may be captured into threads or otherwise
+transferred between them. In the example, the child thread runs an expensive
 computation, then sends the result over the captured channel.
 
 Finally, the parent continues with some other expensive computation, then waits
@@ -137,7 +137,7 @@ The `Sender` and `Receiver` pair created by `channel` enables efficient
 communication between a single sender and a single receiver, but multiple
 senders cannot use a single `Sender` value, and multiple receivers cannot use a
 single `Receiver` value.  What if our example needed to compute multiple
-results across a number of tasks? The following program is ill-typed:
+results across a number of threads? The following program is ill-typed:
 
 ```{rust,ignore}
 # fn some_expensive_computation() -> int { 42 }
@@ -160,7 +160,7 @@ Instead we can clone the `tx`, which allows for multiple senders.
 let (tx, rx) = channel();
 
 for init_val in range(0u, 3) {
-    // Create a new channel handle to distribute to the child task
+    // Create a new channel handle to distribute to the child thread
     let child_tx = tx.clone();
     spawn(move || {
         child_tx.send(some_expensive_computation(init_val));
@@ -172,7 +172,7 @@ let result = rx.recv() + rx.recv() + rx.recv();
 ```
 
 Cloning a `Sender` produces a new handle to the same channel, allowing multiple
-tasks to send data to a single receiver. It upgrades the channel internally in
+threads to send data to a single receiver. It upgrades the channel internally in
 order to allow this functionality, which means that channels that are not
 cloned can avoid the overhead required to handle multiple senders. But this
 fact has no bearing on the channel's usage: the upgrade is transparent.
@@ -182,9 +182,9 @@ 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::task::spawn;
+# use std::thread::spawn;
 
-// Create a vector of ports, one for each child task
+// Create a vector of ports, one for each child thread
 let rxs = Vec::from_fn(3, |init_val| {
     let (tx, rx) = channel();
     spawn(move || {
@@ -256,18 +256,18 @@ fn main() {
 
 ## Sharing without copying: Arc
 
-To share data between tasks, a first approach would be to only use channel as
+To share data between threads, a first approach would be to only use channel as
 we have seen previously. A copy of the data to share would then be made for
-each task. In some cases, this would add up to a significant amount of wasted
+each thread. In some cases, this would add up to a significant amount of wasted
 memory and would require copying the same data more than necessary.
 
 To tackle this issue, one can use an Atomically Reference Counted wrapper
 (`Arc`) as implemented in the `sync` library of Rust. With an Arc, the data
-will no longer be copied for each task. The Arc acts as a reference to the
+will no longer be copied for each thread. The Arc acts as a reference to the
 shared data and only this reference is shared and cloned.
 
 Here is a small example showing how to use Arcs. We wish to run concurrently
-several computations on a single large vector of floats. Each task needs the
+several computations on a single large vector of floats. Each thread needs the
 full vector to perform its duty.
 
 ```{rust,ignore}
@@ -284,10 +284,10 @@ fn main() {
     let numbers_arc = Arc::new(numbers);
 
     for num in range(1u, 10) {
-        let task_numbers = numbers_arc.clone();
+        let thread_numbers = numbers_arc.clone();
 
         spawn(move || {
-            println!("{}-norm = {}", num, pnorm(task_numbers.as_slice(), num));
+            println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
         });
     }
 }
@@ -306,8 +306,8 @@ let numbers_arc = Arc::new(numbers);
 # }
 ```
 
-and a clone is captured for each task via a procedure. This only copies
-the wrapper and not its contents. Within the task's procedure, the captured
+and a clone is captured for each thread via a procedure. This only copies
+the wrapper and not its contents. Within the thread's procedure, the captured
 Arc reference can be used as a shared reference to the underlying vector as
 if it were local.
 
@@ -319,29 +319,29 @@ if it were local.
 # let numbers=Vec::from_fn(1000000, |_| rand::random::<f64>());
 # let numbers_arc = Arc::new(numbers);
 # let num = 4;
-let task_numbers = numbers_arc.clone();
+let thread_numbers = numbers_arc.clone();
 spawn(move || {
-    // Capture task_numbers and use it as if it was the underlying vector
-    println!("{}-norm = {}", num, pnorm(task_numbers.as_slice(), num));
+    // Capture thread_numbers and use it as if it was the underlying vector
+    println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
 });
 # }
 ```
 
-# Handling task panics
+# Handling thread panics
 
 Rust has a built-in mechanism for raising exceptions. The `panic!()` macro
 (which can also be written with an error string as an argument: `panic!(
 ~reason)`) and the `assert!` construct (which effectively calls `panic!()` if a
-boolean expression is false) are both ways to raise exceptions. When a task
-raises an exception, the task unwinds its stack—running destructors and
+boolean expression is false) are both ways to raise exceptions. When a thread
+raises an exception, the thread unwinds its stack—running destructors and
 freeing memory along the way—and then exits. Unlike exceptions in C++,
-exceptions in Rust are unrecoverable within a single task: once a task panics,
+exceptions in Rust are unrecoverable within a single thread: once a thread panics,
 there is no way to "catch" the exception.
 
-While it isn't possible for a task to recover from panicking, tasks may notify
+While it isn't possible for a thread to recover from panicking, threads may notify
 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 task to finish. `try` returns a value of type
+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`
 and `()`, callers can pattern-match on a result to check whether it's an `Ok`
@@ -364,14 +364,14 @@ assert!(result.is_err());
 
 Unlike `spawn`, the function spawned using `try` may return a value, which
 `try` will dutifully propagate back to the caller in a [`Result`] enum. If the
-child task terminates successfully, `try` will return an `Ok` result; if the
-child task panics, `try` will return an `Error` result.
+child thread terminates successfully, `try` will return an `Ok` result; if the
+child thread panics, `try` will return an `Error` result.
 
 [`Result`]: std/result/index.html
 
-> *Note:* A panicked task does not currently produce a useful error
+> *Note:* A panicked thread does not currently produce a useful error
 > value (`try` always returns `Err(())`). In the
-> future, it may be possible for tasks to intercept the value passed to
+> future, it may be possible for threads to intercept the value passed to
 > `panic!()`.
 
 But not all panics are created equal. In some cases you might need to abort
@@ -379,4 +379,4 @@ the entire program (perhaps you're writing an assert which, if it trips,
 indicates an unrecoverable logic error); in other cases you might want to
 contain the panic at a certain boundary (perhaps a small piece of input from
 the outside world, which you happen to be processing in parallel, is malformed
-such that the processing task cannot proceed).
+such that the processing thread cannot proceed).
diff --git a/src/doc/guide.md b/src/doc/guide.md
index 26a39b51405..a3a24abeb2e 100644
--- a/src/doc/guide.md
+++ b/src/doc/guide.md
@@ -23,11 +23,16 @@ Linux or a Mac, all you need to do is this (note that you don't need to type
 in the `$`s, they just indicate the start of each command):
 
 ```bash
-$ curl -s https://static.rust-lang.org/rustup.sh | sudo sh
+curl -L https://static.rust-lang.org/rustup.sh | sudo sh
 ```
 
-(If you're concerned about `curl | sudo sh`, please keep reading. Disclaimer
-below.)
+If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`,
+please keep reading and see our disclaimer below. And feel free to use a two-step version of the installation and examine our installation script:
+
+```bash
+curl -L https://static.rust-lang.org/rustup.sh -O
+sudo sh rustup.sh
+```
 
 If you're on Windows, please download either the [32-bit
 installer](https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.exe)
@@ -455,7 +460,7 @@ x = 10i;
 There is no single reason that bindings are immutable by default, but we can
 think about it through one of Rust's primary focuses: safety. If you forget to
 say `mut`, the compiler will catch it, and let you know that you have mutated
-something you may not have cared to mutate. If bindings were mutable by
+something you may not have intended to mutate. If bindings were mutable by
 default, the compiler would not be able to tell you this. If you _did_ intend
 mutation, then the solution is quite easy: add `mut`.
 
@@ -482,7 +487,7 @@ src/main.rs:2     let x;
 
 Giving it a type will compile, though:
 
-```{ignore}
+```{rust}
 let x: int;
 ```
 
@@ -884,9 +889,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.
 
-You can use the `rustdoc` tool to generate HTML documentation from these doc
-comments. We will talk more about `rustdoc` when we get to modules, as
-generally, you want to export documentation for a full module.
+You can use the [`rustdoc`](rustdoc.html) tool to generate HTML documentation
+from these doc comments.
 
 # Compound Data Types
 
@@ -1044,7 +1048,9 @@ struct Point(int, int, int);
 
 These two will not be equal, even if they have the same values:
 
-```{rust,ignore}
+```{rust}
+# struct Color(int, int, int);
+# struct Point(int, int, int);
 let black  = Color(0, 0, 0);
 let origin = Point(0, 0, 0);
 ```
@@ -1618,22 +1624,18 @@ 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 = [1i, 2i, 3i];     // a: [int, ..3]
-let mut m = [1i, 2i, 3i]; // mut m: [int, ..3]
+let a = [1i, 2i, 3i];     // a: [int; 3]
+let mut m = [1i, 2i, 3i]; // mut m: [int; 3]
 ```
 
-You can create an array with a given number of elements, all initialized to the
-same value, with `[val, ..N]` syntax. The compiler ensures that arrays are
-always initialized.
-
 There's a shorthand for initializing each element of an array to the same
 value. In this example, each element of `a` will be initialized to `0i`:
 
 ```{rust}
-let a = [0i, ..20]; // a: [int, ..20]
+let a = [0i; 20]; // a: [int; 20]
 ```
 
-Arrays have type `[T,..N]`. We'll talk about this `T` notation later, when we
+Arrays have type `[T; N]`. We'll talk about this `T` notation later, when we
 cover generics.
 
 You can get the number of elements in an array `a` with `a.len()`, and use
@@ -1913,7 +1915,7 @@ authors = ["Your Name <you@example.com>"]
 Cargo gets this information from your environment. If it's not correct, go ahead
 and fix that.
 
-Finally, Cargo generated a hello, world for us. Check out `src/main.rs`:
+Finally, Cargo generated a "Hello, world!" for us. Check out `src/main.rs`:
 
 ```{rust}
 fn main() {
@@ -2308,7 +2310,6 @@ Anyway, with us now converting our input to a number, our code looks like this:
 ```{rust,ignore}
 use std::io;
 use std::rand;
-use std::str::from_str;
 use std::cmp::Ordering;
 
 fn main() {
@@ -2359,7 +2360,6 @@ to do that. Try this code:
 ```{rust,no_run}
 use std::io;
 use std::rand;
-use std::str::from_str;
 use std::cmp::Ordering;
 
 fn main() {
@@ -2427,7 +2427,6 @@ code looks like this:
 ```{rust,no_run}
 use std::io;
 use std::rand;
-use std::str::from_str;
 use std::cmp::Ordering;
 
 fn main() {
@@ -2502,7 +2501,6 @@ Let's add that in:
 ```{rust,no_run}
 use std::io;
 use std::rand;
-use std::str::from_str;
 use std::cmp::Ordering;
 
 fn main() {
@@ -2579,7 +2577,6 @@ suboptimal to say the least. First, let's actually quit when you win the game:
 ```{rust,no_run}
 use std::io;
 use std::rand;
-use std::str::from_str;
 use std::cmp::Ordering;
 
 fn main() {
@@ -2636,7 +2633,6 @@ we don't want to quit, we just want to ignore it. Change that `return` to
 ```{rust,no_run}
 use std::io;
 use std::rand;
-use std::str::from_str;
 use std::cmp::Ordering;
 
 fn main() {
@@ -2716,7 +2712,6 @@ It was good for testing, but it kind of ruins the game. Here's our final source:
 ```{rust,no_run}
 use std::io;
 use std::rand;
-use std::str::from_str;
 use std::cmp::Ordering;
 
 fn main() {
@@ -3070,7 +3065,7 @@ test foo ... FAILED
 failures:
 
 ---- foo stdout ----
-        task 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
+        thread 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
 
 
 
@@ -3079,7 +3074,7 @@ failures:
 
 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
 
-task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
+thread '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
 ```
 
 Lots of output! Let's break this down:
@@ -3122,7 +3117,7 @@ failed, especially as we accumulate more tests.
 failures:
 
 ---- foo stdout ----
-        task 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
+        thread 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
 
 
 
@@ -3131,7 +3126,7 @@ failures:
 
 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
 
-task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
+thread '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
 ```
 
 After all the tests run, Rust will show us any output from our failed tests.
@@ -4297,7 +4292,7 @@ is that a moving closure always takes ownership of all variables that
 it uses. Ordinary closures, in contrast, just create a reference into
 the enclosing stack frame. Moving closures are most useful with Rust's
 concurrency features, and so we'll just leave it at this for
-now. We'll talk about them more in the "Tasks" section of the guide.
+now. We'll talk about them more in the "Threads" section of the guide.
 
 ## Accepting closures as arguments
 
@@ -4324,7 +4319,9 @@ let square = |x: int| { x * x };
 We've seen this before. We make a closure that takes an integer, and returns
 its square.
 
-```{rust,ignore}
+```{rust}
+# fn twice(x: int, f: |int| -> int) -> int { f(x) + f(x) }
+# let square = |x: int| { x * x };
 twice(5i, square); // evaluates to 50
 ```
 
@@ -5247,9 +5244,7 @@ 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.
 
-# Tasks
-
-**NOTE**: this section is currently out of date and will be rewritten soon.
+# Threads
 
 Concurrency and parallelism are topics that are of increasing interest to a
 broad subsection of software developers. Modern computers are often multi-core,
@@ -5258,24 +5253,22 @@ processor. Rust's semantics lend themselves very nicely to solving a number of
 issues that programmers have with concurrency. Many concurrency errors that are
 runtime errors in other languages are compile-time errors in Rust.
 
-Rust's concurrency primitive is called a **task**. Tasks are similar to
-threads, and do not share memory in an unsafe manner, preferring message
-passing to communicate. It's worth noting that tasks are implemented as a
-library, and not part of the language. This means that in the future, other
-concurrency libraries can be written for Rust to help in specific scenarios.
-Here's an example of creating a task:
+Rust's concurrency primitive is called a **thread**. It's worth noting that
+threads are implemented as a library, and not part of the language. This means
+that in the future, other concurrency libraries can be written for Rust to help
+in specific scenarios. Here's an example of creating a thread:
 
 ```{rust,ignore}
 spawn(move || {
-    println!("Hello from a task!");
+    println!("Hello from a thread!");
 });
 ```
 
 The `spawn` function takes a closure as an argument, and runs that
-closure in a new task. Typically, you will want to use a moving
+closure in a new thread. Typically, you will want to use a moving
 closure, so that the closure takes ownership of any variables that it
 touches.  This implies that those variables are not usable from the
-parent task after the child task is spawned:
+parent thread after the child thread is spawned:
 
 ```{rust,ignore}
 let mut x = vec![1i, 2i, 3i];
@@ -5291,15 +5284,15 @@ println!("The value of x[0] is: {}", x[0]); // error: use of moved value: `x`
 other languages would let us do this, but it's not safe to do
 so. Rust's borrow checker catches the error.
 
-If tasks were only able to capture these values, they wouldn't be very useful.
-Luckily, tasks can communicate with each other through **channel**s. Channels
+If threads were only able to capture these values, they wouldn't be very useful.
+Luckily, threads can communicate with each other through **channel**s. Channels
 work like this:
 
 ```{rust,ignore}
 let (tx, rx) = channel();
 
 spawn(move || {
-    tx.send("Hello from a task!".to_string());
+    tx.send("Hello from a thread!".to_string());
 });
 
 let message = rx.recv();
@@ -5312,14 +5305,14 @@ receive the message on the `Receiver<T>` side with the `recv()` method.  This
 method blocks until it gets a message. There's a similar method, `.try_recv()`,
 which returns an `Result<T, TryRecvError>` and does not block.
 
-If you want to send messages to the task as well, create two channels!
+If you want to send messages to the thread as well, create two channels!
 
 ```{rust,ignore}
 let (tx1, rx1) = channel();
 let (tx2, rx2) = channel();
 
 spawn(move || {
-    tx1.send("Hello from a task!".to_string());
+    tx1.send("Hello from a thread!".to_string());
     let message = rx2.recv();
     println!("{}", message);
 });
@@ -5330,9 +5323,9 @@ println!("{}", message);
 tx2.send("Goodbye from main!".to_string());
 ```
 
-The closure has one sending end and one receiving end, and the main
-task has one of each as well. Now they can talk back and forth in
-whatever way they wish.
+The closure has one sending end and one receiving end, and the main thread has
+one of each as well. Now they can talk back and forth in whatever way they
+wish.
 
 Notice as well that because `Sender` and `Receiver` are generic, while you can
 pass any kind of information through the channel, the ends are strongly typed.
@@ -5371,7 +5364,7 @@ we'll just get the value immediately.
 
 ## Success and failure
 
-Tasks don't always succeed, they can also panic. A task that wishes to panic
+Threads don't always succeed, they can also panic. A thread that wishes to panic
 can call the `panic!` macro, passing a message:
 
 ```{rust,ignore}
@@ -5380,14 +5373,14 @@ spawn(move || {
 });
 ```
 
-If a task panics, it is not possible for it to recover. However, it can
-notify other tasks that it has panicked. We can do this with `task::try`:
+If a thread panics, it is not possible for it to recover. However, it can
+notify other thread that it has panicked. We can do this with `thread::try`:
 
 ```{rust,ignore}
-use std::task;
+use std::thread;
 use std::rand;
 
-let result = task::try(move || {
+let result = thread::try(move || {
     if rand::random() {
         println!("OK");
     } else {
@@ -5396,7 +5389,7 @@ let result = task::try(move || {
 });
 ```
 
-This task will randomly panic or succeed. `task::try` returns a `Result`
+This thread will randomly panic or succeed. `thread::try` returns a `Result`
 type, so we can handle the response like any other computation that may
 fail.
 
@@ -5444,7 +5437,7 @@ fn main() {
 }
 ```
 
-You can have the macros expanded like this: `rustc print.rs --pretty=expanded`, which will
+You can have the macros expanded like this: `rustc --pretty=expanded print.rs`, which will
 give us this huge result:
 
 ```{rust,ignore}
diff --git a/src/doc/index.md b/src/doc/index.md
index 77909955822..e54bf0eb242 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -58,7 +58,7 @@ a guide that can help you out:
 * [Strings](guide-strings.html)
 * [Pointers](guide-pointers.html)
 * [Crates and modules](guide-crates.html)
-* [Tasks and Communication](guide-tasks.html)
+* [Threads and Communication](guide-threads.html)
 * [Error Handling](guide-error-handling.html)
 * [Foreign Function Interface](guide-ffi.html)
 * [Writing Unsafe and Low-Level Code](guide-unsafe.html)
diff --git a/src/doc/intro.md b/src/doc/intro.md
index 5be97034357..a4e9d85bffd 100644
--- a/src/doc/intro.md
+++ b/src/doc/intro.md
@@ -483,7 +483,7 @@ fn main() {
     for i in range(0u, 3u) {
         let number = numbers.clone();
         Thread::spawn(move || {
-            let mut array = number.lock();
+            let mut array = number.lock().unwrap();
 
             (*array)[i] += 1;
 
diff --git a/src/doc/reference.md b/src/doc/reference.md
index e510685bb18..984ca913069 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -194,11 +194,11 @@ grammar as double-quoted strings. Other tokens have exact rules given.
 | else     | enum     | extern   | false    | final   |
 | fn       | for      | if       | impl     | in      |
 | let      | loop     | match    | mod      | move    |
-| mut      | offsetof | once     | override | priv    |
-| pub      | pure     | ref      | return   | sizeof  |
-| static   | self     | struct   | super    | true    |
-| trait    | type     | typeof   | unsafe   | unsized |
-| use      | virtual  | where    | while    | yield   |
+| mut      | offsetof | override | priv     | pub     |
+| pure     | ref      | return   | sizeof   | static  |
+| self     | struct   | super    | true     | trait   |
+| type     | typeof   | unsafe   | unsized  | use     |
+| virtual  | where    | while    | yield    |
 
 
 Each of these keywords has special meaning in its grammar, and all of them are
@@ -899,8 +899,8 @@ mirrors the module hierarchy.
 // Load the `vec` module from `vec.rs`
 mod vec;
 
-mod task {
-    // Load the `local_data` module from `task/local_data.rs`
+mod thread {
+    // Load the `local_data` module from `thread/local_data.rs`
     mod local_data;
 }
 ```
@@ -909,9 +909,9 @@ The directories and files used for loading external file modules can be
 influenced with the `path` attribute.
 
 ```{.ignore}
-#[path = "task_files"]
-mod task {
-    // Load the `local_data` module from `task_files/tls.rs`
+#[path = "thread_files"]
+mod thread {
+    // Load the `local_data` module from `thread_files/tls.rs`
     #[path = "tls.rs"]
     mod local_data;
 }
@@ -1188,7 +1188,7 @@ code safe, in the surrounding context.
 Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
 or implement features not directly present in the language. For example, Rust
 provides the language features necessary to implement memory-safe concurrency
-in the language but the implementation of tasks and message passing is in the
+in the language but the implementation of threads and message passing is in the
 standard library.
 
 Rust's type system is a conservative approximation of the dynamic safety
@@ -1438,11 +1438,11 @@ the `static` lifetime, fixed-size arrays, tuples, enum variants, and structs.
 const BIT1: uint = 1 << 0;
 const BIT2: uint = 1 << 1;
 
-const BITS: [uint, ..2] = [BIT1, BIT2];
+const BITS: [uint; 2] = [BIT1, BIT2];
 const STRING: &'static str = "bitstring";
 
 struct BitsNStrings<'a> {
-    mybits: [uint, ..2],
+    mybits: [uint; 2],
     mystring: &'a str
 }
 
@@ -1500,7 +1500,7 @@ be modified by the program. One of Rust's goals is to make concurrency bugs
 hard to run into, and this is obviously a very large source of race conditions
 or other bugs. For this reason, an `unsafe` block is required when either
 reading or writing a mutable static variable. Care should be taken to ensure
-that modifications to a mutable static are safe with respect to other tasks
+that modifications to a mutable static are safe with respect to other threads
 running in the same process.
 
 Mutable statics are still very useful, however. They can be used with C
@@ -2253,11 +2253,11 @@ A complete list of the built-in language items follows:
 * `drop`
   : Have destructors.
 * `send`
-  : Able to be sent across task boundaries.
+  : Able to be sent across thread boundaries.
 * `sized`
   : Has a size known at compile time.
 * `sync`
-  : Able to be safely shared between tasks when aliased.
+  : Able to be safely shared between threads when aliased.
 
 #### Operators
 
@@ -2621,7 +2621,7 @@ The currently implemented features of the reference compiler are:
                    LLVM's implementation which works in concert with the kernel
                    loader and dynamic linker. This is not necessarily available
                    on all platforms, and usage of it is discouraged (rust
-                   focuses more on task-local data instead of thread-local
+                   focuses more on thread-local data instead of thread-local
                    data).
 
 * `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
@@ -2923,7 +2923,7 @@ constant expression that can be evaluated at compile time, such as a
 ```
 [1i, 2, 3, 4];
 ["a", "b", "c", "d"];
-[0i, ..128];             // array with 128 zeros
+[0i; 128];             // array with 128 zeros
 [0u8, 0u8, 0u8, 0u8];
 ```
 
@@ -2939,7 +2939,7 @@ array is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can
 be assigned to.
 
 Indices are zero-based, and may be of any integral type. Vector access is
-bounds-checked at run-time. When the check fails, it will put the task in a
+bounds-checked at run-time. When the check fails, it will put the thread in a
 _panicked state_.
 
 ```{should-fail}
@@ -3692,7 +3692,7 @@ An example of each kind:
 
 ```{rust}
 let vec: Vec<int>  = vec![1, 2, 3];
-let arr: [int, ..3] = [1, 2, 3];
+let arr: [int; 3] = [1, 2, 3];
 let s: &[int]      = vec.as_slice();
 ```
 
@@ -3951,7 +3951,7 @@ Types in Rust are categorized into kinds, based on various properties of the
 components of the type. The kinds are:
 
 * `Send`
-  : Types of this kind can be safely sent between tasks.
+  : Types of this kind can be safely sent between threads.
     This kind includes scalars, boxes, procs, and
     structural types containing only other owned types.
     All `Send` types are `'static`.
@@ -3999,21 +3999,21 @@ to sendable.
 
 # Memory and concurrency models
 
-Rust has a memory model centered around concurrently-executing _tasks_. Thus
+Rust has a memory model centered around concurrently-executing _threads_. Thus
 its memory model and its concurrency model are best discussed simultaneously,
 as parts of each only make sense when considered from the perspective of the
 other.
 
 When reading about the memory model, keep in mind that it is partitioned in
-order to support tasks; and when reading about tasks, keep in mind that their
+order to support threads; and when reading about threads, keep in mind that their
 isolation and communication mechanisms are only possible due to the ownership
 and lifetime semantics of the memory model.
 
 ## Memory model
 
 A Rust program's memory consists of a static set of *items*, a set of
-[tasks](#tasks) each with its own *stack*, and a *heap*. Immutable portions of
-the heap may be shared between tasks, mutable portions may not.
+[threads](#threads) each with its own *stack*, and a *heap*. Immutable portions of
+the heap may be shared between threads, mutable portions may not.
 
 Allocations in the stack consist of *slots*, and allocations in the heap
 consist of *boxes*.
@@ -4024,8 +4024,8 @@ The _items_ of a program are those functions, modules and types that have their
 value calculated at compile-time and stored uniquely in the memory image of the
 rust process. Items are neither dynamically allocated nor freed.
 
-A task's _stack_ consists of activation frames automatically allocated on entry
-to each function as the task executes. A stack allocation is reclaimed when
+A thread's _stack_ consists of activation frames automatically allocated on entry
+to each function as the thread executes. A stack allocation is reclaimed when
 control leaves the frame containing it.
 
 The _heap_ is a general term that describes boxes.  The lifetime of an
@@ -4035,10 +4035,10 @@ in the heap, heap allocations may outlive the frame they are allocated within.
 
 ### Memory ownership
 
-A task owns all memory it can *safely* reach through local variables, as well
+A thread owns all memory it can *safely* reach through local variables, as well
 as boxes and references.
 
-When a task sends a value that has the `Send` trait to another task, it loses
+When a thread sends a value that has the `Send` trait to another thread, it loses
 ownership of the value sent and can no longer refer to it. This is statically
 guaranteed by the combined use of "move semantics", and the compiler-checked
 _meaning_ of the `Send` trait: it is only instantiated for (transitively)
@@ -4047,12 +4047,12 @@ sendable kinds of data constructor and pointers, never including references.
 When a stack frame is exited, its local allocations are all released, and its
 references to boxes are dropped.
 
-When a task finishes, its stack is necessarily empty and it therefore has no
+When a thread finishes, its stack is necessarily empty and it therefore has no
 references to any boxes; the remainder of its heap is immediately freed.
 
 ### Memory slots
 
-A task's stack contains slots.
+A thread's stack contains slots.
 
 A _slot_ is a component of a stack frame, either a function parameter, a
 [temporary](#lvalues,-rvalues-and-temporaries), or a local variable.
@@ -4106,72 +4106,69 @@ let y = x;
 // attempting to use `x` will result in an error here
 ```
 
-## Tasks
+## Threads
 
-An executing Rust program consists of a tree of tasks. A Rust _task_ consists
-of an entry function, a stack, a set of outgoing communication channels and
-incoming communication ports, and ownership of some portion of the heap of a
-single operating-system process.
+Rust's primary concurrency mechanism is called a **thread**.
 
-### Communication between tasks
+### Communication between threads
 
-Rust tasks are isolated and generally unable to interfere with one another's
+Rust threads are isolated and generally unable to interfere with one another's
 memory directly, except through [`unsafe` code](#unsafe-functions).  All
-contact between tasks is mediated by safe forms of ownership transfer, and data
+contact between threads is mediated by safe forms of ownership transfer, and data
 races on memory are prohibited by the type system.
 
-When you wish to send data between tasks, the values are restricted to the
+When you wish to send data between threads, the values are restricted to the
 [`Send` type-kind](#type-kinds). Restricting communication interfaces to this
-kind ensures that no references move between tasks. Thus access to an entire
+kind ensures that no references move between threads. Thus access to an entire
 data structure can be mediated through its owning "root" value; no further
 locking or copying is required to avoid data races within the substructure of
 such a value.
 
-### Task lifecycle
+### Thread
 
-The _lifecycle_ of a task consists of a finite set of states and events that
-cause transitions between the states. The lifecycle states of a task are:
+The _lifecycle_ of a threads consists of a finite set of states and events that
+cause transitions between the states. The lifecycle states of a thread are:
 
 * running
 * blocked
 * panicked
 * dead
 
-A task begins its lifecycle &mdash; once it has been spawned &mdash; in the
+A thread begins its lifecycle &mdash; once it has been spawned &mdash; in the
 *running* state. In this state it executes the statements of its entry
 function, and any functions called by the entry function.
 
-A task may transition from the *running* state to the *blocked* state any time
+A thread may transition from the *running* state to the *blocked* state any time
 it makes a blocking communication call. When the call can be completed &mdash;
 when a message arrives at a sender, or a buffer opens to receive a message
-&mdash; then the blocked task will unblock and transition back to *running*.
+&mdash; then the blocked thread will unblock and transition back to *running*.
 
-A task may transition to the *panicked* state at any time, due being killed by
+A thread may transition to the *panicked* state at any time, due being killed by
 some external event or internally, from the evaluation of a `panic!()` macro.
-Once *panicking*, a task unwinds its stack and transitions to the *dead* state.
-Unwinding the stack of a task is done by the task itself, on its own control
+Once *panicking*, a thread unwinds its stack and transitions to the *dead* state.
+Unwinding the stack of a thread is done by the thread itself, on its own control
 stack. If a value with a destructor is freed during unwinding, the code for the
-destructor is run, also on the task's control stack. Running the destructor
+destructor is run, also on the thread's control stack. Running the destructor
 code causes a temporary transition to a *running* state, and allows the
-destructor code to cause any subsequent state transitions. The original task
+destructor code to cause any subsequent state transitions. The original thread
 of unwinding and panicking thereby may suspend temporarily, and may involve
 (recursive) unwinding of the stack of a failed destructor. Nonetheless, the
 outermost unwinding activity will continue until the stack is unwound and the
-task transitions to the *dead* state. There is no way to "recover" from task
-panics. Once a task has temporarily suspended its unwinding in the *panicking*
+thread transitions to the *dead* state. There is no way to "recover" from thread
+panics. Once a thread has temporarily suspended its unwinding in the *panicking*
 state, a panic occurring from within this destructor results in *hard* panic.
 A hard panic currently results in the process aborting.
 
-A task in the *dead* state cannot transition to other states; it exists only to
-have its termination status inspected by other tasks, and/or to await
+A thread in the *dead* state cannot transition to other states; it exists only to
+have its termination status inspected by other threads, and/or to await
 reclamation when the last reference to it drops.
 
 # Runtime services, linkage and debugging
 
 The Rust _runtime_ is a relatively compact collection of Rust code that
-provides fundamental services and datatypes to all Rust tasks at run-time. It
+provides fundamental services and datatypes to all Rust threads at run-time. It
 is smaller and simpler than many modern language runtimes. It is tightly
-integrated into the language's execution model of memory, tasks, communication
+integrated into the language's execution model of memory, threads, communication
 and logging.
 
 ### Memory allocation
@@ -4182,7 +4179,7 @@ environment and releases them back to its environment when they are no longer
 needed. The default implementation of the service-provider interface consists
 of the C runtime functions `malloc` and `free`.
 
-The runtime memory-management system, in turn, supplies Rust tasks with
+The runtime memory-management system, in turn, supplies Rust threads with
 facilities for allocating releasing stacks, as well as allocating and freeing
 heap data.
 
@@ -4190,15 +4187,15 @@ heap data.
 
 The runtime provides C and Rust code to assist with various built-in types,
 such as arrays, strings, and the low level communication system (ports,
-channels, tasks).
+channels, threads).
 
 Support for other built-in types such as simple types, tuples and enums is
 open-coded by the Rust compiler.
 
-### Task scheduling and communication
+### Thread scheduling and communication
 
-The runtime provides code to manage inter-task communication. This includes
-the system of task-lifecycle state transitions depending on the contents of
+The runtime provides code to manage inter-thread communication. This includes
+the system of thread-lifecycle state transitions depending on the contents of
 queues, as well as code to copy values between queues and their recipients and
 to serialize values for transmission over operating-system inter-process
 communication facilities.
diff --git a/src/etc/gdb_load_rust_pretty_printers.py b/src/etc/gdb_load_rust_pretty_printers.py
new file mode 100644
index 00000000000..755cac153d1
--- /dev/null
+++ b/src/etc/gdb_load_rust_pretty_printers.py
@@ -0,0 +1,12 @@
+# 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.
+
+import gdb_rust_pretty_printing
+gdb_rust_pretty_printing.register_printers(gdb.current_objfile())
diff --git a/src/etc/kate/rust.xml b/src/etc/kate/rust.xml
index c22cd9c2047..9d045028509 100644
--- a/src/etc/kate/rust.xml
+++ b/src/etc/kate/rust.xml
@@ -245,6 +245,7 @@
 		<context attribute="CharEscape" lineEndContext="#pop" name="CharEscape">
 			<AnyChar String="nrt\&apos;&quot;" attribute="CharEscape" context="#pop"/>
 			<RegExpr String="x[0-9a-fA-F]{2}" attribute="CharEscape" context="#pop"/>
+			<RegExpr String="u\{[0-9a-fA-F]{1,6}\}" attribute="CharEscape" context="#pop"/>
 			<RegExpr String="u[0-9a-fA-F]{4}" attribute="CharEscape" context="#pop"/>
 			<RegExpr String="U[0-9a-fA-F]{8}" attribute="CharEscape" context="#pop"/>
 			<RegExpr String="." attribute="Error" context="#pop"/>
@@ -255,7 +256,7 @@
 			<Detect2Chars char="*" char1="/" attribute="Comment" context="#pop" endRegion="Comment"/>
 		</context>
 	</contexts>
-    <itemDatas>
+	<itemDatas>
 		<itemData name="Normal Text"  defStyleNum="dsNormal"/>
 		<itemData name="Keyword"      defStyleNum="dsKeyword" color="#770088" bold="1"/>
 		<itemData name="Self"         defStyleNum="dsKeyword" color="#FF0000" bold="1"/>
diff --git a/src/etc/make-win-dist.py b/src/etc/make-win-dist.py
index 95e647c91cf..ea2a98db2dc 100644
--- a/src/etc/make-win-dist.py
+++ b/src/etc/make-win-dist.py
@@ -114,11 +114,5 @@ def make_win_dist(rust_root, gcc_root, target_triple):
     for src in target_libs:
         shutil.copy(src, target_lib_dir)
 
-    # Copy license files
-    lic_dir = os.path.join(rust_root, "bin", "third-party")
-    if os.path.exists(lic_dir):
-        shutil.rmtree(lic_dir) # copytree() won't overwrite existing files
-    shutil.copytree(os.path.join(os.path.dirname(__file__), "third-party"), lic_dir)
-
 if __name__=="__main__":
     make_win_dist(sys.argv[1], sys.argv[2], sys.argv[3])
diff --git a/src/etc/rust-gdb b/src/etc/rust-gdb
new file mode 100755
index 00000000000..520a108da91
--- /dev/null
+++ b/src/etc/rust-gdb
@@ -0,0 +1,23 @@
+#!/bin/sh
+# 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.
+
+# Exit if anything fails
+set -e
+
+# Find out where the pretty printer Python module is
+RUSTC_SYSROOT=`rustc --print=sysroot`
+GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
+
+# Run GDB with the additional arguments that load the pretty printers
+PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" gdb \
+  -d "$GDB_PYTHON_MODULE_DIRECTORY" \
+  -iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \
+  "$@"
diff --git a/src/grammar/README.md b/src/grammar/README.md
index f5b872cdc7f..1f7923e1caf 100644
--- a/src/grammar/README.md
+++ b/src/grammar/README.md
@@ -1,7 +1,7 @@
 Reference grammar.
 
 Uses [antlr4](http://www.antlr.org/) and a custom Rust tool to compare
-ASTs/token streams generated. You can use the `check-syntax` make target to
+ASTs/token streams generated. You can use the `check-lexer` make target to
 run all of the available tests.
 
 To use manually:
@@ -12,7 +12,7 @@ javac *.java
 rustc -O verify.rs
 for file in ../*/**.rs; do
     echo $file;
-    grun RustLexer tokens -tokens < $file | ./verify $file || break
+    grun RustLexer tokens -tokens < $file | ./verify $file RustLexer.tokens || break
 done
 ```
 
diff --git a/src/grammar/RustLexer.g4 b/src/grammar/RustLexer.g4
index 0ff9af7aca1..88de5db41fe 100644
--- a/src/grammar/RustLexer.g4
+++ b/src/grammar/RustLexer.g4
@@ -112,7 +112,64 @@ LIT_INTEGER
   ;
 
 LIT_FLOAT
-  : [0-9][0-9_]* ('.' | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?)
+  : [0-9][0-9_]* ('.' {
+        /* dot followed by another dot is a range, no float */
+        _input.LA(1) != '.' &&
+        /* dot followed by an identifier is an integer with a function call, no float */
+        _input.LA(1) != '_' &&
+        _input.LA(1) != 'a' &&
+        _input.LA(1) != 'b' &&
+        _input.LA(1) != 'c' &&
+        _input.LA(1) != 'd' &&
+        _input.LA(1) != 'e' &&
+        _input.LA(1) != 'f' &&
+        _input.LA(1) != 'g' &&
+        _input.LA(1) != 'h' &&
+        _input.LA(1) != 'i' &&
+        _input.LA(1) != 'j' &&
+        _input.LA(1) != 'k' &&
+        _input.LA(1) != 'l' &&
+        _input.LA(1) != 'm' &&
+        _input.LA(1) != 'n' &&
+        _input.LA(1) != 'o' &&
+        _input.LA(1) != 'p' &&
+        _input.LA(1) != 'q' &&
+        _input.LA(1) != 'r' &&
+        _input.LA(1) != 's' &&
+        _input.LA(1) != 't' &&
+        _input.LA(1) != 'u' &&
+        _input.LA(1) != 'v' &&
+        _input.LA(1) != 'w' &&
+        _input.LA(1) != 'x' &&
+        _input.LA(1) != 'y' &&
+        _input.LA(1) != 'z' &&
+        _input.LA(1) != 'A' &&
+        _input.LA(1) != 'B' &&
+        _input.LA(1) != 'C' &&
+        _input.LA(1) != 'D' &&
+        _input.LA(1) != 'E' &&
+        _input.LA(1) != 'F' &&
+        _input.LA(1) != 'G' &&
+        _input.LA(1) != 'H' &&
+        _input.LA(1) != 'I' &&
+        _input.LA(1) != 'J' &&
+        _input.LA(1) != 'K' &&
+        _input.LA(1) != 'L' &&
+        _input.LA(1) != 'M' &&
+        _input.LA(1) != 'N' &&
+        _input.LA(1) != 'O' &&
+        _input.LA(1) != 'P' &&
+        _input.LA(1) != 'Q' &&
+        _input.LA(1) != 'R' &&
+        _input.LA(1) != 'S' &&
+        _input.LA(1) != 'T' &&
+        _input.LA(1) != 'U' &&
+        _input.LA(1) != 'V' &&
+        _input.LA(1) != 'W' &&
+        _input.LA(1) != 'X' &&
+        _input.LA(1) != 'Y' &&
+        _input.LA(1) != 'Z'
+  }? | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?)
   ;
 
 LIT_STR
diff --git a/src/grammar/check.sh b/src/grammar/check.sh
index f2836312437..cb269bbdb0a 100755
--- a/src/grammar/check.sh
+++ b/src/grammar/check.sh
@@ -11,6 +11,10 @@ if [ "${VERBOSE}" == "1" ]; then
     set -x
 fi
 
+passed=0
+failed=0
+skipped=0
+
 check() {
     grep --silent "// ignore-lexer-test" $1;
 
@@ -21,14 +25,27 @@ check() {
         # seem to have anny effect.
         if $3 RustLexer tokens -tokens < $1 | $4 $1 $5; then
             echo "pass: $1"
+            passed=`expr $passed + 1`
         else
             echo "fail: $1"
+            failed=`expr $failed + 1`
         fi
     else
         echo "skip: $1"
+        skipped=`expr $skipped + 1`
     fi
 }
 
 for file in $(find $1 -iname '*.rs' ! -path '*/test/compile-fail*'); do
     check $file $2 $3 $4 $5
 done
+
+printf "\ntest result: "
+
+if [ $failed -eq 0 ]; then
+    printf "ok. $passed passed; $failed failed; $skipped skipped\n\n"
+else
+    printf "failed. $passed passed; $failed failed; $skipped skipped\n\n"
+    exit 1
+fi
+
diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs
index f7b19cf6fbf..bdb616fcc99 100644
--- a/src/grammar/verify.rs
+++ b/src/grammar/verify.rs
@@ -61,7 +61,7 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
             "SHL"               => token::BinOp(token::Shl),
             "LBRACE"            => token::OpenDelim(token::Brace),
             "RARROW"            => token::RArrow,
-            "LIT_STR"           => token::Literal(token::Str_(Name(0))),
+            "LIT_STR"           => token::Literal(token::Str_(Name(0)), None),
             "DOTDOT"            => token::DotDot,
             "MOD_SEP"           => token::ModSep,
             "DOTDOTDOT"         => token::DotDotDot,
@@ -71,7 +71,7 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
             "ANDAND"            => token::AndAnd,
             "AT"                => token::At,
             "LBRACKET"          => token::OpenDelim(token::Bracket),
-            "LIT_STR_RAW"       => token::Literal(token::StrRaw(Name(0), 0)),
+            "LIT_STR_RAW"       => token::Literal(token::StrRaw(Name(0), 0), None),
             "RPAREN"            => token::CloseDelim(token::Paren),
             "SLASH"             => token::BinOp(token::Slash),
             "COMMA"             => token::Comma,
@@ -80,8 +80,8 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
             "TILDE"             => token::Tilde,
             "IDENT"             => id(),
             "PLUS"              => token::BinOp(token::Plus),
-            "LIT_CHAR"          => token::Literal(token::Char(Name(0))),
-            "LIT_BYTE"          => token::Literal(token::Byte(Name(0))),
+            "LIT_CHAR"          => token::Literal(token::Char(Name(0)), None),
+            "LIT_BYTE"          => token::Literal(token::Byte(Name(0)), None),
             "EQ"                => token::Eq,
             "RBRACKET"          => token::CloseDelim(token::Bracket),
             "COMMENT"           => token::Comment,
@@ -95,9 +95,9 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
             "BINOP"             => token::BinOp(token::Plus),
             "POUND"             => token::Pound,
             "OROR"              => token::OrOr,
-            "LIT_INTEGER"       => token::Literal(token::Integer(Name(0))),
+            "LIT_INTEGER"       => token::Literal(token::Integer(Name(0)), None),
             "BINOPEQ"           => token::BinOpEq(token::Plus),
-            "LIT_FLOAT"         => token::Literal(token::Float(Name(0))),
+            "LIT_FLOAT"         => token::Literal(token::Float(Name(0)), None),
             "WHITESPACE"        => token::Whitespace,
             "UNDERSCORE"        => token::Underscore,
             "MINUS"             => token::BinOp(token::Minus),
@@ -107,8 +107,8 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
             "OR"                => token::BinOp(token::Or),
             "GT"                => token::Gt,
             "LE"                => token::Le,
-            "LIT_BINARY"        => token::Literal(token::Binary(Name(0))),
-            "LIT_BINARY_RAW"    => token::Literal(token::BinaryRaw(Name(0), 0)),
+            "LIT_BINARY"        => token::Literal(token::Binary(Name(0)), None),
+            "LIT_BINARY_RAW"    => token::Literal(token::BinaryRaw(Name(0), 0), None),
             _                   => continue,
         };
 
@@ -189,17 +189,17 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>) -> TokenAn
         token::BinOp(..)           => token::BinOp(str_to_binop(content)),
         token::BinOpEq(..)         => token::BinOpEq(str_to_binop(content.slice_to(
                                                                     content.len() - 1))),
-        token::Literal(token::Str_(..))      => token::Literal(token::Str_(fix(content))),
-        token::Literal(token::StrRaw(..))    => token::Literal(token::StrRaw(fix(content),
-                                                                             count(content))),
-        token::Literal(token::Char(..))      => token::Literal(token::Char(fixchar(content))),
-        token::Literal(token::Byte(..))      => token::Literal(token::Byte(fixchar(content))),
+        token::Literal(token::Str_(..), n)      => token::Literal(token::Str_(fix(content)), n),
+        token::Literal(token::StrRaw(..), n)    => token::Literal(token::StrRaw(fix(content),
+                                                                             count(content)), n),
+        token::Literal(token::Char(..), n)      => token::Literal(token::Char(fixchar(content)), n),
+        token::Literal(token::Byte(..), n)      => token::Literal(token::Byte(fixchar(content)), n),
         token::DocComment(..)      => token::DocComment(nm),
-        token::Literal(token::Integer(..))   => token::Literal(token::Integer(nm)),
-        token::Literal(token::Float(..))     => token::Literal(token::Float(nm)),
-        token::Literal(token::Binary(..))    => token::Literal(token::Binary(nm)),
-        token::Literal(token::BinaryRaw(..)) => token::Literal(token::BinaryRaw(fix(content),
-                                                                                count(content))),
+        token::Literal(token::Integer(..), n)   => token::Literal(token::Integer(nm), n),
+        token::Literal(token::Float(..), n)     => token::Literal(token::Float(nm), n),
+        token::Literal(token::Binary(..), n)    => token::Literal(token::Binary(nm), n),
+        token::Literal(token::BinaryRaw(..), n) => token::Literal(token::BinaryRaw(fix(content),
+                                                                                count(content)), n),
         token::Ident(..)           => token::Ident(ast::Ident { name: nm, ctxt: 0 },
                                                    token::ModName),
         token::Lifetime(..)        => token::Lifetime(ast::Ident { name: nm, ctxt: 0 }),
@@ -214,8 +214,8 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>) -> TokenAn
     };
 
     let sp = syntax::codemap::Span {
-        lo: syntax::codemap::BytePos(from_str::<u32>(start).unwrap() - offset),
-        hi: syntax::codemap::BytePos(from_str::<u32>(end).unwrap() + 1),
+        lo: syntax::codemap::BytePos(start.parse::<u32>().unwrap() - offset),
+        hi: syntax::codemap::BytePos(end.parse::<u32>().unwrap() + 1),
         expn_id: syntax::codemap::NO_EXPANSION
     };
 
@@ -247,7 +247,9 @@ fn main() {
     let token_map = parse_token_list(token_file.read_to_string().unwrap().as_slice());
 
     let mut stdin = std::io::stdin();
-    let mut antlr_tokens = stdin.lines().map(|l| parse_antlr_token(l.unwrap().as_slice().trim(),
+    let mut lock = stdin.lock();
+    let lines = lock.lines();
+    let mut antlr_tokens = lines.map(|l| parse_antlr_token(l.unwrap().as_slice().trim(),
                                                                    &token_map));
 
     let code = File::open(&Path::new(args[1].as_slice())).unwrap().read_to_string().unwrap();
@@ -284,17 +286,17 @@ fn main() {
                     ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok)
                 }
             )
-        )
+        );
 
         matches!(
-            token::Literal(token::Byte(..)),
-            token::Literal(token::Char(..)),
-            token::Literal(token::Integer(..)),
-            token::Literal(token::Float(..)),
-            token::Literal(token::Str_(..)),
-            token::Literal(token::StrRaw(..)),
-            token::Literal(token::Binary(..)),
-            token::Literal(token::BinaryRaw(..)),
+            token::Literal(token::Byte(..), _),
+            token::Literal(token::Char(..), _),
+            token::Literal(token::Integer(..), _),
+            token::Literal(token::Float(..), _),
+            token::Literal(token::Str_(..), _),
+            token::Literal(token::StrRaw(..), _),
+            token::Literal(token::Binary(..), _),
+            token::Literal(token::BinaryRaw(..), _),
             token::Ident(..),
             token::Lifetime(..),
             token::Interpolated(..),
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index b8c7bc74132..aa5a7586118 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -58,7 +58,7 @@
 //!     let five = five.clone();
 //!
 //!     Thread::spawn(move || {
-//!         let mut number = five.lock();
+//!         let mut number = five.lock().unwrap();
 //!
 //!         *number += 1;
 //!
@@ -68,6 +68,7 @@
 //! ```
 
 use core::atomic;
+use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
 use core::borrow::BorrowFrom;
 use core::clone::Clone;
 use core::fmt::{mod, Show};
@@ -80,7 +81,7 @@ use core::nonzero::NonZero;
 use core::ops::{Drop, Deref};
 use core::option::Option;
 use core::option::Option::{Some, None};
-use core::ptr::{mod, RawPtr};
+use core::ptr::{mod, PtrExt};
 use heap::deallocate;
 
 /// An atomically reference counted wrapper for shared state.
@@ -95,7 +96,7 @@ use heap::deallocate;
 /// use std::thread::Thread;
 ///
 /// fn main() {
-///     let numbers = Vec::from_fn(100, |i| i as f32);
+///     let numbers: Vec<_> = range(0, 100u32).map(|i| i as f32).collect();
 ///     let shared_numbers = Arc::new(numbers);
 ///
 ///     for _ in range(0u, 10) {
@@ -182,7 +183,7 @@ impl<T> Arc<T> {
     #[experimental = "Weak pointers may not belong in this module."]
     pub fn downgrade(&self) -> Weak<T> {
         // See the clone() impl for why this is relaxed
-        self.inner().weak.fetch_add(1, atomic::Relaxed);
+        self.inner().weak.fetch_add(1, Relaxed);
         Weak { _ptr: self._ptr }
     }
 }
@@ -201,12 +202,12 @@ impl<T> Arc<T> {
 /// Get the number of weak references to this value.
 #[inline]
 #[experimental]
-pub fn weak_count<T>(this: &Arc<T>) -> uint { this.inner().weak.load(atomic::SeqCst) - 1 }
+pub fn weak_count<T>(this: &Arc<T>) -> uint { this.inner().weak.load(SeqCst) - 1 }
 
 /// Get the number of strong references to this value.
 #[inline]
 #[experimental]
-pub fn strong_count<T>(this: &Arc<T>) -> uint { this.inner().strong.load(atomic::SeqCst) }
+pub fn strong_count<T>(this: &Arc<T>) -> uint { this.inner().strong.load(SeqCst) }
 
 #[stable]
 impl<T> Clone for Arc<T> {
@@ -234,7 +235,7 @@ impl<T> Clone for Arc<T> {
         // must already provide any required synchronization.
         //
         // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
-        self.inner().strong.fetch_add(1, atomic::Relaxed);
+        self.inner().strong.fetch_add(1, Relaxed);
         Arc { _ptr: self._ptr }
     }
 }
@@ -273,8 +274,8 @@ impl<T: Send + Sync + Clone> Arc<T> {
     pub fn make_unique(&mut self) -> &mut T {
         // Note that we hold a strong reference, which also counts as a weak reference, so we only
         // clone if there is an additional reference of either kind.
-        if self.inner().strong.load(atomic::SeqCst) != 1 ||
-           self.inner().weak.load(atomic::SeqCst) != 1 {
+        if self.inner().strong.load(SeqCst) != 1 ||
+           self.inner().weak.load(SeqCst) != 1 {
             *self = Arc::new((**self).clone())
         }
         // This unsafety is ok because we're guaranteed that the pointer returned is the *only*
@@ -322,7 +323,7 @@ impl<T: Sync + Send> Drop for Arc<T> {
         // Because `fetch_sub` is already atomic, we do not need to synchronize with other threads
         // unless we are going to delete the object. This same logic applies to the below
         // `fetch_sub` to the `weak` count.
-        if self.inner().strong.fetch_sub(1, atomic::Release) != 1 { return }
+        if self.inner().strong.fetch_sub(1, Release) != 1 { return }
 
         // This fence is needed to prevent reordering of use of the data and deletion of the data.
         // Because it is marked `Release`, the decreasing of the reference count synchronizes with
@@ -339,14 +340,14 @@ impl<T: Sync + Send> Drop for Arc<T> {
         // > operation before deleting the object.
         //
         // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
-        atomic::fence(atomic::Acquire);
+        atomic::fence(Acquire);
 
         // Destroy the data at this time, even though we may not free the box allocation itself
         // (there may still be weak pointers lying around).
         unsafe { drop(ptr::read(&self.inner().data)); }
 
-        if self.inner().weak.fetch_sub(1, atomic::Release) == 1 {
-            atomic::fence(atomic::Acquire);
+        if self.inner().weak.fetch_sub(1, Release) == 1 {
+            atomic::fence(Acquire);
             unsafe { deallocate(ptr as *mut u8, size_of::<ArcInner<T>>(),
                                 min_align_of::<ArcInner<T>>()) }
         }
@@ -377,9 +378,9 @@ impl<T: Sync + Send> Weak<T> {
         // count hits 0 is must never be above 0.
         let inner = self.inner();
         loop {
-            let n = inner.strong.load(atomic::SeqCst);
+            let n = inner.strong.load(SeqCst);
             if n == 0 { return None }
-            let old = inner.strong.compare_and_swap(n, n + 1, atomic::SeqCst);
+            let old = inner.strong.compare_and_swap(n, n + 1, SeqCst);
             if old == n { return Some(Arc { _ptr: self._ptr }) }
         }
     }
@@ -409,7 +410,7 @@ impl<T: Sync + Send> Clone for Weak<T> {
     #[inline]
     fn clone(&self) -> Weak<T> {
         // See comments in Arc::clone() for why this is relaxed
-        self.inner().weak.fetch_add(1, atomic::Relaxed);
+        self.inner().weak.fetch_add(1, Relaxed);
         Weak { _ptr: self._ptr }
     }
 }
@@ -450,15 +451,15 @@ impl<T: Sync + Send> Drop for Weak<T> {
 
         // If we find out that we were the last weak pointer, then its time to deallocate the data
         // entirely. See the discussion in Arc::drop() about the memory orderings
-        if self.inner().weak.fetch_sub(1, atomic::Release) == 1 {
-            atomic::fence(atomic::Acquire);
+        if self.inner().weak.fetch_sub(1, Release) == 1 {
+            atomic::fence(Acquire);
             unsafe { deallocate(ptr as *mut u8, size_of::<ArcInner<T>>(),
                                 min_align_of::<ArcInner<T>>()) }
         }
     }
 }
 
-#[unstable = "waiting on PartialEq"]
+#[stable]
 impl<T: PartialEq> PartialEq for Arc<T> {
     /// Equality for two `Arc<T>`s.
     ///
@@ -490,7 +491,7 @@ impl<T: PartialEq> PartialEq for Arc<T> {
     /// ```
     fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
 }
-#[unstable = "waiting on PartialOrd"]
+#[stable]
 impl<T: PartialOrd> PartialOrd for Arc<T> {
     /// Partial comparison for two `Arc<T>`s.
     ///
@@ -569,11 +570,11 @@ impl<T: PartialOrd> PartialOrd for Arc<T> {
     /// ```
     fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
 }
-#[unstable = "waiting on Ord"]
+#[stable]
 impl<T: Ord> Ord for Arc<T> {
     fn cmp(&self, other: &Arc<T>) -> Ordering { (**self).cmp(&**other) }
 }
-#[unstable = "waiting on Eq"]
+#[stable]
 impl<T: Eq> Eq for Arc<T> {}
 
 impl<T: fmt::Show> fmt::Show for Arc<T> {
@@ -599,6 +600,7 @@ mod tests {
     use std::option::Option::{Some, None};
     use std::str::Str;
     use std::sync::atomic;
+    use std::sync::atomic::Ordering::{Acquire, SeqCst};
     use std::task;
     use std::kinds::Send;
     use std::vec::Vec;
@@ -613,7 +615,7 @@ mod tests {
             unsafe {
                 match *self {
                     Canary(c) => {
-                        (*c).fetch_add(1, atomic::SeqCst);
+                        (*c).fetch_add(1, SeqCst);
                     }
                 }
             }
@@ -722,7 +724,7 @@ mod tests {
 
         let a = Arc::new(Cycle { x: Mutex::new(None) });
         let b = a.clone().downgrade();
-        *a.x.lock() = Some(b);
+        *a.x.lock().unwrap() = Some(b);
 
         // hopefully we don't double-free (or leak)...
     }
@@ -732,7 +734,7 @@ mod tests {
         let mut canary = atomic::AtomicUint::new(0);
         let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint));
         drop(x);
-        assert!(canary.load(atomic::Acquire) == 1);
+        assert!(canary.load(Acquire) == 1);
     }
 
     #[test]
@@ -740,9 +742,9 @@ mod tests {
         let mut canary = atomic::AtomicUint::new(0);
         let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint));
         let arc_weak = arc.downgrade();
-        assert!(canary.load(atomic::Acquire) == 0);
+        assert!(canary.load(Acquire) == 0);
         drop(arc);
-        assert!(canary.load(atomic::Acquire) == 1);
+        assert!(canary.load(Acquire) == 1);
         drop(arc_weak);
     }
 
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 3c6b2d2cbc0..74f0599e486 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -72,12 +72,14 @@ impl<T: Clone> Clone for Box<T> {
     }
 }
 
+#[stable]
 impl<Sized? T: PartialEq> PartialEq for Box<T> {
     #[inline]
     fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
     #[inline]
     fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
 }
+#[stable]
 impl<Sized? T: PartialOrd> PartialOrd for Box<T> {
     #[inline]
     fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
@@ -92,12 +94,14 @@ impl<Sized? T: PartialOrd> PartialOrd for Box<T> {
     #[inline]
     fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
 }
+#[stable]
 impl<Sized? T: Ord> Ord for Box<T> {
     #[inline]
     fn cmp(&self, other: &Box<T>) -> Ordering {
         Ord::cmp(&**self, &**other)
     }
-}
+
+#[stable]}
 impl<Sized? T: Eq> Eq for Box<T> {}
 
 impl<S: hash::Writer, Sized? T: Hash<S>> Hash<S> for Box<T> {
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index c6b6a784f06..cdc30efd2d9 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::ptr::RawPtr;
+use core::ptr::PtrExt;
 
 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
 
@@ -371,7 +371,7 @@ mod imp {
 mod test {
     extern crate test;
     use self::test::Bencher;
-    use core::ptr::RawPtr;
+    use core::ptr::PtrExt;
     use heap;
 
     #[test]
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 13dc4474c1a..bd250938836 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Task-local reference-counted boxes (the `Rc<T>` type).
+//! Thread-local reference-counted boxes (the `Rc<T>` type).
 //!
 //! The `Rc<T>` type provides shared ownership of an immutable value. Destruction is deterministic,
 //! and will occur as soon as the last owner is gone. It is marked as non-sendable because it
@@ -154,7 +154,7 @@ use core::nonzero::NonZero;
 use core::ops::{Deref, Drop};
 use core::option::Option;
 use core::option::Option::{Some, None};
-use core::ptr::{mod, RawPtr};
+use core::ptr::{mod, PtrExt};
 use core::result::Result;
 use core::result::Result::{Ok, Err};
 
@@ -452,7 +452,7 @@ impl<T: Default> Default for Rc<T> {
     }
 }
 
-#[unstable = "PartialEq is unstable."]
+#[stable]
 impl<T: PartialEq> PartialEq for Rc<T> {
     /// Equality for two `Rc<T>`s.
     ///
@@ -487,10 +487,10 @@ impl<T: PartialEq> PartialEq for Rc<T> {
     fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
 }
 
-#[unstable = "Eq is unstable."]
+#[stable]
 impl<T: Eq> Eq for Rc<T> {}
 
-#[unstable = "PartialOrd is unstable."]
+#[stable]
 impl<T: PartialOrd> PartialOrd for Rc<T> {
     /// Partial comparison for two `Rc<T>`s.
     ///
@@ -575,7 +575,7 @@ impl<T: PartialOrd> PartialOrd for Rc<T> {
     fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
 }
 
-#[unstable = "Ord is unstable."]
+#[stable]
 impl<T: Ord> Ord for Rc<T> {
     /// Comparison for two `Rc<T>`s.
     ///
@@ -719,6 +719,13 @@ impl<T> Clone for Weak<T> {
     }
 }
 
+#[experimental = "Show is experimental."]
+impl<T: fmt::Show> fmt::Show for Weak<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "(Weak)")
+    }
+}
+
 #[doc(hidden)]
 trait RcBoxPtr<T> {
     fn inner(&self) -> &RcBox<T>;
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 1f4df1fd0a5..b0fa5434a14 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -412,7 +412,7 @@ impl<T> TypedArenaChunk<T> {
         let size = calculate_size::<T>(self.capacity);
         deallocate(self as *mut TypedArenaChunk<T> as *mut u8, size,
                    mem::min_align_of::<TypedArenaChunk<T>>());
-        if next.is_not_null() {
+        if !next.is_null() {
             let capacity = (*next).capacity;
             (*next).destroy(capacity);
         }
diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs
index dfddf045fc8..f748c8ad1eb 100644
--- a/src/libcollections/binary_heap.rs
+++ b/src/libcollections/binary_heap.rs
@@ -67,7 +67,7 @@
 //! // for a simpler implementation.
 //! fn shortest_path(adj_list: &Vec<Vec<Edge>>, start: uint, goal: uint) -> uint {
 //!     // dist[node] = current shortest distance from `start` to `node`
-//!     let mut dist = Vec::from_elem(adj_list.len(), uint::MAX);
+//!     let mut dist: Vec<_> = range(0, adj_list.len()).map(|_| uint::MAX).collect();
 //!
 //!     let mut heap = BinaryHeap::new();
 //!
@@ -163,6 +163,7 @@ use vec::{mod, Vec};
 ///
 /// This will be a max-heap.
 #[deriving(Clone)]
+#[stable]
 pub struct BinaryHeap<T> {
     data: Vec<T>,
 }
@@ -170,7 +171,6 @@ pub struct BinaryHeap<T> {
 #[stable]
 impl<T: Ord> Default for BinaryHeap<T> {
     #[inline]
-    #[stable]
     fn default() -> BinaryHeap<T> { BinaryHeap::new() }
 }
 
@@ -184,7 +184,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// let mut heap = BinaryHeap::new();
     /// heap.push(4u);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> BinaryHeap<T> { BinaryHeap { data: vec![] } }
 
     /// Creates an empty `BinaryHeap` with a specific capacity.
@@ -199,7 +199,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// let mut heap = BinaryHeap::with_capacity(10);
     /// heap.push(4u);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn with_capacity(capacity: uint) -> BinaryHeap<T> {
         BinaryHeap { data: Vec::with_capacity(capacity) }
     }
@@ -237,7 +237,7 @@ impl<T: Ord> BinaryHeap<T> {
     ///     println!("{}", x);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn iter(&self) -> Iter<T> {
         Iter { iter: self.data.iter() }
     }
@@ -258,7 +258,7 @@ impl<T: Ord> BinaryHeap<T> {
     ///     println!("{}", x);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter { iter: self.data.into_iter() }
     }
@@ -293,7 +293,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert!(heap.capacity() >= 100);
     /// heap.push(4u);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint { self.data.capacity() }
 
     /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
@@ -316,7 +316,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert!(heap.capacity() >= 100);
     /// heap.push(4u);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_exact(&mut self, additional: uint) {
         self.data.reserve_exact(additional);
     }
@@ -337,13 +337,13 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert!(heap.capacity() >= 100);
     /// heap.push(4u);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve(&mut self, additional: uint) {
         self.data.reserve(additional);
     }
 
     /// Discards as much additional capacity as possible.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn shrink_to_fit(&mut self) {
         self.data.shrink_to_fit();
     }
@@ -361,7 +361,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert_eq!(heap.pop(), Some(1));
     /// assert_eq!(heap.pop(), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn pop(&mut self) -> Option<T> {
         self.data.pop().map(|mut item| {
             if !self.is_empty() {
@@ -386,7 +386,7 @@ impl<T: Ord> BinaryHeap<T> {
     /// assert_eq!(heap.len(), 3);
     /// assert_eq!(heap.peek(), Some(&5));
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn push(&mut self, item: T) {
         let old_len = self.len();
         self.data.push(item);
@@ -541,11 +541,11 @@ impl<T: Ord> BinaryHeap<T> {
     }
 
     /// Returns the length of the binary heap.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint { self.data.len() }
 
     /// Checks if the binary heap is empty.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears the binary heap, returning an iterator over the removed elements.
@@ -556,7 +556,7 @@ impl<T: Ord> BinaryHeap<T> {
     }
 
     /// Drops all items from the binary heap.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) { self.drain(); }
 }
 
@@ -565,6 +565,14 @@ pub struct Iter <'a, T: 'a> {
     iter: slice::Iter<'a, T>,
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, T> Clone for Iter<'a, T> {
+    fn clone(&self) -> Iter<'a, T> {
+        Iter { iter: self.iter.clone() }
+    }
+}
+
+#[stable]
 impl<'a, T> Iterator<&'a T> for Iter<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a T> { self.iter.next() }
@@ -573,11 +581,13 @@ impl<'a, T> Iterator<&'a T> for Iter<'a, T> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
+#[stable]
 impl<'a, T> DoubleEndedIterator<&'a T> for Iter<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() }
 }
 
+#[stable]
 impl<'a, T> ExactSizeIterator<&'a T> for Iter<'a, T> {}
 
 /// An iterator that moves out of a `BinaryHeap`.
@@ -585,6 +595,7 @@ pub struct IntoIter<T> {
     iter: vec::IntoIter<T>,
 }
 
+#[stable]
 impl<T> Iterator<T> for IntoIter<T> {
     #[inline]
     fn next(&mut self) -> Option<T> { self.iter.next() }
@@ -593,11 +604,13 @@ impl<T> Iterator<T> for IntoIter<T> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
+#[stable]
 impl<T> DoubleEndedIterator<T> for IntoIter<T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
 }
 
+#[stable]
 impl<T> ExactSizeIterator<T> for IntoIter<T> {}
 
 /// An iterator that drains a `BinaryHeap`.
@@ -605,6 +618,7 @@ pub struct Drain<'a, T: 'a> {
     iter: vec::Drain<'a, T>,
 }
 
+#[stable]
 impl<'a, T: 'a> Iterator<T> for Drain<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<T> { self.iter.next() }
@@ -613,19 +627,23 @@ impl<'a, T: 'a> Iterator<T> for Drain<'a, T> {
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
+#[stable]
 impl<'a, T: 'a> DoubleEndedIterator<T> for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
 }
 
+#[stable]
 impl<'a, T: 'a> ExactSizeIterator<T> for Drain<'a, T> {}
 
+#[stable]
 impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
     fn from_iter<Iter: Iterator<T>>(iter: Iter) -> BinaryHeap<T> {
         BinaryHeap::from_vec(iter.collect())
     }
 }
 
+#[stable]
 impl<T: Ord> Extend<T> for BinaryHeap<T> {
     fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
         let (lower, _) = iter.size_hint();
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index fe3267b6c35..91dea72ec8d 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -94,11 +94,12 @@ use core::num::Int;
 use core::ops::Index;
 use core::slice::{Iter, IterMut};
 use core::{u8, u32, uint};
+use bitv_set; //so meta
 
 use Vec;
 
-type Blocks<'a> = Cloned<Iter<'a, u32>>;
-type MutBlocks<'a> = IterMut<'a, u32>;
+type Blocks<'a> = Cloned<slice::Iter<'a, u32>>;
+type MutBlocks<'a> = slice::IterMut<'a, u32>;
 type MatchWords<'a> = Chain<Enumerate<Blocks<'a>>, Skip<Take<Enumerate<Repeat<u32>>>>>;
 
 fn reverse_bits(byte: u8) -> u8 {
@@ -155,6 +156,7 @@ static FALSE: bool = false;
 /// println!("{}", bv.to_string());
 /// println!("total bits set to true: {}", bv.iter().filter(|x| *x).count());
 /// ```
+#[stable]
 pub struct Bitv {
     /// Internal representation of the bit vector
     storage: Vec<u32>,
@@ -165,7 +167,7 @@ pub struct Bitv {
 // FIXME(Gankro): NopeNopeNopeNopeNope (wait for IndexGet to be a thing)
 impl Index<uint,bool> for Bitv {
     #[inline]
-    fn index<'a>(&'a self, i: &uint) -> &'a bool {
+    fn index(&self, i: &uint) -> &bool {
         if self.get(*i).expect("index out of bounds") {
             &TRUE
         } else {
@@ -248,7 +250,7 @@ impl Bitv {
     /// use std::collections::Bitv;
     /// let mut bv = Bitv::new();
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> Bitv {
         Bitv { storage: Vec::new(), nbits: 0 }
     }
@@ -270,7 +272,7 @@ impl Bitv {
     pub fn from_elem(nbits: uint, bit: bool) -> Bitv {
         let nblocks = blocks_for_bits(nbits);
         let mut bitv = Bitv {
-            storage: Vec::from_elem(nblocks, if bit { !0u32 } else { 0u32 }),
+            storage: repeat(if bit { !0u32 } else { 0u32 }).take(nblocks).collect(),
             nbits: nbits
         };
         bitv.fix_last_block();
@@ -284,7 +286,7 @@ impl Bitv {
     ///
     /// It is important to note that this function does not specify the
     /// *length* of the returned bitvector, but only the *capacity*.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn with_capacity(nbits: uint) -> Bitv {
         Bitv {
             storage: Vec::with_capacity(blocks_for_bits(nbits)),
@@ -370,7 +372,7 @@ impl Bitv {
     /// assert_eq!(bv[1], true);
     /// ```
     #[inline]
-    #[unstable = "panic semantics are likely to change in the future"]
+    #[stable]
     pub fn get(&self, i: uint) -> Option<bool> {
         if i >= self.nbits {
             return None;
@@ -581,9 +583,9 @@ impl Bitv {
     /// assert_eq!(bv.iter().filter(|x| *x).count(), 7);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter<'a>(&'a self) -> Bits<'a> {
-        Bits { bitv: self, next_idx: 0, end_idx: self.nbits }
+    #[stable]
+    pub fn iter(&self) -> Iter {
+        Iter { bitv: self, next_idx: 0, end_idx: self.nbits }
     }
 
     /// Returns `true` if all bits are 0.
@@ -654,7 +656,7 @@ impl Bitv {
 
         let len = self.nbits/8 +
                   if self.nbits % 8 == 0 { 0 } else { 1 };
-        Vec::from_fn(len, |i|
+        range(0, len).map(|i|
             bit(self, i, 0) |
             bit(self, i, 1) |
             bit(self, i, 2) |
@@ -663,7 +665,7 @@ impl Bitv {
             bit(self, i, 5) |
             bit(self, i, 6) |
             bit(self, i, 7)
-        )
+        ).collect()
     }
 
     /// Deprecated: Use `iter().collect()`.
@@ -708,7 +710,7 @@ impl Bitv {
     /// bv.truncate(2);
     /// assert!(bv.eq_vec(&[false, true]));
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn truncate(&mut self, len: uint) {
         if len < self.len() {
             self.nbits = len;
@@ -735,7 +737,7 @@ impl Bitv {
     /// assert_eq!(bv.len(), 3);
     /// assert!(bv.capacity() >= 13);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve(&mut self, additional: uint) {
         let desired_cap = self.len().checked_add(additional).expect("capacity overflow");
         let storage_len = self.storage.len();
@@ -765,7 +767,7 @@ impl Bitv {
     /// assert_eq!(bv.len(), 3);
     /// assert!(bv.capacity() >= 13);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_exact(&mut self, additional: uint) {
         let desired_cap = self.len().checked_add(additional).expect("capacity overflow");
         let storage_len = self.storage.len();
@@ -787,7 +789,7 @@ impl Bitv {
     /// assert!(bv.capacity() >= 10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint {
         self.storage.capacity().checked_mul(u32::BITS).unwrap_or(uint::MAX)
     }
@@ -837,7 +839,7 @@ impl Bitv {
         // Allocate new words, if needed
         if new_nblocks > self.storage.len() {
             let to_add = new_nblocks - self.storage.len();
-            self.storage.grow(to_add, full_value);
+            self.storage.extend(repeat(full_value).take(to_add));
         }
 
         // Adjust internal bit count
@@ -858,7 +860,7 @@ impl Bitv {
     /// assert_eq!(bv.pop(), Some(false));
     /// assert_eq!(bv.len(), 6);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn pop(&mut self) -> Option<bool> {
         if self.is_empty() {
             None
@@ -888,7 +890,7 @@ impl Bitv {
     /// bv.push(false);
     /// assert!(bv.eq_vec(&[true, false]));
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn push(&mut self, elem: bool) {
         if self.nbits % u32::BITS == 0 {
             self.storage.push(0);
@@ -900,17 +902,17 @@ impl Bitv {
 
     /// Return the total number of bits in this vector
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint { self.nbits }
 
     /// Returns true if there are no bits in this vector
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears all bits in this vector.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) {
         for w in self.storage.iter_mut() { *w = 0u32; }
     }
@@ -931,10 +933,10 @@ pub fn from_fn<F>(len: uint, f: F) -> Bitv where F: FnMut(uint) -> bool {
 #[stable]
 impl Default for Bitv {
     #[inline]
-    #[stable]
     fn default() -> Bitv { Bitv::new() }
 }
 
+#[stable]
 impl FromIterator<bool> for Bitv {
     fn from_iter<I:Iterator<bool>>(iterator: I) -> Bitv {
         let mut ret = Bitv::new();
@@ -943,6 +945,7 @@ impl FromIterator<bool> for Bitv {
     }
 }
 
+#[stable]
 impl Extend<bool> for Bitv {
     #[inline]
     fn extend<I: Iterator<bool>>(&mut self, mut iterator: I) {
@@ -968,6 +971,7 @@ impl Clone for Bitv {
     }
 }
 
+#[stable]
 impl PartialOrd for Bitv {
     #[inline]
     fn partial_cmp(&self, other: &Bitv) -> Option<Ordering> {
@@ -975,6 +979,7 @@ impl PartialOrd for Bitv {
     }
 }
 
+#[stable]
 impl Ord for Bitv {
     #[inline]
     fn cmp(&self, other: &Bitv) -> Ordering {
@@ -982,6 +987,7 @@ impl Ord for Bitv {
     }
 }
 
+#[stable]
 impl fmt::Show for Bitv {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         for bit in self.iter() {
@@ -991,6 +997,7 @@ impl fmt::Show for Bitv {
     }
 }
 
+#[stable]
 impl<S: hash::Writer> hash::Hash<S> for Bitv {
     fn hash(&self, state: &mut S) {
         self.nbits.hash(state);
@@ -1000,6 +1007,7 @@ impl<S: hash::Writer> hash::Hash<S> for Bitv {
     }
 }
 
+#[stable]
 impl cmp::PartialEq for Bitv {
     #[inline]
     fn eq(&self, other: &Bitv) -> bool {
@@ -1010,16 +1018,20 @@ impl cmp::PartialEq for Bitv {
     }
 }
 
+#[stable]
 impl cmp::Eq for Bitv {}
 
 /// An iterator for `Bitv`.
-pub struct Bits<'a> {
+#[stable]
+#[deriving(Clone)]
+pub struct Iter<'a> {
     bitv: &'a Bitv,
     next_idx: uint,
     end_idx: uint,
 }
 
-impl<'a> Iterator<bool> for Bits<'a> {
+#[stable]
+impl<'a> Iterator<bool> for Iter<'a> {
     #[inline]
     fn next(&mut self) -> Option<bool> {
         if self.next_idx != self.end_idx {
@@ -1037,7 +1049,8 @@ impl<'a> Iterator<bool> for Bits<'a> {
     }
 }
 
-impl<'a> DoubleEndedIterator<bool> for Bits<'a> {
+#[stable]
+impl<'a> DoubleEndedIterator<bool> for Iter<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<bool> {
         if self.next_idx != self.end_idx {
@@ -1049,9 +1062,11 @@ impl<'a> DoubleEndedIterator<bool> for Bits<'a> {
     }
 }
 
-impl<'a> ExactSizeIterator<bool> for Bits<'a> {}
+#[stable]
+impl<'a> ExactSizeIterator<bool> for Iter<'a> {}
 
-impl<'a> RandomAccessIterator<bool> for Bits<'a> {
+#[stable]
+impl<'a> RandomAccessIterator<bool> for Iter<'a> {
     #[inline]
     fn indexable(&self) -> uint {
         self.end_idx - self.next_idx
@@ -1106,15 +1121,18 @@ impl<'a> RandomAccessIterator<bool> for Bits<'a> {
 /// assert!(bv[3]);
 /// ```
 #[deriving(Clone)]
+#[stable]
 pub struct BitvSet {
     bitv: Bitv,
 }
 
+#[stable]
 impl Default for BitvSet {
     #[inline]
     fn default() -> BitvSet { BitvSet::new() }
 }
 
+#[stable]
 impl FromIterator<uint> for BitvSet {
     fn from_iter<I:Iterator<uint>>(iterator: I) -> BitvSet {
         let mut ret = BitvSet::new();
@@ -1123,6 +1141,7 @@ impl FromIterator<uint> for BitvSet {
     }
 }
 
+#[stable]
 impl Extend<uint> for BitvSet {
     #[inline]
     fn extend<I: Iterator<uint>>(&mut self, mut iterator: I) {
@@ -1132,6 +1151,7 @@ impl Extend<uint> for BitvSet {
     }
 }
 
+#[stable]
 impl PartialOrd for BitvSet {
     #[inline]
     fn partial_cmp(&self, other: &BitvSet) -> Option<Ordering> {
@@ -1140,6 +1160,7 @@ impl PartialOrd for BitvSet {
     }
 }
 
+#[stable]
 impl Ord for BitvSet {
     #[inline]
     fn cmp(&self, other: &BitvSet) -> Ordering {
@@ -1148,6 +1169,7 @@ impl Ord for BitvSet {
     }
 }
 
+#[stable]
 impl cmp::PartialEq for BitvSet {
     #[inline]
     fn eq(&self, other: &BitvSet) -> bool {
@@ -1156,6 +1178,7 @@ impl cmp::PartialEq for BitvSet {
     }
 }
 
+#[stable]
 impl cmp::Eq for BitvSet {}
 
 impl BitvSet {
@@ -1169,7 +1192,7 @@ impl BitvSet {
     /// let mut s = BitvSet::new();
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> BitvSet {
         BitvSet { bitv: Bitv::new() }
     }
@@ -1186,7 +1209,7 @@ impl BitvSet {
     /// assert!(s.capacity() >= 100);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn with_capacity(nbits: uint) -> BitvSet {
         let bitv = Bitv::from_elem(nbits, false);
         BitvSet::from_bitv(bitv)
@@ -1224,7 +1247,7 @@ impl BitvSet {
     /// assert!(s.capacity() >= 100);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint {
         self.bitv.capacity()
     }
@@ -1245,7 +1268,7 @@ impl BitvSet {
     /// s.reserve_len(10);
     /// assert!(s.capacity() >= 10);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_len(&mut self, len: uint) {
         let cur_len = self.bitv.len();
         if len >= cur_len {
@@ -1271,7 +1294,7 @@ impl BitvSet {
     /// s.reserve_len_exact(10);
     /// assert!(s.capacity() >= 10);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_len_exact(&mut self, len: uint) {
         let cur_len = self.bitv.len();
         if len >= cur_len {
@@ -1314,7 +1337,7 @@ impl BitvSet {
     /// assert_eq!(bv[0], true);
     /// ```
     #[inline]
-    pub fn get_ref<'a>(&'a self) -> &'a Bitv {
+    pub fn get_ref(&self) -> &Bitv {
         &self.bitv
     }
 
@@ -1365,7 +1388,7 @@ impl BitvSet {
     /// println!("new capacity: {}", s.capacity());
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn shrink_to_fit(&mut self) {
         let bitv = &mut self.bitv;
         // Obtain original length
@@ -1393,9 +1416,9 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter<'a>(&'a self) -> BitPositions<'a> {
-        BitPositions {set: self, next_idx: 0u}
+    #[stable]
+    pub fn iter(&self) -> bitv_set::Iter {
+        SetIter {set: self, next_idx: 0u}
     }
 
     /// Iterator over each u32 stored in `self` union `other`.
@@ -1415,17 +1438,17 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn union<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> {
+    #[stable]
+    pub fn union<'a>(&'a self, other: &'a BitvSet) -> Union<'a> {
         fn or(w1: u32, w2: u32) -> u32 { w1 | w2 }
 
-        TwoBitPositions {
+        Union(TwoBitPositions {
             set: self,
             other: other,
             merge: or,
             current_word: 0u32,
             next_idx: 0u
-        }
+        })
     }
 
     /// Iterator over each uint stored in `self` intersect `other`.
@@ -1445,17 +1468,17 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Take<TwoBitPositions<'a>> {
+    #[stable]
+    pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Intersection<'a> {
         fn bitand(w1: u32, w2: u32) -> u32 { w1 & w2 }
         let min = cmp::min(self.bitv.len(), other.bitv.len());
-        TwoBitPositions {
+        Intersection(TwoBitPositions {
             set: self,
             other: other,
             merge: bitand,
             current_word: 0u32,
             next_idx: 0
-        }.take(min)
+        }.take(min))
     }
 
     /// Iterator over each uint stored in the `self` setminus `other`.
@@ -1482,17 +1505,17 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> {
+    #[stable]
+    pub fn difference<'a>(&'a self, other: &'a BitvSet) -> Difference<'a> {
         fn diff(w1: u32, w2: u32) -> u32 { w1 & !w2 }
 
-        TwoBitPositions {
+        Difference(TwoBitPositions {
             set: self,
             other: other,
             merge: diff,
             current_word: 0u32,
             next_idx: 0
-        }
+        })
     }
 
     /// Iterator over each u32 stored in the symmetric difference of `self` and `other`.
@@ -1513,17 +1536,17 @@ impl BitvSet {
     /// }
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn symmetric_difference<'a>(&'a self, other: &'a BitvSet) -> TwoBitPositions<'a> {
+    #[stable]
+    pub fn symmetric_difference<'a>(&'a self, other: &'a BitvSet) -> SymmetricDifference<'a> {
         fn bitxor(w1: u32, w2: u32) -> u32 { w1 ^ w2 }
 
-        TwoBitPositions {
+        SymmetricDifference(TwoBitPositions {
             set: self,
             other: other,
             merge: bitxor,
             current_word: 0u32,
             next_idx: 0
-        }
+        })
     }
 
     /// Unions in-place with the specified other bit vector.
@@ -1630,28 +1653,28 @@ impl BitvSet {
 
     /// Return the number of set bits in this set.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint  {
         self.bitv.blocks().fold(0, |acc, n| acc + n.count_ones())
     }
 
     /// Returns whether there are no bits set in this set
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool {
         self.bitv.none()
     }
 
     /// Clears all bits in this set
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) {
         self.bitv.clear();
     }
 
     /// Returns `true` if this set contains the specified integer.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn contains(&self, value: &uint) -> bool {
         let bitv = &self.bitv;
         *value < bitv.nbits && bitv[*value]
@@ -1660,14 +1683,14 @@ impl BitvSet {
     /// Returns `true` if the set has no elements in common with `other`.
     /// This is equivalent to checking for an empty intersection.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_disjoint(&self, other: &BitvSet) -> bool {
         self.intersection(other).next().is_none()
     }
 
     /// Returns `true` if the set is a subset of another.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_subset(&self, other: &BitvSet) -> bool {
         let self_bitv = &self.bitv;
         let other_bitv = &other.bitv;
@@ -1681,14 +1704,14 @@ impl BitvSet {
 
     /// Returns `true` if the set is a superset of another.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_superset(&self, other: &BitvSet) -> bool {
         other.is_subset(self)
     }
 
     /// Adds a value to the set. Returns `true` if the value was not already
     /// present in the set.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn insert(&mut self, value: uint) -> bool {
         if self.contains(&value) {
             return false;
@@ -1706,7 +1729,7 @@ impl BitvSet {
 
     /// Removes a value from the set. Returns `true` if the value was
     /// present in the set.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn remove(&mut self, value: &uint) -> bool {
         if !self.contains(value) {
             return false;
@@ -1742,13 +1765,16 @@ impl<S: hash::Writer> hash::Hash<S> for BitvSet {
 }
 
 /// An iterator for `BitvSet`.
-pub struct BitPositions<'a> {
+#[deriving(Clone)]
+#[stable]
+pub struct SetIter<'a> {
     set: &'a BitvSet,
     next_idx: uint
 }
 
 /// An iterator combining two `BitvSet` iterators.
-pub struct TwoBitPositions<'a> {
+#[deriving(Clone)]
+struct TwoBitPositions<'a> {
     set: &'a BitvSet,
     other: &'a BitvSet,
     merge: fn(u32, u32) -> u32,
@@ -1756,7 +1782,17 @@ pub struct TwoBitPositions<'a> {
     next_idx: uint
 }
 
-impl<'a> Iterator<uint> for BitPositions<'a> {
+#[stable]
+pub struct Union<'a>(TwoBitPositions<'a>);
+#[stable]
+pub struct Intersection<'a>(Take<TwoBitPositions<'a>>);
+#[stable]
+pub struct Difference<'a>(TwoBitPositions<'a>);
+#[stable]
+pub struct SymmetricDifference<'a>(TwoBitPositions<'a>);
+
+#[stable]
+impl<'a> Iterator<uint> for SetIter<'a> {
     fn next(&mut self) -> Option<uint> {
         while self.next_idx < self.set.bitv.len() {
             let idx = self.next_idx;
@@ -1776,6 +1812,7 @@ impl<'a> Iterator<uint> for BitPositions<'a> {
     }
 }
 
+#[stable]
 impl<'a> Iterator<uint> for TwoBitPositions<'a> {
     fn next(&mut self) -> Option<uint> {
         while self.next_idx < self.set.bitv.len() ||
@@ -1811,8 +1848,29 @@ impl<'a> Iterator<uint> for TwoBitPositions<'a> {
     }
 }
 
+#[stable]
+impl<'a> Iterator<uint> for Union<'a> {
+    #[inline] fn next(&mut self) -> Option<uint> { self.0.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
+}
+
+#[stable]
+impl<'a> Iterator<uint> for Intersection<'a> {
+    #[inline] fn next(&mut self) -> Option<uint> { self.0.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
+}
 
+#[stable]
+impl<'a> Iterator<uint> for Difference<'a> {
+    #[inline] fn next(&mut self) -> Option<uint> { self.0.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
+}
 
+#[stable]
+impl<'a> Iterator<uint> for SymmetricDifference<'a> {
+    #[inline] fn next(&mut self) -> Option<uint> { self.0.next() }
+    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
+}
 
 
 #[cfg(test)]
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 0030e612f6e..6d41883dc8d 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -82,6 +82,7 @@ use super::node::{mod, Node, Found, GoDown};
 /// done on each operation isn't *catastrophic*, and *is* still bounded by O(B log<sub>B</sub>n),
 /// it is certainly much slower when it does.
 #[deriving(Clone)]
+#[stable]
 pub struct BTreeMap<K, V> {
     root: Node<K, V>,
     length: uint,
@@ -98,26 +99,31 @@ struct AbsIter<T> {
 }
 
 /// An iterator over a BTreeMap's entries.
+#[stable]
 pub struct Iter<'a, K: 'a, V: 'a> {
     inner: AbsIter<Traversal<'a, K, V>>
 }
 
 /// A mutable iterator over a BTreeMap's entries.
+#[stable]
 pub struct IterMut<'a, K: 'a, V: 'a> {
     inner: AbsIter<MutTraversal<'a, K, V>>
 }
 
 /// An owning iterator over a BTreeMap's entries.
+#[stable]
 pub struct IntoIter<K, V> {
     inner: AbsIter<MoveTraversal<K, V>>
 }
 
 /// An iterator over a BTreeMap's keys.
+#[stable]
 pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
 }
 
 /// An iterator over a BTreeMap's values.
+#[stable]
 pub struct Values<'a, K: 'a, V: 'a> {
     inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
 }
@@ -143,7 +149,7 @@ pub struct OccupiedEntry<'a, K:'a, V:'a> {
 
 impl<K: Ord, V> BTreeMap<K, V> {
     /// Makes a new empty BTreeMap with a reasonable choice for B.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> BTreeMap<K, V> {
         //FIXME(Gankro): Tune this as a function of size_of<K/V>?
         BTreeMap::with_b(6)
@@ -174,7 +180,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// a.clear();
     /// assert!(a.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) {
         let b = self.b;
         // avoid recursive destructors by manually traversing the tree
@@ -210,7 +216,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.get(&1), Some(&"a"));
     /// assert_eq!(map.get(&2), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
         let mut cur_node = &self.root;
         loop {
@@ -242,7 +248,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.contains_key(&1), true);
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn contains_key<Sized? Q>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
         self.get(key).is_some()
     }
@@ -272,7 +278,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map[1], "b");
     /// ```
     // See `get` for implementation notes, this is basically a copy-paste with mut's added
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
         // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
         let mut temp_node = &mut self.root;
@@ -339,7 +345,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.insert(37, "c"), Some("b"));
     /// assert_eq!(map[37], "c");
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
         // This is a stack of rawptrs to nodes paired with indices, respectively
         // representing the nodes and edges of our search path. We have to store rawptrs
@@ -454,7 +460,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
         // See `swap` for a more thorough description of the stuff going on in here
         let mut stack = stack::PartialSearchStack::new(self);
@@ -813,6 +819,7 @@ mod stack {
     }
 }
 
+#[stable]
 impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
     fn from_iter<T: Iterator<(K, V)>>(iter: T) -> BTreeMap<K, V> {
         let mut map = BTreeMap::new();
@@ -821,6 +828,7 @@ impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
     }
 }
 
+#[stable]
 impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
     #[inline]
     fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
@@ -830,6 +838,7 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
     }
 }
 
+#[stable]
 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() {
@@ -846,6 +855,7 @@ impl<K: Ord, V> Default for BTreeMap<K, V> {
     }
 }
 
+#[stable]
 impl<K: PartialEq, V: PartialEq> PartialEq for BTreeMap<K, V> {
     fn eq(&self, other: &BTreeMap<K, V>) -> bool {
         self.len() == other.len() &&
@@ -853,8 +863,10 @@ impl<K: PartialEq, V: PartialEq> PartialEq for BTreeMap<K, V> {
     }
 }
 
+#[stable]
 impl<K: Eq, V: Eq> Eq for BTreeMap<K, V> {}
 
+#[stable]
 impl<K: PartialOrd, V: PartialOrd> PartialOrd for BTreeMap<K, V> {
     #[inline]
     fn partial_cmp(&self, other: &BTreeMap<K, V>) -> Option<Ordering> {
@@ -862,6 +874,7 @@ impl<K: PartialOrd, V: PartialOrd> PartialOrd for BTreeMap<K, V> {
     }
 }
 
+#[stable]
 impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
     #[inline]
     fn cmp(&self, other: &BTreeMap<K, V>) -> Ordering {
@@ -869,6 +882,7 @@ impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
     }
 }
 
+#[stable]
 impl<K: Show, V: Show> Show for BTreeMap<K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "{{"));
@@ -882,6 +896,7 @@ impl<K: Show, V: Show> Show for BTreeMap<K, V> {
     }
 }
 
+#[stable]
 impl<K: Ord, Sized? Q, V> Index<Q, V> for BTreeMap<K, V>
     where Q: BorrowFrom<K> + Ord
 {
@@ -890,6 +905,7 @@ impl<K: Ord, Sized? Q, V> Index<Q, V> for BTreeMap<K, V>
     }
 }
 
+#[stable]
 impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for BTreeMap<K, V>
     where Q: BorrowFrom<K> + Ord
 {
@@ -1035,53 +1051,64 @@ impl<K, V, E, T: Traverse<E> + DoubleEndedIterator<TraversalItem<K, V, E>>>
     }
 }
 
+#[stable]
 impl<'a, K, V> Iterator<(&'a K, &'a V)> for Iter<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
+#[stable]
 impl<'a, K, V> DoubleEndedIterator<(&'a K, &'a V)> for Iter<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next_back() }
 }
+#[stable]
 impl<'a, K, V> ExactSizeIterator<(&'a K, &'a V)> for Iter<'a, K, V> {}
 
-
+#[stable]
 impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for IterMut<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
+#[stable]
 impl<'a, K, V> DoubleEndedIterator<(&'a K, &'a mut V)> for IterMut<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next_back() }
 }
+#[stable]
 impl<'a, K, V> ExactSizeIterator<(&'a K, &'a mut V)> for IterMut<'a, K, V> {}
 
-
+#[stable]
 impl<K, V> Iterator<(K, V)> for IntoIter<K, V> {
     fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
+#[stable]
 impl<K, V> DoubleEndedIterator<(K, V)> for IntoIter<K, V> {
     fn next_back(&mut self) -> Option<(K, V)> { self.inner.next_back() }
 }
+#[stable]
 impl<K, V> ExactSizeIterator<(K, V)> for IntoIter<K, V> {}
 
-
+#[stable]
 impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
+#[stable]
 impl<'a, K, V> DoubleEndedIterator<&'a K> for Keys<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a K)> { self.inner.next_back() }
 }
+#[stable]
 impl<'a, K, V> ExactSizeIterator<&'a K> for Keys<'a, K, V> {}
 
-
+#[stable]
 impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
     fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
+#[stable]
 impl<'a, K, V> DoubleEndedIterator<&'a V> for Values<'a, K, V> {
     fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() }
 }
+#[stable]
 impl<'a, K, V> ExactSizeIterator<&'a V> for Values<'a, K, V> {}
 
 
@@ -1142,8 +1169,8 @@ impl<K, V> BTreeMap<K, V> {
     /// let (first_key, first_value) = map.iter().next().unwrap();
     /// assert_eq!((*first_key, *first_value), (1u, "a"));
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter<'a>(&'a self) -> Iter<'a, K, V> {
+    #[stable]
+    pub fn iter(&self) -> Iter<K, V> {
         let len = self.len();
         Iter {
             inner: AbsIter {
@@ -1174,8 +1201,8 @@ impl<K, V> BTreeMap<K, V> {
     ///     }
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, K, V> {
+    #[stable]
+    pub fn iter_mut(&mut self) -> IterMut<K, V> {
         let len = self.len();
         IterMut {
             inner: AbsIter {
@@ -1203,7 +1230,7 @@ impl<K, V> BTreeMap<K, V> {
     ///     println!("{}: {}", key, value);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<K, V> {
         let len = self.len();
         IntoIter {
@@ -1230,7 +1257,7 @@ impl<K, V> BTreeMap<K, V> {
     /// let keys: Vec<uint> = a.keys().cloned().collect();
     /// assert_eq!(keys, vec![1u,2,]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((&'a K, &'a V)) -> &'a K = first; // coerce to fn pointer
@@ -1252,7 +1279,7 @@ impl<K, V> BTreeMap<K, V> {
     /// let values: Vec<&str> = a.values().cloned().collect();
     /// assert_eq!(values, vec!["a","b"]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn values<'a>(&'a self) -> Values<'a, K, V> {
         fn second<A, B>((_, b): (A, B)) -> B { b }
         let second: fn((&'a K, &'a V)) -> &'a V = second; // coerce to fn pointer
@@ -1272,7 +1299,7 @@ impl<K, V> BTreeMap<K, V> {
     /// a.insert(1u, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint { self.length }
 
     /// Return true if the map contains no elements.
@@ -1287,7 +1314,7 @@ impl<K, V> BTreeMap<K, V> {
     /// a.insert(1u, "a");
     /// assert!(!a.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 }
 
diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs
index 828c1ae89b4..05356368365 100644
--- a/src/libcollections/btree/node.rs
+++ b/src/libcollections/btree/node.rs
@@ -22,6 +22,7 @@ use core::borrow::BorrowFrom;
 use core::cmp::Ordering::{Greater, Less, Equal};
 use core::iter::Zip;
 use core::ops::{Deref, DerefMut};
+use core::ptr::Unique;
 use core::{slice, mem, ptr, cmp, num, raw};
 use alloc::heap;
 
@@ -53,11 +54,11 @@ pub struct Node<K, V> {
     // These will never be null during normal usage of a `Node`. However, to avoid the need for a
     // drop flag, `Node::drop` zeroes `keys`, signaling that the `Node` has already been cleaned
     // up.
-    keys: *mut K,
-    vals: *mut V,
+    keys: Unique<K>,
+    vals: Unique<V>,
 
     // In leaf nodes, this will be null, and no space will be allocated for edges.
-    edges: *mut Node<K, V>,
+    edges: Unique<Node<K, V>>,
 
     // At any given time, there will be `_len` keys, `_len` values, and (in an internal node)
     // `_len + 1` edges. In a leaf node, there will never be any edges.
@@ -257,7 +258,7 @@ impl<T> Drop for RawItems<T> {
 #[unsafe_destructor]
 impl<K, V> Drop for Node<K, V> {
     fn drop(&mut self) {
-        if self.keys.is_null() {
+        if self.keys.0.is_null() {
             // We have already cleaned up this node.
             return;
         }
@@ -271,7 +272,7 @@ impl<K, V> Drop for Node<K, V> {
             self.destroy();
         }
 
-        self.keys = ptr::null_mut();
+        self.keys.0 = ptr::null_mut();
     }
 }
 
@@ -287,9 +288,9 @@ impl<K, V> Node<K, V> {
         let (vals_offset, edges_offset) = calculate_offsets_generic::<K, V>(capacity, false);
 
         Node {
-            keys: buffer as *mut K,
-            vals: buffer.offset(vals_offset as int) as *mut V,
-            edges: buffer.offset(edges_offset as int) as *mut Node<K, V>,
+            keys: Unique(buffer as *mut K),
+            vals: Unique(buffer.offset(vals_offset as int) as *mut V),
+            edges: Unique(buffer.offset(edges_offset as int) as *mut Node<K, V>),
             _len: 0,
             _capacity: capacity,
         }
@@ -305,9 +306,9 @@ impl<K, V> Node<K, V> {
         let (vals_offset, _) = calculate_offsets_generic::<K, V>(capacity, true);
 
         Node {
-            keys: buffer as *mut K,
-            vals: unsafe { buffer.offset(vals_offset as int) as *mut V },
-            edges: ptr::null_mut(),
+            keys: Unique(buffer as *mut K),
+            vals: Unique(unsafe { buffer.offset(vals_offset as int) as *mut V }),
+            edges: Unique(ptr::null_mut()),
             _len: 0,
             _capacity: capacity,
         }
@@ -316,18 +317,18 @@ impl<K, V> Node<K, V> {
     unsafe fn destroy(&mut self) {
         let (alignment, size) =
                 calculate_allocation_generic::<K, V>(self.capacity(), self.is_leaf());
-        heap::deallocate(self.keys as *mut u8, size, alignment);
+        heap::deallocate(self.keys.0 as *mut u8, size, alignment);
     }
 
     #[inline]
     pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) {
         unsafe {(
             mem::transmute(raw::Slice {
-                data: self.keys as *const K,
+                data: self.keys.0 as *const K,
                 len: self.len()
             }),
             mem::transmute(raw::Slice {
-                data: self.vals as *const V,
+                data: self.vals.0 as *const V,
                 len: self.len()
             })
         )}
@@ -346,7 +347,7 @@ impl<K, V> Node<K, V> {
         } else {
             unsafe {
                 mem::transmute(raw::Slice {
-                    data: self.edges as *const Node<K, V>,
+                    data: self.edges.0 as *const Node<K, V>,
                     len: self.len() + 1
                 })
             }
@@ -556,10 +557,10 @@ impl <K, V> Node<K, V> {
         let node = mem::replace(left_and_out, unsafe { Node::new_internal(capacity_from_b(b)) });
         left_and_out._len = 1;
         unsafe {
-            ptr::write(left_and_out.keys_mut().unsafe_mut(0), key);
-            ptr::write(left_and_out.vals_mut().unsafe_mut(0), value);
-            ptr::write(left_and_out.edges_mut().unsafe_mut(0), node);
-            ptr::write(left_and_out.edges_mut().unsafe_mut(1), right);
+            ptr::write(left_and_out.keys_mut().get_unchecked_mut(0), key);
+            ptr::write(left_and_out.vals_mut().get_unchecked_mut(0), value);
+            ptr::write(left_and_out.edges_mut().get_unchecked_mut(0), node);
+            ptr::write(left_and_out.edges_mut().get_unchecked_mut(1), right);
         }
     }
 
@@ -575,7 +576,7 @@ impl <K, V> Node<K, V> {
 
     /// If the node has any children
     pub fn is_leaf(&self) -> bool {
-        self.edges.is_null()
+        self.edges.0.is_null()
     }
 
     /// if the node has too few elements
@@ -638,7 +639,7 @@ impl<'a, K: 'a, V: 'a> Handle<&'a Node<K, V>, handle::Edge, handle::Internal> {
     /// making it more suitable for moving down a chain of nodes.
     pub fn into_edge(self) -> &'a Node<K, V> {
         unsafe {
-            self.node.edges().unsafe_get(self.index)
+            self.node.edges().get_unchecked(self.index)
         }
     }
 }
@@ -649,7 +650,7 @@ impl<'a, K: 'a, V: 'a> Handle<&'a mut Node<K, V>, handle::Edge, handle::Internal
     /// `edge_mut`, making it more suitable for moving down a chain of nodes.
     pub fn into_edge_mut(self) -> &'a mut Node<K, V> {
         unsafe {
-            self.node.edges_mut().unsafe_mut(self.index)
+            self.node.edges_mut().get_unchecked_mut(self.index)
         }
     }
 }
@@ -723,7 +724,7 @@ impl<K, V, NodeRef: DerefMut<Node<K, V>>> Handle<NodeRef, handle::Edge, handle::
     /// confused with `node`, which references the parent node of what is returned here.
     pub fn edge_mut(&mut self) -> &mut Node<K, V> {
         unsafe {
-            self.node.edges_mut().unsafe_mut(self.index)
+            self.node.edges_mut().get_unchecked_mut(self.index)
         }
     }
 
@@ -831,8 +832,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a Node<K, V>, handle::KV, NodeType> {
         let (keys, vals) = self.node.as_slices();
         unsafe {
             (
-                keys.unsafe_get(self.index),
-                vals.unsafe_get(self.index)
+                keys.get_unchecked(self.index),
+                vals.get_unchecked(self.index)
             )
         }
     }
@@ -846,8 +847,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node<K, V>, handle::KV, NodeType
         let (keys, vals) = self.node.as_slices_mut();
         unsafe {
             (
-                keys.unsafe_mut(self.index),
-                vals.unsafe_mut(self.index)
+                keys.get_unchecked_mut(self.index),
+                vals.get_unchecked_mut(self.index)
             )
         }
     }
@@ -871,14 +872,14 @@ impl<'a, K: 'a, V: 'a, NodeRef: Deref<Node<K, V>> + 'a, NodeType> Handle<NodeRef
     // /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the
     // /// handle.
     // pub fn key(&'a self) -> &'a K {
-    //     unsafe { self.node.keys().unsafe_get(self.index) }
+    //     unsafe { self.node.keys().get_unchecked(self.index) }
     // }
     //
     // /// Returns a reference to the value pointed-to by this handle. This doesn't return a
     // /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the
     // /// handle.
     // pub fn val(&'a self) -> &'a V {
-    //     unsafe { self.node.vals().unsafe_get(self.index) }
+    //     unsafe { self.node.vals().get_unchecked(self.index) }
     // }
 }
 
@@ -888,14 +889,14 @@ impl<'a, K: 'a, V: 'a, NodeRef: DerefMut<Node<K, V>> + 'a, NodeType> Handle<Node
     /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the
     /// handle.
     pub fn key_mut(&'a mut self) -> &'a mut K {
-        unsafe { self.node.keys_mut().unsafe_mut(self.index) }
+        unsafe { self.node.keys_mut().get_unchecked_mut(self.index) }
     }
 
     /// Returns a mutable reference to the value pointed-to by this handle. This doesn't return a
     /// reference with a lifetime as large as `into_kv_mut`, but it also does not consume the
     /// handle.
     pub fn val_mut(&'a mut self) -> &'a mut V {
-        unsafe { self.node.vals_mut().unsafe_mut(self.index) }
+        unsafe { self.node.vals_mut().get_unchecked_mut(self.index) }
     }
 }
 
@@ -1059,7 +1060,7 @@ impl<K, V> Node<K, V> {
                     vals: RawItems::from_slice(self.vals()),
                     edges: RawItems::from_slice(self.edges()),
 
-                    ptr: self.keys as *mut u8,
+                    ptr: self.keys.0 as *mut u8,
                     capacity: self.capacity(),
                     is_leaf: self.is_leaf()
                 },
@@ -1079,7 +1080,7 @@ impl<K, V> Node<K, V> {
         debug_assert!(!self.is_leaf());
 
         unsafe {
-            let ret = ptr::read(self.edges().unsafe_get(0));
+            let ret = ptr::read(self.edges().get_unchecked(0));
             self.destroy();
             ptr::write(self, ret);
         }
@@ -1093,8 +1094,8 @@ impl<K, V> Node<K, V> {
     unsafe fn push_kv(&mut self, key: K, val: V) {
         let len = self.len();
 
-        ptr::write(self.keys_mut().unsafe_mut(len), key);
-        ptr::write(self.vals_mut().unsafe_mut(len), val);
+        ptr::write(self.keys_mut().get_unchecked_mut(len), key);
+        ptr::write(self.vals_mut().get_unchecked_mut(len), val);
 
         self._len += 1;
     }
@@ -1104,7 +1105,7 @@ impl<K, V> Node<K, V> {
     unsafe fn push_edge(&mut self, edge: Node<K, V>) {
         let len = self.len();
 
-        ptr::write(self.edges_mut().unsafe_mut(len), edge);
+        ptr::write(self.edges_mut().get_unchecked_mut(len), edge);
     }
 
     // This must be followed by insert_edge on an internal node.
@@ -1121,12 +1122,12 @@ impl<K, V> Node<K, V> {
             self.len() - index
         );
 
-        ptr::write(self.keys_mut().unsafe_mut(index), key);
-        ptr::write(self.vals_mut().unsafe_mut(index), val);
+        ptr::write(self.keys_mut().get_unchecked_mut(index), key);
+        ptr::write(self.vals_mut().get_unchecked_mut(index), val);
 
         self._len += 1;
 
-        self.vals_mut().unsafe_mut(index)
+        self.vals_mut().get_unchecked_mut(index)
     }
 
     // This can only be called immediately after a call to insert_kv.
@@ -1137,14 +1138,14 @@ impl<K, V> Node<K, V> {
             self.edges().as_ptr().offset(index as int),
             self.len() - index
         );
-        ptr::write(self.edges_mut().unsafe_mut(index), edge);
+        ptr::write(self.edges_mut().get_unchecked_mut(index), edge);
     }
 
     // This must be followed by pop_edge on an internal node.
     #[inline]
     unsafe fn pop_kv(&mut self) -> (K, V) {
-        let key = ptr::read(self.keys().unsafe_get(self.len() - 1));
-        let val = ptr::read(self.vals().unsafe_get(self.len() - 1));
+        let key = ptr::read(self.keys().get_unchecked(self.len() - 1));
+        let val = ptr::read(self.vals().get_unchecked(self.len() - 1));
 
         self._len -= 1;
 
@@ -1154,7 +1155,7 @@ impl<K, V> Node<K, V> {
     // This can only be called immediately after a call to pop_kv.
     #[inline]
     unsafe fn pop_edge(&mut self) -> Node<K, V> {
-        let edge = ptr::read(self.edges().unsafe_get(self.len() + 1));
+        let edge = ptr::read(self.edges().get_unchecked(self.len() + 1));
 
         edge
     }
@@ -1162,8 +1163,8 @@ impl<K, V> Node<K, V> {
     // This must be followed by remove_edge on an internal node.
     #[inline]
     unsafe fn remove_kv(&mut self, index: uint) -> (K, V) {
-        let key = ptr::read(self.keys().unsafe_get(index));
-        let val = ptr::read(self.vals().unsafe_get(index));
+        let key = ptr::read(self.keys().get_unchecked(index));
+        let val = ptr::read(self.vals().get_unchecked(index));
 
         ptr::copy_memory(
             self.keys_mut().as_mut_ptr().offset(index as int),
@@ -1184,7 +1185,7 @@ impl<K, V> Node<K, V> {
     // This can only be called immediately after a call to remove_kv.
     #[inline]
     unsafe fn remove_edge(&mut self, index: uint) -> Node<K, V> {
-        let edge = ptr::read(self.edges().unsafe_get(index));
+        let edge = ptr::read(self.edges().get_unchecked(index));
 
         ptr::copy_memory(
             self.edges_mut().as_mut_ptr().offset(index as int),
@@ -1231,8 +1232,8 @@ impl<K, V> Node<K, V> {
                 );
             }
 
-            let key = ptr::read(self.keys().unsafe_get(right_offset - 1));
-            let val = ptr::read(self.vals().unsafe_get(right_offset - 1));
+            let key = ptr::read(self.keys().get_unchecked(right_offset - 1));
+            let val = ptr::read(self.vals().get_unchecked(right_offset - 1));
 
             self._len = right_offset - 1;
 
@@ -1251,8 +1252,8 @@ impl<K, V> Node<K, V> {
             let old_len = self.len();
             self._len += right.len() + 1;
 
-            ptr::write(self.keys_mut().unsafe_mut(old_len), key);
-            ptr::write(self.vals_mut().unsafe_mut(old_len), val);
+            ptr::write(self.keys_mut().get_unchecked_mut(old_len), key);
+            ptr::write(self.vals_mut().get_unchecked_mut(old_len), val);
 
             ptr::copy_nonoverlapping_memory(
                 self.keys_mut().as_mut_ptr().offset(old_len as int + 1),
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index e24b203efed..3e8988530e6 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -31,39 +31,46 @@ use btree_map::{BTreeMap, Keys};
 /// See BTreeMap's documentation for a detailed discussion of this collection's performance
 /// benefits and drawbacks.
 #[deriving(Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
+#[stable]
 pub struct BTreeSet<T>{
     map: BTreeMap<T, ()>,
 }
 
 /// An iterator over a BTreeSet's items.
+#[stable]
 pub struct Iter<'a, T: 'a> {
     iter: Keys<'a, T, ()>
 }
 
 /// An owning iterator over a BTreeSet's items.
+#[stable]
 pub struct IntoIter<T> {
     iter: Map<(T, ()), T, ::btree_map::IntoIter<T, ()>, fn((T, ())) -> T>
 }
 
 /// A lazy iterator producing elements in the set difference (in-order).
+#[stable]
 pub struct Difference<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
 }
 
 /// A lazy iterator producing elements in the set symmetric difference (in-order).
+#[stable]
 pub struct SymmetricDifference<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
 }
 
 /// A lazy iterator producing elements in the set intersection (in-order).
+#[stable]
 pub struct Intersection<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
 }
 
 /// A lazy iterator producing elements in the set union (in-order).
+#[stable]
 pub struct Union<'a, T:'a> {
     a: Peekable<&'a T, Iter<'a, T>>,
     b: Peekable<&'a T, Iter<'a, T>>,
@@ -79,7 +86,7 @@ impl<T: Ord> BTreeSet<T> {
     ///
     /// let mut set: BTreeSet<int> = BTreeSet::new();
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::new() }
     }
@@ -87,6 +94,7 @@ impl<T: Ord> BTreeSet<T> {
     /// Makes a new BTreeSet with the given B.
     ///
     /// B cannot be less than 2.
+    #[unstable = "probably want this to be on the type, eventually"]
     pub fn with_b(b: uint) -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::with_b(b) }
     }
@@ -109,8 +117,8 @@ impl<T> BTreeSet<T> {
     /// let v: Vec<uint> = set.iter().map(|&x| x).collect();
     /// assert_eq!(v, vec![1u,2,3,4]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter<'a>(&'a self) -> Iter<'a, T> {
+    #[stable]
+    pub fn iter(&self) -> Iter<T> {
         Iter { iter: self.map.keys() }
     }
 
@@ -126,7 +134,7 @@ impl<T> BTreeSet<T> {
     /// let v: Vec<uint> = set.into_iter().collect();
     /// assert_eq!(v, vec![1u,2,3,4]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((T, ())) -> T = first; // coerce to fn pointer
@@ -154,7 +162,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let diff: Vec<uint> = a.difference(&b).cloned().collect();
     /// assert_eq!(diff, vec![1u]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
         Difference{a: self.iter().peekable(), b: other.iter().peekable()}
     }
@@ -177,7 +185,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let sym_diff: Vec<uint> = a.symmetric_difference(&b).cloned().collect();
     /// assert_eq!(sym_diff, vec![1u,3]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
         -> SymmetricDifference<'a, T> {
         SymmetricDifference{a: self.iter().peekable(), b: other.iter().peekable()}
@@ -201,7 +209,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let intersection: Vec<uint> = a.intersection(&b).cloned().collect();
     /// assert_eq!(intersection, vec![2u]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
         -> Intersection<'a, T> {
         Intersection{a: self.iter().peekable(), b: other.iter().peekable()}
@@ -223,7 +231,7 @@ impl<T: Ord> BTreeSet<T> {
     /// let union: Vec<uint> = a.union(&b).cloned().collect();
     /// assert_eq!(union, vec![1u,2]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
         Union{a: self.iter().peekable(), b: other.iter().peekable()}
     }
@@ -240,7 +248,7 @@ impl<T: Ord> BTreeSet<T> {
     /// v.insert(1i);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint { self.map.len() }
 
     /// Returns true if the set contains no elements
@@ -255,7 +263,7 @@ impl<T: Ord> BTreeSet<T> {
     /// v.insert(1i);
     /// assert!(!v.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears the set, removing all values.
@@ -270,7 +278,7 @@ impl<T: Ord> BTreeSet<T> {
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) {
         self.map.clear()
     }
@@ -290,7 +298,7 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.contains(&1), true);
     /// assert_eq!(set.contains(&4), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn contains<Sized? Q>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
         self.map.contains_key(value)
     }
@@ -312,7 +320,7 @@ impl<T: Ord> BTreeSet<T> {
     /// b.insert(1);
     /// assert_eq!(a.is_disjoint(&b), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_disjoint(&self, other: &BTreeSet<T>) -> bool {
         self.intersection(other).next().is_none()
     }
@@ -333,7 +341,7 @@ impl<T: Ord> BTreeSet<T> {
     /// set.insert(4);
     /// assert_eq!(set.is_subset(&sup), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_subset(&self, other: &BTreeSet<T>) -> bool {
         // Stolen from TreeMap
         let mut x = self.iter();
@@ -378,7 +386,7 @@ impl<T: Ord> BTreeSet<T> {
     /// set.insert(2);
     /// assert_eq!(set.is_superset(&sub), true);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_superset(&self, other: &BTreeSet<T>) -> bool {
         other.is_subset(self)
     }
@@ -397,7 +405,7 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.insert(2i), false);
     /// assert_eq!(set.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn insert(&mut self, value: T) -> bool {
         self.map.insert(value, ()).is_none()
     }
@@ -420,12 +428,13 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
         self.map.remove(value).is_some()
     }
 }
 
+#[stable]
 impl<T: Ord> FromIterator<T> for BTreeSet<T> {
     fn from_iter<Iter: Iterator<T>>(iter: Iter) -> BTreeSet<T> {
         let mut set = BTreeSet::new();
@@ -434,6 +443,7 @@ impl<T: Ord> FromIterator<T> for BTreeSet<T> {
     }
 }
 
+#[stable]
 impl<T: Ord> Extend<T> for BTreeSet<T> {
     #[inline]
     fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
@@ -451,7 +461,7 @@ impl<T: Ord> Default for BTreeSet<T> {
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
     /// Returns the difference of `self` and `rhs` as a new `BTreeSet<T>`.
     ///
@@ -472,7 +482,7 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
     /// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet<T>`.
     ///
@@ -493,7 +503,7 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeS
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
     /// Returns the intersection of `self` and `rhs` as a new `BTreeSet<T>`.
     ///
@@ -514,7 +524,7 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeS
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSet<T> {
     /// Returns the union of `self` and `rhs` as a new `BTreeSet<T>`.
     ///
@@ -535,6 +545,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>, BTreeSet<T>> for &'a BTreeSe
     }
 }
 
+#[stable]
 impl<T: Show> Show for BTreeSet<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "{{"));
@@ -548,23 +559,28 @@ impl<T: Show> Show for BTreeSet<T> {
     }
 }
 
+#[stable]
 impl<'a, T> Iterator<&'a T> for Iter<'a, T> {
     fn next(&mut self) -> Option<&'a T> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
+#[stable]
 impl<'a, T> DoubleEndedIterator<&'a T> for Iter<'a, T> {
     fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() }
 }
+#[stable]
 impl<'a, T> ExactSizeIterator<&'a T> for Iter<'a, T> {}
 
-
+#[stable]
 impl<T> Iterator<T> for IntoIter<T> {
     fn next(&mut self) -> Option<T> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
+#[stable]
 impl<T> DoubleEndedIterator<T> for IntoIter<T> {
     fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
 }
+#[stable]
 impl<T> ExactSizeIterator<T> for IntoIter<T> {}
 
 /// Compare `x` and `y`, but return `short` if x is None and `long` if y is None
@@ -577,6 +593,7 @@ fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>,
     }
 }
 
+#[stable]
 impl<'a, T: Ord> Iterator<&'a T> for Difference<'a, T> {
     fn next(&mut self) -> Option<&'a T> {
         loop {
@@ -589,6 +606,7 @@ impl<'a, T: Ord> Iterator<&'a T> for Difference<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T: Ord> Iterator<&'a T> for SymmetricDifference<'a, T> {
     fn next(&mut self) -> Option<&'a T> {
         loop {
@@ -601,6 +619,7 @@ impl<'a, T: Ord> Iterator<&'a T> for SymmetricDifference<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T: Ord> Iterator<&'a T> for Intersection<'a, T> {
     fn next(&mut self) -> Option<&'a T> {
         loop {
@@ -619,6 +638,7 @@ impl<'a, T: Ord> Iterator<&'a T> for Intersection<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T: Ord> Iterator<&'a T> for Union<'a, T> {
     fn next(&mut self) -> Option<&'a T> {
         loop {
diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs
index 53fefcc8305..68acbfcb3c3 100644
--- a/src/libcollections/dlist.rs
+++ b/src/libcollections/dlist.rs
@@ -31,6 +31,7 @@ use core::mem;
 use core::ptr;
 
 /// A doubly-linked list.
+#[stable]
 pub struct DList<T> {
     length: uint,
     list_head: Link<T>,
@@ -54,20 +55,27 @@ struct Node<T> {
 }
 
 /// An iterator over references to the items of a `DList`.
+#[stable]
 pub struct Iter<'a, T:'a> {
     head: &'a Link<T>,
     tail: Rawlink<Node<T>>,
     nelem: uint,
 }
 
-// FIXME #11820: the &'a Option<> of the Link stops clone working.
+// FIXME #19839: deriving is too aggressive on the bounds (T doesn't need to be Clone).
+#[stable]
 impl<'a, T> Clone for Iter<'a, T> {
-    fn clone(&self) -> Iter<'a, T> { *self }
+    fn clone(&self) -> Iter<'a, T> {
+        Iter {
+            head: self.head.clone(),
+            tail: self.tail,
+            nelem: self.nelem,
+        }
+    }
 }
 
-impl<'a,T> Copy for Iter<'a,T> {}
-
 /// An iterator over mutable references to the items of a `DList`.
+#[stable]
 pub struct IterMut<'a, T:'a> {
     list: &'a mut DList<T>,
     head: Rawlink<Node<T>>,
@@ -77,6 +85,7 @@ pub struct IterMut<'a, T:'a> {
 
 /// An iterator over mutable references to the items of a `DList`.
 #[deriving(Clone)]
+#[stable]
 pub struct IntoIter<T> {
     list: DList<T>
 }
@@ -96,7 +105,7 @@ impl<T> Rawlink<T> {
     /// Convert the `Rawlink` into an Option value
     fn resolve_immut<'a>(&self) -> Option<&'a T> {
         unsafe {
-            self.p.as_ref()
+            mem::transmute(self.p.as_ref())
         }
     }
 
@@ -205,59 +214,21 @@ impl<T> Default for DList<T> {
 impl<T> DList<T> {
     /// Creates an empty `DList`.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> DList<T> {
         DList{list_head: None, list_tail: Rawlink::none(), length: 0}
     }
 
-    /// Moves the last element to the front of the list.
-    ///
-    /// If the list is empty, does nothing.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::collections::DList;
-    ///
-    /// let mut dl = DList::new();
-    /// dl.push_back(1i);
-    /// dl.push_back(2);
-    /// dl.push_back(3);
-    ///
-    /// dl.rotate_forward();
-    ///
-    /// for e in dl.iter() {
-    ///     println!("{}", e); // prints 3, then 1, then 2
-    /// }
-    /// ```
-    #[inline]
+    /// Deprecated: Not clearly useful enough; use split and append when available.
+    #[deprecated = "Not clearly useful enough; use split and append when available"]
     pub fn rotate_forward(&mut self) {
         self.pop_back_node().map(|tail| {
             self.push_front_node(tail)
         });
     }
 
-    /// Moves the first element to the back of the list.
-    ///
-    /// If the list is empty, does nothing.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::collections::DList;
-    ///
-    /// let mut dl = DList::new();
-    /// dl.push_back(1i);
-    /// dl.push_back(2);
-    /// dl.push_back(3);
-    ///
-    /// dl.rotate_backward();
-    ///
-    /// for e in dl.iter() {
-    ///     println!("{}", e); // prints 2, then 3, then 1
-    /// }
-    /// ```
-    #[inline]
+    /// Deprecated: Not clearly useful enough; use split and append when available.
+    #[deprecated = "Not clearly useful enough; use split and append when available"]
     pub fn rotate_backward(&mut self) {
         self.pop_front_node().map(|head| {
             self.push_back_node(head)
@@ -286,6 +257,7 @@ impl<T> DList<T> {
     ///     println!("{}", e); // prints 1, then 2, then 3, then 4
     /// }
     /// ```
+    #[unstable = "append should be by-mutable-reference"]
     pub fn append(&mut self, mut other: DList<T>) {
         match self.list_tail.resolve() {
             None => *self = other,
@@ -305,57 +277,15 @@ impl<T> DList<T> {
         }
     }
 
-    /// Adds all elements from `other` to the beginning of the list.
-    ///
-    /// This operation should compute in O(1) time.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::collections::DList;
-    ///
-    /// let mut a = DList::new();
-    /// let mut b = DList::new();
-    /// a.push_back(1i);
-    /// a.push_back(2);
-    /// b.push_back(3i);
-    /// b.push_back(4);
-    ///
-    /// a.prepend(b);
-    ///
-    /// for e in a.iter() {
-    ///     println!("{}", e); // prints 3, then 4, then 1, then 2
-    /// }
-    /// ```
-    #[inline]
+    /// Deprecated: Use append and a swap instead.
+    #[deprecated = "Use append and a swap instead"]
     pub fn prepend(&mut self, mut other: DList<T>) {
         mem::swap(self, &mut other);
         self.append(other);
     }
 
-    /// Inserts `elt` before the first `x` in the list where `f(x, elt)` is
-    /// true, or at the end.
-    ///
-    /// This operation should compute in O(N) time.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::collections::DList;
-    ///
-    /// let mut a: DList<int> = DList::new();
-    /// a.push_back(2i);
-    /// a.push_back(4);
-    /// a.push_back(7);
-    /// a.push_back(8);
-    ///
-    /// // insert 11 before the first odd number in the list
-    /// a.insert_when(11, |&e, _| e % 2 == 1);
-    ///
-    /// for e in a.iter() {
-    ///     println!("{}", e); // prints 2, then 4, then 11, then 7, then 8
-    /// }
-    /// ```
+    /// Deprecated: Use custom methods on IterMut.
+    #[deprecated = "Use custom methods on IterMut"]
     pub fn insert_when<F>(&mut self, elt: T, mut f: F) where F: FnMut(&T, &T) -> bool {
         let mut it = self.iter_mut();
         loop {
@@ -368,12 +298,8 @@ impl<T> DList<T> {
         it.insert_next(elt);
     }
 
-    /// Merges `other` into this `DList`, using the function `f`.
-    ///
-    /// Iterates both `DList`s with `a` from self and `b` from `other`, and
-    /// put `a` in the result if `f(a, b)` is true, and otherwise `b`.
-    ///
-    /// This operation should compute in O(max(N, M)) time.
+    /// Deprecated: Use custom methods on IterMut.
+    #[deprecated = "Use custom methods on IterMut"]
     pub fn merge<F>(&mut self, mut other: DList<T>, mut f: F) where F: FnMut(&T, &T) -> bool {
         {
             let mut it = self.iter_mut();
@@ -396,15 +322,15 @@ impl<T> DList<T> {
 
     /// Provides a forward iterator.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter<'a>(&'a self) -> Iter<'a, T> {
+    #[stable]
+    pub fn iter(&self) -> Iter<T> {
         Iter{nelem: self.len(), head: &self.list_head, tail: self.list_tail}
     }
 
     /// Provides a forward iterator with mutable references.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
+    #[stable]
+    pub fn iter_mut(&mut self) -> IterMut<T> {
         let head_raw = match self.list_head {
             Some(ref mut h) => Rawlink::some(&mut **h),
             None => Rawlink::none(),
@@ -419,7 +345,7 @@ impl<T> DList<T> {
 
     /// Consumes the list into an iterator yielding elements by value.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter{list: self}
     }
@@ -428,7 +354,7 @@ impl<T> DList<T> {
     ///
     /// This operation should compute in O(1) time.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool {
         self.list_head.is_none()
     }
@@ -437,7 +363,7 @@ impl<T> DList<T> {
     ///
     /// This operation should compute in O(1) time.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint {
         self.length
     }
@@ -446,7 +372,7 @@ impl<T> DList<T> {
     ///
     /// This operation should compute in O(n) time.
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) {
         *self = DList::new()
     }
@@ -486,7 +412,7 @@ impl<T> DList<T> {
     /// Adds an element first in the list.
     ///
     /// This operation should compute in O(1) time.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn push_front(&mut self, elt: T) {
         self.push_front_node(box Node::new(elt))
     }
@@ -495,7 +421,7 @@ impl<T> DList<T> {
     /// empty.
     ///
     /// This operation should compute in O(1) time.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn pop_front(&mut self) -> Option<T> {
         self.pop_front_node().map(|box Node{value, ..}| value)
     }
@@ -518,7 +444,7 @@ impl<T> DList<T> {
     /// d.push_back(3);
     /// assert_eq!(3, *d.back().unwrap());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn push_back(&mut self, elt: T) {
         self.push_back_node(box Node::new(elt))
     }
@@ -543,23 +469,23 @@ impl<T> DList<T> {
     /// d.push_back(3);
     /// assert_eq!(d.pop_back(), Some(3));
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn pop_back(&mut self) -> Option<T> {
         self.pop_back_node().map(|box Node{value, ..}| value)
     }
 }
 
 impl<T: Ord> DList<T> {
-    /// Inserts `elt` sorted in ascending order.
-    ///
-    /// This operation should compute in O(N) time.
-    #[inline]
+    /// Deprecated: Why are you maintaining a sorted DList?
+    #[deprecated = "Why are you maintaining a sorted DList?"]
+    #[allow(deprecated)]
     pub fn insert_ordered(&mut self, elt: T) {
         self.insert_when(elt, |a, b| a >= b)
     }
 }
 
 #[unsafe_destructor]
+#[stable]
 impl<T> Drop for DList<T> {
     fn drop(&mut self) {
         // Dissolve the dlist in backwards direction
@@ -581,7 +507,7 @@ impl<T> Drop for DList<T> {
     }
 }
 
-
+#[stable]
 impl<'a, A> Iterator<&'a A> for Iter<'a, A> {
     #[inline]
     fn next(&mut self) -> Option<&'a A> {
@@ -601,6 +527,7 @@ impl<'a, A> Iterator<&'a A> for Iter<'a, A> {
     }
 }
 
+#[stable]
 impl<'a, A> DoubleEndedIterator<&'a A> for Iter<'a, A> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a A> {
@@ -615,8 +542,10 @@ impl<'a, A> DoubleEndedIterator<&'a A> for Iter<'a, A> {
     }
 }
 
+#[stable]
 impl<'a, A> ExactSizeIterator<&'a A> for Iter<'a, A> {}
 
+#[stable]
 impl<'a, A> Iterator<&'a mut A> for IterMut<'a, A> {
     #[inline]
     fn next(&mut self) -> Option<&'a mut A> {
@@ -639,6 +568,7 @@ impl<'a, A> Iterator<&'a mut A> for IterMut<'a, A> {
     }
 }
 
+#[stable]
 impl<'a, A> DoubleEndedIterator<&'a mut A> for IterMut<'a, A> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut A> {
@@ -653,6 +583,7 @@ impl<'a, A> DoubleEndedIterator<&'a mut A> for IterMut<'a, A> {
     }
 }
 
+#[stable]
 impl<'a, A> ExactSizeIterator<&'a mut A> for IterMut<'a, A> {}
 
 /// Allows mutating a `DList` while iterating.
@@ -714,6 +645,7 @@ impl<'a, A> IterMut<'a, A> {
     /// }
     /// ```
     #[inline]
+    #[unstable = "this is probably better handled by a cursor type -- we'll see"]
     pub fn insert_next(&mut self, elt: A) {
         self.insert_next_node(box Node::new(elt))
     }
@@ -734,6 +666,7 @@ impl<'a, A> IterMut<'a, A> {
     /// assert_eq!(it.next().unwrap(), &2);
     /// ```
     #[inline]
+    #[unstable = "this is probably better handled by a cursor type -- we'll see"]
     pub fn peek_next(&mut self) -> Option<&mut A> {
         if self.nelem == 0 {
             return None
@@ -742,6 +675,7 @@ impl<'a, A> IterMut<'a, A> {
     }
 }
 
+#[stable]
 impl<A> Iterator<A> for IntoIter<A> {
     #[inline]
     fn next(&mut self) -> Option<A> { self.list.pop_front() }
@@ -752,11 +686,13 @@ impl<A> Iterator<A> for IntoIter<A> {
     }
 }
 
+#[stable]
 impl<A> DoubleEndedIterator<A> for IntoIter<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> { self.list.pop_back() }
 }
 
+#[stable]
 impl<A> FromIterator<A> for DList<A> {
     fn from_iter<T: Iterator<A>>(iterator: T) -> DList<A> {
         let mut ret = DList::new();
@@ -765,12 +701,14 @@ impl<A> FromIterator<A> for DList<A> {
     }
 }
 
+#[stable]
 impl<A> Extend<A> for DList<A> {
     fn extend<T: Iterator<A>>(&mut self, mut iterator: T) {
         for elt in iterator { self.push_back(elt); }
     }
 }
 
+#[stable]
 impl<A: PartialEq> PartialEq for DList<A> {
     fn eq(&self, other: &DList<A>) -> bool {
         self.len() == other.len() &&
@@ -783,14 +721,17 @@ impl<A: PartialEq> PartialEq for DList<A> {
     }
 }
 
+#[stable]
 impl<A: Eq> Eq for DList<A> {}
 
+#[stable]
 impl<A: PartialOrd> PartialOrd for DList<A> {
     fn partial_cmp(&self, other: &DList<A>) -> Option<Ordering> {
         iter::order::partial_cmp(self.iter(), other.iter())
     }
 }
 
+#[stable]
 impl<A: Ord> Ord for DList<A> {
     #[inline]
     fn cmp(&self, other: &DList<A>) -> Ordering {
@@ -805,6 +746,7 @@ impl<A: Clone> Clone for DList<A> {
     }
 }
 
+#[stable]
 impl<A: fmt::Show> fmt::Show for DList<A> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "["));
@@ -818,6 +760,7 @@ impl<A: fmt::Show> fmt::Show for DList<A> {
     }
 }
 
+#[stable]
 impl<S: Writer, A: Hash<S>> Hash<S> for DList<A> {
     fn hash(&self, state: &mut S) {
         self.len().hash(state);
@@ -1291,8 +1234,10 @@ mod tests {
                     v.pop();
                 }
                 1 => {
-                    m.pop_front();
-                    v.remove(0);
+                    if !v.is_empty() {
+                        m.pop_front();
+                        v.remove(0);
+                    }
                 }
                 2 | 4 =>  {
                     m.push_front(-i);
@@ -1317,7 +1262,7 @@ mod tests {
 
     #[bench]
     fn bench_collect_into(b: &mut test::Bencher) {
-        let v = &[0i, ..64];
+        let v = &[0i; 64];
         b.iter(|| {
             let _: DList<int> = v.iter().map(|x| *x).collect();
         })
@@ -1379,7 +1324,7 @@ mod tests {
 
     #[bench]
     fn bench_iter(b: &mut test::Bencher) {
-        let v = &[0i, ..128];
+        let v = &[0i; 128];
         let m: DList<int> = v.iter().map(|&x|x).collect();
         b.iter(|| {
             assert!(m.iter().count() == 128);
@@ -1387,7 +1332,7 @@ mod tests {
     }
     #[bench]
     fn bench_iter_mut(b: &mut test::Bencher) {
-        let v = &[0i, ..128];
+        let v = &[0i; 128];
         let mut m: DList<int> = v.iter().map(|&x|x).collect();
         b.iter(|| {
             assert!(m.iter_mut().count() == 128);
@@ -1395,7 +1340,7 @@ mod tests {
     }
     #[bench]
     fn bench_iter_rev(b: &mut test::Bencher) {
-        let v = &[0i, ..128];
+        let v = &[0i; 128];
         let m: DList<int> = v.iter().map(|&x|x).collect();
         b.iter(|| {
             assert!(m.iter().rev().count() == 128);
@@ -1403,7 +1348,7 @@ mod tests {
     }
     #[bench]
     fn bench_iter_mut_rev(b: &mut test::Bencher) {
-        let v = &[0i, ..128];
+        let v = &[0i; 128];
         let mut m: DList<int> = v.iter().map(|&x|x).collect();
         b.iter(|| {
             assert!(m.iter_mut().rev().count() == 128);
diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs
index fae3228b064..ea3d8659f54 100644
--- a/src/libcollections/enum_set.rs
+++ b/src/libcollections/enum_set.rs
@@ -215,6 +215,16 @@ pub struct Iter<E> {
     bits: uint,
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<E> Clone for Iter<E> {
+    fn clone(&self) -> Iter<E> {
+        Iter {
+            index: self.index,
+            bits: self.bits,
+        }
+    }
+}
+
 impl<E:CLike> Iter<E> {
     fn new(bits: uint) -> Iter<E> {
         Iter { index: 0, bits: bits }
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index 363d30abd03..cbd8d4955b2 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -64,11 +64,12 @@ pub mod vec;
 pub mod vec_map;
 
 pub mod bitv {
-    pub use bit::{Bitv, Bits, from_fn, from_bytes};
+    pub use bit::{Bitv, Iter, from_fn, from_bytes};
 }
 
 pub mod bitv_set {
-    pub use bit::{BitvSet, BitPositions, TwoBitPositions};
+    pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
+    pub use bit::SetIter as Iter;
 }
 
 pub mod btree_map {
@@ -114,22 +115,22 @@ mod prelude {
     pub use core::ops::{Drop, Fn, FnMut, FnOnce};
     pub use core::option::Option;
     pub use core::option::Option::{Some, None};
-    pub use core::ptr::RawPtr;
+    pub use core::ptr::PtrExt;
     pub use core::result::Result;
     pub use core::result::Result::{Ok, Err};
 
     // in core and collections (may differ).
     pub use slice::{PartialEqSliceExt, OrdSliceExt};
     pub use slice::{AsSlice, SliceExt};
-    pub use str::{from_str, Str};
+    pub use str::{from_str, Str, StrExt};
 
     // from other crates.
     pub use alloc::boxed::Box;
     pub use unicode::char::UnicodeChar;
 
     // from collections.
-    pub use slice::{CloneSliceExt, VectorVector};
-    pub use str::{IntoMaybeOwned, StrVector};
+    pub use slice::{CloneSliceExt, SliceConcatExt};
+    pub use str::IntoMaybeOwned;
     pub use string::{String, ToString};
     pub use vec::Vec;
 }
diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs
index 66f7b9e9c4c..e4c9e51a845 100644
--- a/src/libcollections/ring_buf.rs
+++ b/src/libcollections/ring_buf.rs
@@ -37,6 +37,7 @@ static MINIMUM_CAPACITY: uint = 2u;
 // be scrapped anyway. Defer to rewrite?
 
 /// `RingBuf` is a circular buffer, which can be used as a double-ended queue efficiently.
+#[stable]
 pub struct RingBuf<T> {
     // tail and head are pointers into the buffer. Tail always points
     // to the first element that could be read, Head always points
@@ -51,6 +52,12 @@ pub struct RingBuf<T> {
 }
 
 #[stable]
+unsafe impl<T: Send> Send for RingBuf<T> {}
+
+#[stable]
+unsafe impl<T: Sync> Sync for RingBuf<T> {}
+
+#[stable]
 impl<T: Clone> Clone for RingBuf<T> {
     fn clone(&self) -> RingBuf<T> {
         self.iter().map(|t| t.clone()).collect()
@@ -58,6 +65,7 @@ impl<T: Clone> Clone for RingBuf<T> {
 }
 
 #[unsafe_destructor]
+#[stable]
 impl<T> Drop for RingBuf<T> {
     fn drop(&mut self) {
         self.clear();
@@ -73,7 +81,6 @@ impl<T> Drop for RingBuf<T> {
 
 #[stable]
 impl<T> Default for RingBuf<T> {
-    #[stable]
     #[inline]
     fn default() -> RingBuf<T> { RingBuf::new() }
 }
@@ -81,13 +88,13 @@ impl<T> Default for RingBuf<T> {
 impl<T> RingBuf<T> {
     /// Turn ptr into a slice
     #[inline]
-    unsafe fn buffer_as_slice<'a>(&'a self) -> &'a [T] {
+    unsafe fn buffer_as_slice(&self) -> &[T] {
         mem::transmute(RawSlice { data: self.ptr as *const T, len: self.cap })
     }
 
     /// Turn ptr into a mut slice
     #[inline]
-    unsafe fn buffer_as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
+    unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
         mem::transmute(RawSlice { data: self.ptr as *const T, len: self.cap })
     }
 
@@ -127,13 +134,13 @@ impl<T> RingBuf<T> {
 
 impl<T> RingBuf<T> {
     /// Creates an empty `RingBuf`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> RingBuf<T> {
         RingBuf::with_capacity(INITIAL_CAPACITY)
     }
 
     /// Creates an empty `RingBuf` with space for at least `n` elements.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn with_capacity(n: uint) -> RingBuf<T> {
         // +1 since the ringbuffer always leaves one space empty
         let cap = cmp::max(n + 1, MINIMUM_CAPACITY).next_power_of_two();
@@ -171,7 +178,7 @@ impl<T> RingBuf<T> {
     /// buf.push_back(5);
     /// assert_eq!(buf.get(1).unwrap(), &4);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get(&self, i: uint) -> Option<&T> {
         if i < self.len() {
             let idx = self.wrap_index(self.tail + i);
@@ -201,7 +208,7 @@ impl<T> RingBuf<T> {
     ///
     /// assert_eq!(buf[1], 7);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get_mut(&mut self, i: uint) -> Option<&mut T> {
         if i < self.len() {
             let idx = self.wrap_index(self.tail + i);
@@ -253,7 +260,7 @@ impl<T> RingBuf<T> {
     /// assert!(buf.capacity() >= 10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint { self.cap - 1 }
 
     /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
@@ -276,7 +283,7 @@ impl<T> RingBuf<T> {
     /// buf.reserve_exact(10);
     /// assert!(buf.capacity() >= 11);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_exact(&mut self, additional: uint) {
         self.reserve(additional);
     }
@@ -297,7 +304,7 @@ impl<T> RingBuf<T> {
     /// buf.reserve(10);
     /// assert!(buf.capacity() >= 11);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve(&mut self, additional: uint) {
         let new_len = self.len() + additional;
         assert!(new_len + 1 > self.len(), "capacity overflow");
@@ -378,7 +385,7 @@ impl<T> RingBuf<T> {
     /// let b: &[_] = &[&5, &3, &4];
     /// assert_eq!(buf.iter().collect::<Vec<&int>>().as_slice(), b);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn iter(&self) -> Iter<T> {
         Iter {
             tail: self.tail,
@@ -404,7 +411,7 @@ impl<T> RingBuf<T> {
     /// let b: &[_] = &[&mut 3, &mut 1, &mut 2];
     /// assert_eq!(buf.iter_mut().collect::<Vec<&mut int>>()[], b);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
         IterMut {
             tail: self.tail,
@@ -416,7 +423,7 @@ impl<T> RingBuf<T> {
     }
 
     /// Consumes the list into an iterator yielding elements by value.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<T> {
         IntoIter {
             inner: self,
@@ -455,7 +462,7 @@ impl<T> RingBuf<T> {
 
             if contiguous {
                 let (empty, buf) = buf.split_at_mut(0);
-                (buf[mut tail..head], empty)
+                (buf.slice_mut(tail, head), empty)
             } else {
                 let (mid, right) = buf.split_at_mut(tail);
                 let (left, _) = mid.split_at_mut(head);
@@ -477,7 +484,7 @@ impl<T> RingBuf<T> {
     /// v.push_back(1i);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint { count(self.tail, self.head, self.cap) }
 
     /// Returns true if the buffer contains no elements
@@ -492,7 +499,7 @@ impl<T> RingBuf<T> {
     /// v.push_front(1i);
     /// assert!(!v.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Creates a draining iterator that clears the `RingBuf` and iterates over
@@ -510,7 +517,7 @@ impl<T> RingBuf<T> {
     /// ```
     #[inline]
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn drain<'a>(&'a mut self) -> Drain<'a, T> {
+    pub fn drain(&mut self) -> Drain<T> {
         Drain {
             inner: self,
         }
@@ -528,7 +535,7 @@ impl<T> RingBuf<T> {
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     #[inline]
     pub fn clear(&mut self) {
         self.drain();
@@ -639,7 +646,7 @@ impl<T> RingBuf<T> {
     /// assert_eq!(d.pop_front(), Some(2i));
     /// assert_eq!(d.pop_front(), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn pop_front(&mut self) -> Option<T> {
         if self.is_empty() {
             None
@@ -662,7 +669,7 @@ impl<T> RingBuf<T> {
     /// d.push_front(2i);
     /// assert_eq!(d.front(), Some(&2i));
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn push_front(&mut self, t: T) {
         if self.is_full() {
             self.reserve(1);
@@ -692,7 +699,7 @@ impl<T> RingBuf<T> {
     /// buf.push_back(3);
     /// assert_eq!(3, *buf.back().unwrap());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn push_back(&mut self, t: T) {
         if self.is_full() {
             self.reserve(1);
@@ -724,7 +731,7 @@ impl<T> RingBuf<T> {
     /// buf.push_back(3);
     /// assert_eq!(buf.pop_back(), Some(3));
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn pop_back(&mut self) -> Option<T> {
         if self.is_empty() {
             None
@@ -962,7 +969,7 @@ impl<T> RingBuf<T> {
     /// buf.remove(2);
     /// assert_eq!(Some(&15), buf.get(2));
     /// ```
-    #[unstable = "matches collection reform specification; waiting on panic semantics"]
+    #[stable]
     pub fn remove(&mut self, i: uint) -> Option<T> {
         if self.is_empty() || self.len() <= i {
             return None;
@@ -1125,12 +1132,25 @@ fn count(tail: uint, head: uint, size: uint) -> uint {
 }
 
 /// `RingBuf` iterator.
+#[stable]
 pub struct Iter<'a, T:'a> {
     ring: &'a [T],
     tail: uint,
     head: uint
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, T> Clone for Iter<'a, T> {
+    fn clone(&self) -> Iter<'a, T> {
+        Iter {
+            ring: self.ring,
+            tail: self.tail,
+            head: self.head
+        }
+    }
+}
+
+#[stable]
 impl<'a, T> Iterator<&'a T> for Iter<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a T> {
@@ -1139,7 +1159,7 @@ impl<'a, T> Iterator<&'a T> for Iter<'a, T> {
         }
         let tail = self.tail;
         self.tail = wrap_index(self.tail + 1, self.ring.len());
-        unsafe { Some(self.ring.unsafe_get(tail)) }
+        unsafe { Some(self.ring.get_unchecked(tail)) }
     }
 
     #[inline]
@@ -1149,6 +1169,7 @@ impl<'a, T> Iterator<&'a T> for Iter<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T> DoubleEndedIterator<&'a T> for Iter<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a T> {
@@ -1156,12 +1177,14 @@ impl<'a, T> DoubleEndedIterator<&'a T> for Iter<'a, T> {
             return None;
         }
         self.head = wrap_index(self.head - 1, self.ring.len());
-        unsafe { Some(self.ring.unsafe_get(self.head)) }
+        unsafe { Some(self.ring.get_unchecked(self.head)) }
     }
 }
 
+#[stable]
 impl<'a, T> ExactSizeIterator<&'a T> for Iter<'a, T> {}
 
+#[stable]
 impl<'a, T> RandomAccessIterator<&'a T> for Iter<'a, T> {
     #[inline]
     fn indexable(&self) -> uint {
@@ -1175,7 +1198,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Iter<'a, T> {
             None
         } else {
             let idx = wrap_index(self.tail + j, self.ring.len());
-            unsafe { Some(self.ring.unsafe_get(idx)) }
+            unsafe { Some(self.ring.get_unchecked(idx)) }
         }
     }
 }
@@ -1184,6 +1207,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Iter<'a, T> {
 //       with returning the mutable reference. I couldn't find a way to
 //       make the lifetime checker happy so, but there should be a way.
 /// `RingBuf` mutable iterator.
+#[stable]
 pub struct IterMut<'a, T:'a> {
     ptr: *mut T,
     tail: uint,
@@ -1192,6 +1216,7 @@ pub struct IterMut<'a, T:'a> {
     marker: marker::ContravariantLifetime<'a>,
 }
 
+#[stable]
 impl<'a, T> Iterator<&'a mut T> for IterMut<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a mut T> {
@@ -1213,6 +1238,7 @@ impl<'a, T> Iterator<&'a mut T> for IterMut<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T> DoubleEndedIterator<&'a mut T> for IterMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut T> {
@@ -1227,13 +1253,16 @@ impl<'a, T> DoubleEndedIterator<&'a mut T> for IterMut<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T> ExactSizeIterator<&'a mut T> for IterMut<'a, T> {}
 
-// A by-value RingBuf iterator
+/// A by-value RingBuf iterator
+#[stable]
 pub struct IntoIter<T> {
     inner: RingBuf<T>,
 }
 
+#[stable]
 impl<T> Iterator<T> for IntoIter<T> {
     #[inline]
     fn next(&mut self) -> Option<T> {
@@ -1247,6 +1276,7 @@ impl<T> Iterator<T> for IntoIter<T> {
     }
 }
 
+#[stable]
 impl<T> DoubleEndedIterator<T> for IntoIter<T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
@@ -1254,14 +1284,17 @@ impl<T> DoubleEndedIterator<T> for IntoIter<T> {
     }
 }
 
+#[stable]
 impl<T> ExactSizeIterator<T> for IntoIter<T> {}
 
 /// A draining RingBuf iterator
+#[unstable = "matches collection reform specification, waiting for dust to settle"]
 pub struct Drain<'a, T: 'a> {
     inner: &'a mut RingBuf<T>,
 }
 
 #[unsafe_destructor]
+#[stable]
 impl<'a, T: 'a> Drop for Drain<'a, T> {
     fn drop(&mut self) {
         for _ in *self {}
@@ -1270,6 +1303,7 @@ impl<'a, T: 'a> Drop for Drain<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T: 'a> Iterator<T> for Drain<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<T> {
@@ -1283,6 +1317,7 @@ impl<'a, T: 'a> Iterator<T> for Drain<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T: 'a> DoubleEndedIterator<T> for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
@@ -1290,8 +1325,10 @@ impl<'a, T: 'a> DoubleEndedIterator<T> for Drain<'a, T> {
     }
 }
 
+#[stable]
 impl<'a, T: 'a> ExactSizeIterator<T> for Drain<'a, T> {}
 
+#[stable]
 impl<A: PartialEq> PartialEq for RingBuf<A> {
     fn eq(&self, other: &RingBuf<A>) -> bool {
         self.len() == other.len() &&
@@ -1299,14 +1336,17 @@ impl<A: PartialEq> PartialEq for RingBuf<A> {
     }
 }
 
+#[stable]
 impl<A: Eq> Eq for RingBuf<A> {}
 
+#[stable]
 impl<A: PartialOrd> PartialOrd for RingBuf<A> {
     fn partial_cmp(&self, other: &RingBuf<A>) -> Option<Ordering> {
         iter::order::partial_cmp(self.iter(), other.iter())
     }
 }
 
+#[stable]
 impl<A: Ord> Ord for RingBuf<A> {
     #[inline]
     fn cmp(&self, other: &RingBuf<A>) -> Ordering {
@@ -1314,6 +1354,7 @@ impl<A: Ord> Ord for RingBuf<A> {
     }
 }
 
+#[stable]
 impl<S: Writer, A: Hash<S>> Hash<S> for RingBuf<A> {
     fn hash(&self, state: &mut S) {
         self.len().hash(state);
@@ -1323,6 +1364,7 @@ impl<S: Writer, A: Hash<S>> Hash<S> for RingBuf<A> {
     }
 }
 
+#[stable]
 impl<A> Index<uint, A> for RingBuf<A> {
     #[inline]
     fn index<'a>(&'a self, i: &uint) -> &'a A {
@@ -1330,6 +1372,7 @@ impl<A> Index<uint, A> for RingBuf<A> {
     }
 }
 
+#[stable]
 impl<A> IndexMut<uint, A> for RingBuf<A> {
     #[inline]
     fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut A {
@@ -1337,6 +1380,7 @@ impl<A> IndexMut<uint, A> for RingBuf<A> {
     }
 }
 
+#[stable]
 impl<A> FromIterator<A> for RingBuf<A> {
     fn from_iter<T: Iterator<A>>(iterator: T) -> RingBuf<A> {
         let (lower, _) = iterator.size_hint();
@@ -1346,6 +1390,7 @@ impl<A> FromIterator<A> for RingBuf<A> {
     }
 }
 
+#[stable]
 impl<A> Extend<A> for RingBuf<A> {
     fn extend<T: Iterator<A>>(&mut self, mut iterator: T) {
         for elt in iterator {
@@ -1354,6 +1399,7 @@ impl<A> Extend<A> for RingBuf<A> {
     }
 }
 
+#[stable]
 impl<T: fmt::Show> fmt::Show for RingBuf<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "["));
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index a183250fed0..9e2b4b77910 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -89,609 +89,43 @@
 
 use alloc::boxed::Box;
 use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned};
+use core::clone::Clone;
 use core::cmp::Ordering::{mod, Greater, Less};
-use core::cmp;
-use core::iter::{range_step, MultiplicativeIterator};
+use core::cmp::{mod, Ord};
+use core::iter::{Iterator, IteratorExt, IteratorCloneExt};
+use core::iter::{range, range_step, MultiplicativeIterator};
 use core::kinds::Sized;
 use core::mem::size_of;
 use core::mem;
-use core::ops::FnMut;
-use core::prelude::{Clone, Iterator, IteratorExt, None, Option};
-use core::prelude::{Ord, RawPtr, Some, range};
+use core::ops::{FnMut, SliceMut};
+use core::option::Option::{mod, Some, None};
+use core::ptr::PtrExt;
 use core::ptr;
+use core::result::Result;
 use core::slice as core_slice;
 use self::Direction::*;
 
 use vec::Vec;
 
-pub use core::slice::{Chunks, AsSlice, SplitsN, Windows};
+pub use core::slice::{Chunks, AsSlice, Windows};
 pub use core::slice::{Iter, IterMut, PartialEqSliceExt};
-pub use core::slice::{ImmutableIntSlice, MutableIntSlice};
-pub use core::slice::{MutSplits, MutChunks, Splits};
+pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
+pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
 pub use core::slice::{bytes, mut_ref_slice, ref_slice};
-pub use core::slice::{from_raw_buf, from_raw_mut_buf, BinarySearchResult};
+pub use core::slice::{from_raw_buf, from_raw_mut_buf};
 
-// Functional utilities
+#[deprecated = "use Iter instead"]
+pub type Items<'a, T:'a> = Iter<'a, T>;
 
-#[allow(missing_docs)]
-pub trait VectorVector<T> for Sized? {
-    // FIXME #5898: calling these .concat and .connect conflicts with
-    // StrVector::con{cat,nect}, since they have generic contents.
-    /// Flattens a vector of vectors of `T` into a single `Vec<T>`.
-    fn concat_vec(&self) -> Vec<T>;
+#[deprecated = "use IterMut instead"]
+pub type MutItems<'a, T:'a> = IterMut<'a, T>;
 
-    /// Concatenate a vector of vectors, placing a given separator between each.
-    fn connect_vec(&self, sep: &T) -> Vec<T>;
-}
-
-impl<'a, T: Clone, V: AsSlice<T>> VectorVector<T> for [V] {
-    fn concat_vec(&self) -> Vec<T> {
-        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
-        let mut result = Vec::with_capacity(size);
-        for v in self.iter() {
-            result.push_all(v.as_slice())
-        }
-        result
-    }
-
-    fn connect_vec(&self, sep: &T) -> Vec<T> {
-        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
-        let mut result = Vec::with_capacity(size + self.len());
-        let mut first = true;
-        for v in self.iter() {
-            if first { first = false } else { result.push(sep.clone()) }
-            result.push_all(v.as_slice())
-        }
-        result
-    }
-}
-
-/// An iterator that yields the element swaps needed to produce
-/// a sequence of all possible permutations for an indexed sequence of
-/// elements. Each permutation is only a single swap apart.
-///
-/// The Steinhaus-Johnson-Trotter algorithm is used.
-///
-/// Generates even and odd permutations alternately.
-///
-/// The last generated swap is always (0, 1), and it returns the
-/// sequence to its initial order.
-pub struct ElementSwaps {
-    sdir: Vec<SizeDirection>,
-    /// If `true`, emit the last swap that returns the sequence to initial
-    /// state.
-    emit_reset: bool,
-    swaps_made : uint,
-}
-
-impl ElementSwaps {
-    /// Creates an `ElementSwaps` iterator for a sequence of `length` elements.
-    pub fn new(length: uint) -> ElementSwaps {
-        // Initialize `sdir` with a direction that position should move in
-        // (all negative at the beginning) and the `size` of the
-        // element (equal to the original index).
-        ElementSwaps{
-            emit_reset: true,
-            sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(),
-            swaps_made: 0
-        }
-    }
-}
-
-#[deriving(Copy)]
-enum Direction { Pos, Neg }
-
-/// An `Index` and `Direction` together.
-#[deriving(Copy)]
-struct SizeDirection {
-    size: uint,
-    dir: Direction,
-}
-
-impl Iterator<(uint, uint)> for ElementSwaps {
-    #[inline]
-    fn next(&mut self) -> Option<(uint, uint)> {
-        fn new_pos(i: uint, s: Direction) -> uint {
-            i + match s { Pos => 1, Neg => -1 }
-        }
-
-        // Find the index of the largest mobile element:
-        // The direction should point into the vector, and the
-        // swap should be with a smaller `size` element.
-        let max = self.sdir.iter().map(|&x| x).enumerate()
-                           .filter(|&(i, sd)|
-                                new_pos(i, sd.dir) < self.sdir.len() &&
-                                self.sdir[new_pos(i, sd.dir)].size < sd.size)
-                           .max_by(|&(_, sd)| sd.size);
-        match max {
-            Some((i, sd)) => {
-                let j = new_pos(i, sd.dir);
-                self.sdir.swap(i, j);
-
-                // Swap the direction of each larger SizeDirection
-                for x in self.sdir.iter_mut() {
-                    if x.size > sd.size {
-                        x.dir = match x.dir { Pos => Neg, Neg => Pos };
-                    }
-                }
-                self.swaps_made += 1;
-                Some((i, j))
-            },
-            None => if self.emit_reset {
-                self.emit_reset = false;
-                if self.sdir.len() > 1 {
-                    // The last swap
-                    self.swaps_made += 1;
-                    Some((0, 1))
-                } else {
-                    // Vector is of the form [] or [x], and the only permutation is itself
-                    self.swaps_made += 1;
-                    Some((0,0))
-                }
-            } else { None }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        // For a vector of size n, there are exactly n! permutations.
-        let n = range(2, self.sdir.len() + 1).product();
-        (n - self.swaps_made, Some(n - self.swaps_made))
-    }
-}
-
-/// An iterator that uses `ElementSwaps` to iterate through
-/// all possible permutations of a vector.
-///
-/// The first iteration yields a clone of the vector as it is,
-/// then each successive element is the vector with one
-/// swap applied.
-///
-/// Generates even and odd permutations alternately.
-pub struct Permutations<T> {
-    swaps: ElementSwaps,
-    v: Vec<T>,
-}
-
-impl<T: Clone> Iterator<Vec<T>> for Permutations<T> {
-    #[inline]
-    fn next(&mut self) -> Option<Vec<T>> {
-        match self.swaps.next() {
-            None => None,
-            Some((0,0)) => Some(self.v.clone()),
-            Some((a, b)) => {
-                let elt = self.v.clone();
-                self.v.swap(a, b);
-                Some(elt)
-            }
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        self.swaps.size_hint()
-    }
-}
-
-/// Extension methods for boxed slices.
-pub trait BoxedSliceExt<T> {
-    /// Convert `self` into a vector without clones or allocation.
-    fn into_vec(self) -> Vec<T>;
-}
-
-impl<T> BoxedSliceExt<T> for Box<[T]> {
-    #[experimental]
-    fn into_vec(mut self) -> Vec<T> {
-        unsafe {
-            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
-            mem::forget(self);
-            xs
-        }
-    }
-}
-
-/// Allocating extension methods for slices containing `Clone` elements.
-pub trait CloneSliceExt<T> for Sized? {
-    /// Copies `self` into a new `Vec`.
-    fn to_vec(&self) -> Vec<T>;
-
-    /// Partitions the vector into two vectors `(a, b)`, where all
-    /// elements of `a` satisfy `f` and all elements of `b` do not.
-    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool;
-
-    /// Creates an iterator that yields every possible permutation of the
-    /// vector in succession.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// for p in perms {
-    ///   println!("{}", p);
-    /// }
-    /// ```
-    ///
-    /// Iterating through permutations one by one.
-    ///
-    /// ```rust
-    /// let v = [1i, 2, 3];
-    /// let mut perms = v.permutations();
-    ///
-    /// assert_eq!(Some(vec![1i, 2, 3]), perms.next());
-    /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
-    /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
-    /// ```
-    fn permutations(&self) -> Permutations<T>;
-
-    /// Copies as many elements from `src` as it can into `self` (the
-    /// shorter of `self.len()` and `src.len()`). Returns the number
-    /// of elements copied.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let mut dst = [0i, 0, 0];
-    /// let src = [1i, 2];
-    ///
-    /// assert!(dst.clone_from_slice(&src) == 2);
-    /// assert!(dst == [1, 2, 0]);
-    ///
-    /// let src2 = [3i, 4, 5, 6];
-    /// assert!(dst.clone_from_slice(&src2) == 3);
-    /// assert!(dst == [3i, 4, 5]);
-    /// ```
-    fn clone_from_slice(&mut self, &[T]) -> uint;
-}
-
-impl<T: Clone> CloneSliceExt<T> for [T] {
-    /// Returns a copy of `v`.
-    #[inline]
-    fn to_vec(&self) -> Vec<T> {
-        let mut vector = Vec::with_capacity(self.len());
-        vector.push_all(self);
-        vector
-    }
-
-
-    #[inline]
-    fn partitioned<F>(&self, mut f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
-        let mut lefts  = Vec::new();
-        let mut rights = Vec::new();
-
-        for elt in self.iter() {
-            if f(elt) {
-                lefts.push((*elt).clone());
-            } else {
-                rights.push((*elt).clone());
-            }
-        }
-
-        (lefts, rights)
-    }
-
-    /// Returns an iterator over all permutations of a vector.
-    fn permutations(&self) -> Permutations<T> {
-        Permutations{
-            swaps: ElementSwaps::new(self.len()),
-            v: self.to_vec(),
-        }
-    }
-
-    fn clone_from_slice(&mut self, src: &[T]) -> uint {
-        core_slice::CloneSliceExt::clone_from_slice(self, src)
-    }
-}
-
-fn insertion_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
-    let len = v.len() as int;
-    let buf_v = v.as_mut_ptr();
-
-    // 1 <= i < len;
-    for i in range(1, len) {
-        // j satisfies: 0 <= j <= i;
-        let mut j = i;
-        unsafe {
-            // `i` is in bounds.
-            let read_ptr = buf_v.offset(i) as *const T;
-
-            // find where to insert, we need to do strict <,
-            // rather than <=, to maintain stability.
-
-            // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
-            while j > 0 &&
-                    compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
-                j -= 1;
-            }
-
-            // shift everything to the right, to make space to
-            // insert this value.
-
-            // j + 1 could be `len` (for the last `i`), but in
-            // that case, `i == j` so we don't copy. The
-            // `.offset(j)` is always in bounds.
-
-            if i != j {
-                let tmp = ptr::read(read_ptr);
-                ptr::copy_memory(buf_v.offset(j + 1),
-                                 &*buf_v.offset(j),
-                                 (i - j) as uint);
-                ptr::copy_nonoverlapping_memory(buf_v.offset(j),
-                                                &tmp as *const T,
-                                                1);
-                mem::forget(tmp);
-            }
-        }
-    }
-}
-
-fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
-    // warning: this wildly uses unsafe.
-    static BASE_INSERTION: uint = 32;
-    static LARGE_INSERTION: uint = 16;
-
-    // FIXME #12092: smaller insertion runs seems to make sorting
-    // vectors of large elements a little faster on some platforms,
-    // but hasn't been tested/tuned extensively
-    let insertion = if size_of::<T>() <= 16 {
-        BASE_INSERTION
-    } else {
-        LARGE_INSERTION
-    };
-
-    let len = v.len();
-
-    // short vectors get sorted in-place via insertion sort to avoid allocations
-    if len <= insertion {
-        insertion_sort(v, compare);
-        return;
-    }
-
-    // allocate some memory to use as scratch memory, we keep the
-    // length 0 so we can keep shallow copies of the contents of `v`
-    // without risking the dtors running on an object twice if
-    // `compare` panics.
-    let mut working_space = Vec::with_capacity(2 * len);
-    // these both are buffers of length `len`.
-    let mut buf_dat = working_space.as_mut_ptr();
-    let mut buf_tmp = unsafe {buf_dat.offset(len as int)};
-
-    // length `len`.
-    let buf_v = v.as_ptr();
-
-    // step 1. sort short runs with insertion sort. This takes the
-    // values from `v` and sorts them into `buf_dat`, leaving that
-    // with sorted runs of length INSERTION.
-
-    // We could hardcode the sorting comparisons here, and we could
-    // manipulate/step the pointers themselves, rather than repeatedly
-    // .offset-ing.
-    for start in range_step(0, len, insertion) {
-        // start <= i < len;
-        for i in range(start, cmp::min(start + insertion, len)) {
-            // j satisfies: start <= j <= i;
-            let mut j = i as int;
-            unsafe {
-                // `i` is in bounds.
-                let read_ptr = buf_v.offset(i as int);
-
-                // find where to insert, we need to do strict <,
-                // rather than <=, to maintain stability.
-
-                // start <= j - 1 < len, so .offset(j - 1) is in
-                // bounds.
-                while j > start as int &&
-                        compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less {
-                    j -= 1;
-                }
-
-                // shift everything to the right, to make space to
-                // insert this value.
-
-                // j + 1 could be `len` (for the last `i`), but in
-                // that case, `i == j` so we don't copy. The
-                // `.offset(j)` is always in bounds.
-                ptr::copy_memory(buf_dat.offset(j + 1),
-                                 &*buf_dat.offset(j),
-                                 i - j as uint);
-                ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
-            }
-        }
-    }
-
-    // step 2. merge the sorted runs.
-    let mut width = insertion;
-    while width < len {
-        // merge the sorted runs of length `width` in `buf_dat` two at
-        // a time, placing the result in `buf_tmp`.
-
-        // 0 <= start <= len.
-        for start in range_step(0, len, 2 * width) {
-            // manipulate pointers directly for speed (rather than
-            // using a `for` loop with `range` and `.offset` inside
-            // that loop).
-            unsafe {
-                // the end of the first run & start of the
-                // second. Offset of `len` is defined, since this is
-                // precisely one byte past the end of the object.
-                let right_start = buf_dat.offset(cmp::min(start + width, len) as int);
-                // end of the second. Similar reasoning to the above re safety.
-                let right_end_idx = cmp::min(start + 2 * width, len);
-                let right_end = buf_dat.offset(right_end_idx as int);
-
-                // the pointers to the elements under consideration
-                // from the two runs.
-
-                // both of these are in bounds.
-                let mut left = buf_dat.offset(start as int);
-                let mut right = right_start;
-
-                // where we're putting the results, it is a run of
-                // length `2*width`, so we step it once for each step
-                // of either `left` or `right`.  `buf_tmp` has length
-                // `len`, so these are in bounds.
-                let mut out = buf_tmp.offset(start as int);
-                let out_end = buf_tmp.offset(right_end_idx as int);
-
-                while out < out_end {
-                    // Either the left or the right run are exhausted,
-                    // so just copy the remainder from the other run
-                    // and move on; this gives a huge speed-up (order
-                    // of 25%) for mostly sorted vectors (the best
-                    // case).
-                    if left == right_start {
-                        // the number remaining in this run.
-                        let elems = (right_end as uint - right as uint) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*right, elems);
-                        break;
-                    } else if right == right_end {
-                        let elems = (right_start as uint - left as uint) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*left, elems);
-                        break;
-                    }
-
-                    // check which side is smaller, and that's the
-                    // next element for the new run.
-
-                    // `left < right_start` and `right < right_end`,
-                    // so these are valid.
-                    let to_copy = if compare(&*left, &*right) == Greater {
-                        step(&mut right)
-                    } else {
-                        step(&mut left)
-                    };
-                    ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
-                    step(&mut out);
-                }
-            }
-        }
-
-        mem::swap(&mut buf_dat, &mut buf_tmp);
-
-        width *= 2;
-    }
-
-    // write the result to `v` in one go, so that there are never two copies
-    // of the same object in `v`.
-    unsafe {
-        ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
-    }
-
-    // increment the pointer, returning the old pointer.
-    #[inline(always)]
-    unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
-        let old = *ptr;
-        *ptr = ptr.offset(1);
-        old
-    }
-}
-
-/// Allocating extension methods for slices on Ord values.
-#[experimental = "likely to merge with other traits"]
-pub trait OrdSliceExt<T> for Sized? {
-    /// Sorts the slice, in place.
-    ///
-    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let mut v = [-5i, 4, 1, -3, 2];
-    ///
-    /// v.sort();
-    /// assert!(v == [-5i, -3, 1, 2, 4]);
-    /// ```
-    #[experimental]
-    fn sort(&mut self);
-
-    /// Binary search a sorted slice for a given element.
-    ///
-    /// If the value is found then `Found` is returned, containing the
-    /// index of the matching element; if the value is not found then
-    /// `NotFound` is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
-    ///
-    /// # Example
-    ///
-    /// Looks up a series of four elements. The first is found, with a
-    /// uniquely determined position; the second and third are not
-    /// found; the fourth could match any position in `[1,4]`.
-    ///
-    /// ```rust
-    /// use std::slice::BinarySearchResult::{Found, NotFound};
-    /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    /// let s = s.as_slice();
-    ///
-    /// assert_eq!(s.binary_search_elem(&13),  Found(9));
-    /// assert_eq!(s.binary_search_elem(&4),   NotFound(7));
-    /// assert_eq!(s.binary_search_elem(&100), NotFound(13));
-    /// let r = s.binary_search_elem(&1);
-    /// assert!(match r { Found(1...4) => true, _ => false, });
-    /// ```
-    #[unstable = "name likely to change"]
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult;
-
-    /// Mutates the slice to the next lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// last-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [0i, 1, 2];
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.next_permutation();
-    /// let b: &mut [_] = &mut [1i, 0, 2];
-    /// assert!(v == b);
-    /// ```
-    #[experimental]
-    fn next_permutation(&mut self) -> bool;
-
-    /// Mutates the slice to the previous lexicographic permutation.
-    ///
-    /// Returns `true` if successful and `false` if the slice is at the
-    /// first-ordered permutation.
-    ///
-    /// # Example
-    ///
-    /// ```rust
-    /// let v: &mut [_] = &mut [1i, 0, 2];
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 2, 1];
-    /// assert!(v == b);
-    /// v.prev_permutation();
-    /// let b: &mut [_] = &mut [0i, 1, 2];
-    /// assert!(v == b);
-    /// ```
-    #[experimental]
-    fn prev_permutation(&mut self) -> bool;
-}
-
-impl<T: Ord> OrdSliceExt<T> for [T] {
-    #[inline]
-    fn sort(&mut self) {
-        self.sort_by(|a, b| a.cmp(b))
-    }
-
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
-        core_slice::OrdSliceExt::binary_search_elem(self, x)
-    }
-
-    fn next_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::next_permutation(self)
-    }
-
-    fn prev_permutation(&mut self) -> bool {
-        core_slice::OrdSliceExt::prev_permutation(self)
-    }
-}
+////////////////////////////////////////////////////////////////////////////////
+// Basic slice extension methods
+////////////////////////////////////////////////////////////////////////////////
 
 /// Allocating extension methods for slices.
-#[experimental = "likely to merge with other traits"]
+#[unstable = "needs associated types, may merge with other traits"]
 pub trait SliceExt<T> for Sized? {
     /// Sorts the slice, in place, using `compare` to compare
     /// elements.
@@ -710,6 +144,7 @@ pub trait SliceExt<T> for Sized? {
     /// v.sort_by(|a, b| b.cmp(a));
     /// assert!(v == [5, 4, 3, 2, 1]);
     /// ```
+    #[stable]
     fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering;
 
     /// Consumes `src` and moves as many elements as it can into `self`
@@ -733,6 +168,7 @@ pub trait SliceExt<T> for Sized? {
     /// assert_eq!(num_moved, 3);
     /// assert!(a == [6i, 7, 8, 4, 5]);
     /// ```
+    #[experimental = "uncertain about this API approach"]
     fn move_from(&mut self, src: Vec<T>, start: uint, end: uint) -> uint;
 
     /// Returns a subslice spanning the interval [`start`, `end`).
@@ -741,7 +177,7 @@ pub trait SliceExt<T> for Sized? {
     /// original slice (i.e. when `end > self.len()`) or when `start > end`.
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
-    #[unstable = "waiting on final error conventions/slicing syntax"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice(&self, start: uint, end: uint) -> &[T];
 
     /// Returns a subslice from `start` to the end of the slice.
@@ -749,7 +185,7 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `start` is strictly greater than the length of the original slice.
     ///
     /// Slicing from `self.len()` yields an empty slice.
-    #[unstable = "waiting on final error conventions/slicing syntax"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_from(&self, start: uint) -> &[T];
 
     /// Returns a subslice from the start of the slice to `end`.
@@ -757,7 +193,7 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `end` is strictly greater than the length of the original slice.
     ///
     /// Slicing to `0` yields an empty slice.
-    #[unstable = "waiting on final error conventions/slicing syntax"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_to(&self, end: uint) -> &[T];
 
     /// Divides one slice into two at an index.
@@ -767,32 +203,32 @@ pub trait SliceExt<T> for Sized? {
     /// indices from `[mid, len)` (excluding the index `len` itself).
     ///
     /// Panics if `mid > len`.
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn split_at(&self, mid: uint) -> (&[T], &[T]);
 
     /// Returns an iterator over the slice
-    #[unstable = "iterator type may change"]
+    #[stable]
     fn iter(&self) -> Iter<T>;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`.  The matched element is not contained in the subslices.
-    #[unstable = "iterator type may change, waiting on unboxed closures"]
-    fn split<F>(&self, pred: F) -> Splits<T, F>
+    #[stable]
+    fn split<F>(&self, pred: F) -> Split<T, F>
                 where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
-    #[unstable = "iterator type may change"]
-    fn splitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    #[stable]
+    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F>
                  where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
-    #[unstable = "iterator type may change"]
-    fn rsplitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    #[stable]
+    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F>
                   where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over all contiguous windows of length
@@ -814,7 +250,7 @@ pub trait SliceExt<T> for Sized? {
     ///     println!("{}", win);
     /// }
     /// ```
-    #[unstable = "iterator type may change"]
+    #[stable]
     fn windows(&self, size: uint) -> Windows<T>;
 
     /// Returns an iterator over `size` elements of the slice at a
@@ -837,34 +273,44 @@ pub trait SliceExt<T> for Sized? {
     ///     println!("{}", win);
     /// }
     /// ```
-    #[unstable = "iterator type may change"]
+    #[stable]
     fn chunks(&self, size: uint) -> Chunks<T>;
 
     /// Returns the element of a slice at the given index, or `None` if the
     /// index is out of bounds.
-    #[unstable = "waiting on final collection conventions"]
+    #[stable]
     fn get(&self, index: uint) -> Option<&T>;
 
     /// Returns the first element of a slice, or `None` if it is empty.
-    #[unstable = "name may change"]
-    fn head(&self) -> Option<&T>;
+    #[stable]
+    fn first(&self) -> Option<&T>;
+
+    /// Deprecated: renamed to `first`.
+    #[deprecated = "renamed to `first`"]
+    fn head(&self) -> Option<&T> { self.first() }
 
     /// Returns all but the first element of a slice.
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed"]
     fn tail(&self) -> &[T];
 
     /// Returns all but the last element of a slice.
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed"]
     fn init(&self) -> &[T];
 
     /// Returns the last element of a slice, or `None` if it is empty.
-    #[unstable = "name may change"]
+    #[stable]
     fn last(&self) -> Option<&T>;
 
     /// Returns a pointer to the element at the given index, without doing
     /// bounds checking.
-    #[unstable]
-    unsafe fn unsafe_get(&self, index: uint) -> &T;
+    #[stable]
+    unsafe fn get_unchecked(&self, index: uint) -> &T;
+
+    /// Deprecated: renamed to `get_unchecked`.
+    #[deprecated = "renamed to get_unchecked"]
+    unsafe fn unsafe_get(&self, index: uint) -> &T {
+        self.get_unchecked(index)
+    }
 
     /// Returns an unsafe pointer to the slice's buffer
     ///
@@ -873,7 +319,7 @@ pub trait SliceExt<T> for Sized? {
     ///
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
-    #[unstable]
+    #[stable]
     fn as_ptr(&self) -> *const T;
 
     /// Binary search a sorted slice with a comparator function.
@@ -883,9 +329,9 @@ pub trait SliceExt<T> for Sized? {
     /// order code that indicates whether its argument is `Less`,
     /// `Equal` or `Greater` the desired target.
     ///
-    /// If a matching value is found then returns `Found`, containing
+    /// If a matching value is found then returns `Ok`, containing
     /// the index for the matched element; if no match is found then
-    /// `NotFound` is returned, containing the index where a matching
+    /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
     /// # Example
@@ -895,23 +341,22 @@ pub trait SliceExt<T> for Sized? {
     /// found; the fourth could match any position in `[1,4]`.
     ///
     /// ```rust
-    /// use std::slice::BinarySearchResult::{Found, NotFound};
     /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
     /// let s = s.as_slice();
     ///
     /// let seek = 13;
-    /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), Found(9));
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
     /// let seek = 4;
-    /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), NotFound(7));
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(7));
     /// let seek = 100;
-    /// assert_eq!(s.binary_search(|probe| probe.cmp(&seek)), NotFound(13));
+    /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Err(13));
     /// let seek = 1;
-    /// let r = s.binary_search(|probe| probe.cmp(&seek));
-    /// assert!(match r { Found(1...4) => true, _ => false, });
+    /// let r = s.binary_search_by(|probe| probe.cmp(&seek));
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
     /// ```
-    #[unstable = "waiting on unboxed closures"]
-    fn binary_search<F>(&self, f: F) -> BinarySearchResult
-                        where F: FnMut(&T) -> Ordering;
+    #[stable]
+    fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
+        F: FnMut(&T) -> Ordering;
 
     /// Return the number of elements in the slice
     ///
@@ -921,7 +366,7 @@ pub trait SliceExt<T> for Sized? {
     /// let a = [1i, 2, 3];
     /// assert_eq!(a.len(), 3);
     /// ```
-    #[experimental = "not triaged yet"]
+    #[stable]
     fn len(&self) -> uint;
 
     /// Returns true if the slice has a length of 0
@@ -933,15 +378,16 @@ pub trait SliceExt<T> for Sized? {
     /// assert!(!a.is_empty());
     /// ```
     #[inline]
-    #[experimental = "not triaged yet"]
+    #[stable]
     fn is_empty(&self) -> bool { self.len() == 0 }
     /// Returns a mutable reference to the element at the given index,
     /// or `None` if the index is out of bounds
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn get_mut(&mut self, index: uint) -> Option<&mut T>;
 
     /// Work with `self` as a mut slice.
-    /// Primarily intended for getting a &mut [T] from a [T, ..N].
+    /// Primarily intended for getting a &mut [T] from a [T; N].
+    #[stable]
     fn as_mut_slice(&mut self) -> &mut [T];
 
     /// Returns a mutable subslice spanning the interval [`start`, `end`).
@@ -950,7 +396,7 @@ pub trait SliceExt<T> for Sized? {
     /// original slice (i.e. when `end > self.len()`) or when `start > end`.
     ///
     /// Slicing with `start` equal to `end` yields an empty slice.
-    #[unstable = "waiting on final error conventions"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T];
 
     /// Returns a mutable subslice from `start` to the end of the slice.
@@ -958,7 +404,7 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `start` is strictly greater than the length of the original slice.
     ///
     /// Slicing from `self.len()` yields an empty slice.
-    #[unstable = "waiting on final error conventions"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_from_mut(&mut self, start: uint) -> &mut [T];
 
     /// Returns a mutable subslice from the start of the slice to `end`.
@@ -966,48 +412,54 @@ pub trait SliceExt<T> for Sized? {
     /// Panics when `end` is strictly greater than the length of the original slice.
     ///
     /// Slicing to `0` yields an empty slice.
-    #[unstable = "waiting on final error conventions"]
+    #[experimental = "will be replaced by slice syntax"]
     fn slice_to_mut(&mut self, end: uint) -> &mut [T];
 
     /// Returns an iterator that allows modifying each value
-    #[unstable = "waiting on iterator type name conventions"]
+    #[stable]
     fn iter_mut(&mut self) -> IterMut<T>;
 
     /// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
-    #[unstable = "name may change"]
-    fn head_mut(&mut self) -> Option<&mut T>;
+    #[stable]
+    fn first_mut(&mut self) -> Option<&mut T>;
+
+    /// Depreated: renamed to `first_mut`.
+    #[deprecated = "renamed to first_mut"]
+    fn head_mut(&mut self) -> Option<&mut T> {
+        self.first_mut()
+    }
 
     /// Returns all but the first element of a mutable slice
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed or removed"]
     fn tail_mut(&mut self) -> &mut [T];
 
     /// Returns all but the last element of a mutable slice
-    #[unstable = "name may change"]
+    #[experimental = "likely to be renamed or removed"]
     fn init_mut(&mut self) -> &mut [T];
 
     /// Returns a mutable pointer to the last item in the slice.
-    #[unstable = "name may change"]
+    #[stable]
     fn last_mut(&mut self) -> Option<&mut T>;
 
     /// Returns an iterator over mutable subslices separated by elements that
     /// match `pred`.  The matched element is not contained in the subslices.
-    #[unstable = "waiting on unboxed closures, iterator type name conventions"]
-    fn split_mut<F>(&mut self, pred: F) -> MutSplits<T, F>
+    #[stable]
+    fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
                     where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`, limited to splitting at most `n` times.  The matched element is
     /// not contained in the subslices.
-    #[unstable = "waiting on unboxed closures, iterator type name conventions"]
-    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    #[stable]
+    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F>
                      where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over subslices separated by elements that match
     /// `pred` limited to splitting at most `n` times. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
-    #[unstable = "waiting on unboxed closures, iterator type name conventions"]
-    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    #[stable]
+    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<T, F>
                       where F: FnMut(&T) -> bool;
 
     /// Returns an iterator over `chunk_size` elements of the slice at a time.
@@ -1018,18 +470,20 @@ pub trait SliceExt<T> for Sized? {
     /// # Panics
     ///
     /// Panics if `chunk_size` is 0.
-    #[unstable = "waiting on iterator type name conventions"]
-    fn chunks_mut(&mut self, chunk_size: uint) -> MutChunks<T>;
+    #[stable]
+    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T>;
 
     /// Swaps two elements in a slice.
     ///
-    /// Panics if `a` or `b` are out of bounds.
-    ///
     /// # Arguments
     ///
     /// * a - The index of the first element
     /// * b - The index of the second element
     ///
+    /// # Panics
+    ///
+    /// Panics if `a` or `b` are out of bounds.
+    ///
     /// # Example
     ///
     /// ```rust
@@ -1037,7 +491,7 @@ pub trait SliceExt<T> for Sized? {
     /// v.swap(1, 3);
     /// assert!(v == ["a", "d", "c", "b"]);
     /// ```
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn swap(&mut self, a: uint, b: uint);
 
     /// Divides one `&mut` into two at an index.
@@ -1046,6 +500,8 @@ pub trait SliceExt<T> for Sized? {
     /// the index `mid` itself) and the second will contain all
     /// indices from `[mid, len)` (excluding the index `len` itself).
     ///
+    /// # Panics
+    ///
     /// Panics if `mid > len`.
     ///
     /// # Example
@@ -1072,7 +528,7 @@ pub trait SliceExt<T> for Sized? {
     ///     assert!(right == []);
     /// }
     /// ```
-    #[unstable = "waiting on final error conventions"]
+    #[stable]
     fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]);
 
     /// Reverse the order of elements in a slice, in place.
@@ -1084,12 +540,18 @@ pub trait SliceExt<T> for Sized? {
     /// v.reverse();
     /// assert!(v == [3i, 2, 1]);
     /// ```
-    #[experimental = "may be moved to iterators instead"]
+    #[stable]
     fn reverse(&mut self);
 
     /// Returns an unsafe mutable pointer to the element in index
-    #[experimental = "waiting on unsafe conventions"]
-    unsafe fn unsafe_mut(&mut self, index: uint) -> &mut T;
+    #[stable]
+    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T;
+
+    /// Deprecated: renamed to `get_unchecked_mut`.
+    #[deprecated = "renamed to get_unchecked_mut"]
+    unsafe fn unchecked_mut(&mut self, index: uint) -> &mut T {
+        self.get_unchecked_mut(index)
+    }
 
     /// Return an unsafe mutable pointer to the slice's buffer.
     ///
@@ -1099,10 +561,11 @@ pub trait SliceExt<T> for Sized? {
     /// Modifying the slice may cause its buffer to be reallocated, which
     /// would also make any pointers to it invalid.
     #[inline]
-    #[unstable]
+    #[stable]
     fn as_mut_ptr(&mut self) -> *mut T;
 }
 
+#[unstable = "trait is unstable"]
 impl<T> SliceExt<T> for [T] {
     #[inline]
     fn sort_by<F>(&mut self, compare: F) where F: FnMut(&T, &T) -> Ordering {
@@ -1111,7 +574,7 @@ impl<T> SliceExt<T> for [T] {
 
     #[inline]
     fn move_from(&mut self, mut src: Vec<T>, start: uint, end: uint) -> uint {
-        for (a, b) in self.iter_mut().zip(src[mut start..end].iter_mut()) {
+        for (a, b) in self.iter_mut().zip(src.slice_mut(start, end).iter_mut()) {
             mem::swap(a, b);
         }
         cmp::min(self.len(), end-start)
@@ -1143,19 +606,19 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn split<F>(&self, pred: F) -> Splits<T, F>
+    fn split<F>(&self, pred: F) -> Split<T, F>
                 where F: FnMut(&T) -> bool {
         core_slice::SliceExt::split(self, pred)
     }
 
     #[inline]
-    fn splitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    fn splitn<F>(&self, n: uint, pred: F) -> SplitN<T, F>
                  where F: FnMut(&T) -> bool {
         core_slice::SliceExt::splitn(self, n, pred)
     }
 
     #[inline]
-    fn rsplitn<F>(&self, n: uint, pred: F) -> SplitsN<Splits<T, F>>
+    fn rsplitn<F>(&self, n: uint, pred: F) -> RSplitN<T, F>
                   where F: FnMut(&T) -> bool {
         core_slice::SliceExt::rsplitn(self, n, pred)
     }
@@ -1176,8 +639,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head<'a>(&'a self) -> Option<&'a T> {
-        core_slice::SliceExt::head(self)
+    fn first<'a>(&'a self) -> Option<&'a T> {
+        core_slice::SliceExt::first(self)
     }
 
     #[inline]
@@ -1196,8 +659,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_get<'a>(&'a self, index: uint) -> &'a T {
-        core_slice::SliceExt::unsafe_get(self, index)
+    unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T {
+        core_slice::SliceExt::get_unchecked(self, index)
     }
 
     #[inline]
@@ -1206,9 +669,9 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn binary_search<F>(&self, f: F) -> BinarySearchResult
+    fn binary_search_by<F>(&self, f: F) -> Result<uint, uint>
                         where F: FnMut(&T) -> Ordering {
-        core_slice::SliceExt::binary_search(self, f)
+        core_slice::SliceExt::binary_search_by(self, f)
     }
 
     #[inline]
@@ -1252,8 +715,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head_mut<'a>(&'a mut self) -> Option<&'a mut T> {
-        core_slice::SliceExt::head_mut(self)
+    fn first_mut<'a>(&'a mut self) -> Option<&'a mut T> {
+        core_slice::SliceExt::first_mut(self)
     }
 
     #[inline]
@@ -1272,25 +735,25 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn split_mut<F>(&mut self, pred: F) -> MutSplits<T, F>
+    fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F>
                     where F: FnMut(&T) -> bool {
         core_slice::SliceExt::split_mut(self, pred)
     }
 
     #[inline]
-    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    fn splitn_mut<F>(&mut self, n: uint, pred: F) -> SplitNMut<T, F>
                      where F: FnMut(&T) -> bool {
         core_slice::SliceExt::splitn_mut(self, n, pred)
     }
 
     #[inline]
-    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> SplitsN<MutSplits<T, F>>
+    fn rsplitn_mut<F>(&mut self,  n: uint, pred: F) -> RSplitNMut<T, F>
                       where F: FnMut(&T) -> bool {
         core_slice::SliceExt::rsplitn_mut(self, n, pred)
     }
 
     #[inline]
-    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> MutChunks<'a, T> {
+    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T> {
         core_slice::SliceExt::chunks_mut(self, chunk_size)
     }
 
@@ -1310,8 +773,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
-        core_slice::SliceExt::unsafe_mut(self, index)
+    unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
+        core_slice::SliceExt::get_unchecked_mut(self, index)
     }
 
     #[inline]
@@ -1320,6 +783,311 @@ impl<T> SliceExt<T> for [T] {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Extension traits for slices over specifc kinds of data
+////////////////////////////////////////////////////////////////////////////////
+
+/// Extension methods for boxed slices.
+#[experimental = "likely to merge into SliceExt if it survives"]
+pub trait BoxedSliceExt<T> {
+    /// Convert `self` into a vector without clones or allocation.
+    #[experimental]
+    fn into_vec(self) -> Vec<T>;
+}
+
+#[experimental = "trait is experimental"]
+impl<T> BoxedSliceExt<T> for Box<[T]> {
+    fn into_vec(mut self) -> Vec<T> {
+        unsafe {
+            let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
+            mem::forget(self);
+            xs
+        }
+    }
+}
+
+/// Allocating extension methods for slices containing `Clone` elements.
+#[unstable = "likely to be merged into SliceExt"]
+pub trait CloneSliceExt<T> for Sized? {
+    /// Copies `self` into a new `Vec`.
+    #[stable]
+    fn to_vec(&self) -> Vec<T>;
+
+    /// Deprecated: use `iter().cloned().partition(f)` instead.
+    #[deprecated = "use iter().cloned().partition(f) instead"]
+    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool;
+
+    /// Creates an iterator that yields every possible permutation of the
+    /// vector in succession.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let v = [1i, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// for p in perms {
+    ///   println!("{}", p);
+    /// }
+    /// ```
+    ///
+    /// Iterating through permutations one by one.
+    ///
+    /// ```rust
+    /// let v = [1i, 2, 3];
+    /// let mut perms = v.permutations();
+    ///
+    /// assert_eq!(Some(vec![1i, 2, 3]), perms.next());
+    /// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
+    /// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
+    /// ```
+    #[unstable]
+    fn permutations(&self) -> Permutations<T>;
+
+    /// Copies as many elements from `src` as it can into `self` (the
+    /// shorter of `self.len()` and `src.len()`). Returns the number
+    /// of elements copied.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let mut dst = [0i, 0, 0];
+    /// let src = [1i, 2];
+    ///
+    /// assert!(dst.clone_from_slice(&src) == 2);
+    /// assert!(dst == [1, 2, 0]);
+    ///
+    /// let src2 = [3i, 4, 5, 6];
+    /// assert!(dst.clone_from_slice(&src2) == 3);
+    /// assert!(dst == [3i, 4, 5]);
+    /// ```
+    #[experimental]
+    fn clone_from_slice(&mut self, &[T]) -> uint;
+}
+
+
+#[unstable = "trait is unstable"]
+impl<T: Clone> CloneSliceExt<T> for [T] {
+    /// Returns a copy of `v`.
+    #[inline]
+    fn to_vec(&self) -> Vec<T> {
+        let mut vector = Vec::with_capacity(self.len());
+        vector.push_all(self);
+        vector
+    }
+
+
+    #[inline]
+    fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
+        self.iter().cloned().partition(f)
+    }
+
+    /// Returns an iterator over all permutations of a vector.
+    fn permutations(&self) -> Permutations<T> {
+        Permutations{
+            swaps: ElementSwaps::new(self.len()),
+            v: self.to_vec(),
+        }
+    }
+
+    fn clone_from_slice(&mut self, src: &[T]) -> uint {
+        core_slice::CloneSliceExt::clone_from_slice(self, src)
+    }
+}
+
+/// Allocating extension methods for slices on Ord values.
+#[unstable = "likely to merge with SliceExt"]
+pub trait OrdSliceExt<T> for Sized? {
+    /// Sorts the slice, in place.
+    ///
+    /// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut v = [-5i, 4, 1, -3, 2];
+    ///
+    /// v.sort();
+    /// assert!(v == [-5i, -3, 1, 2, 4]);
+    /// ```
+    #[stable]
+    fn sort(&mut self);
+
+    /// Binary search a sorted slice for a given element.
+    ///
+    /// If the value is found then `Ok` is returned, containing the
+    /// index of the matching element; if the value is not found then
+    /// `Err` is returned, containing the index where a matching
+    /// element could be inserted while maintaining sorted order.
+    ///
+    /// # Example
+    ///
+    /// Looks up a series of four elements. The first is found, with a
+    /// uniquely determined position; the second and third are not
+    /// found; the fourth could match any position in `[1,4]`.
+    ///
+    /// ```rust
+    /// let s = [0i, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+    /// let s = s.as_slice();
+    ///
+    /// assert_eq!(s.binary_search(&13),  Ok(9));
+    /// assert_eq!(s.binary_search(&4),   Err(7));
+    /// assert_eq!(s.binary_search(&100), Err(13));
+    /// let r = s.binary_search(&1);
+    /// assert!(match r { Ok(1...4) => true, _ => false, });
+    /// ```
+    #[stable]
+    fn binary_search(&self, x: &T) -> Result<uint, uint>;
+
+    /// Deprecated: use `binary_search` instead.
+    #[deprecated = "use binary_search instead"]
+    fn binary_search_elem(&self, x: &T) -> Result<uint, uint> {
+        self.binary_search(x)
+    }
+
+    /// Mutates the slice to the next lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// last-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [0i, 1, 2];
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [1i, 0, 2];
+    /// assert!(v == b);
+    /// ```
+    #[unstable = "uncertain if this merits inclusion in std"]
+    fn next_permutation(&mut self) -> bool;
+
+    /// Mutates the slice to the previous lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// first-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [1i, 0, 2];
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 1, 2];
+    /// assert!(v == b);
+    /// ```
+    #[unstable = "uncertain if this merits inclusion in std"]
+    fn prev_permutation(&mut self) -> bool;
+}
+
+#[unstable = "trait is unstable"]
+impl<T: Ord> OrdSliceExt<T> for [T] {
+    #[inline]
+    fn sort(&mut self) {
+        self.sort_by(|a, b| a.cmp(b))
+    }
+
+    fn binary_search(&self, x: &T) -> Result<uint, uint> {
+        core_slice::OrdSliceExt::binary_search(self, x)
+    }
+
+    fn next_permutation(&mut self) -> bool {
+        core_slice::OrdSliceExt::next_permutation(self)
+    }
+
+    fn prev_permutation(&mut self) -> bool {
+        core_slice::OrdSliceExt::prev_permutation(self)
+    }
+}
+
+#[unstable = "U should be an associated type"]
+/// An extension trait for concatenating slices
+pub trait SliceConcatExt<Sized? T, U> for Sized? {
+    /// Flattens a slice of `T` into a single value `U`.
+    #[stable]
+    fn concat(&self) -> U;
+
+    #[deprecated = "renamed to concat"]
+    fn concat_vec(&self) -> U {
+        self.concat()
+    }
+
+    /// Flattens a slice of `T` into a single value `U`, placing a
+    /// given seperator between each.
+    #[stable]
+    fn connect(&self, sep: &T) -> U;
+
+    #[deprecated = "renamed to connect"]
+    fn connect_vec(&self, sep: &T) -> U {
+        self.connect(sep)
+    }
+}
+
+impl<T: Clone, V: AsSlice<T>> SliceConcatExt<T, Vec<T>> for [V] {
+    fn concat(&self) -> Vec<T> {
+        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
+        let mut result = Vec::with_capacity(size);
+        for v in self.iter() {
+            result.push_all(v.as_slice())
+        }
+        result
+    }
+
+    fn connect(&self, sep: &T) -> Vec<T> {
+        let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
+        let mut result = Vec::with_capacity(size + self.len());
+        let mut first = true;
+        for v in self.iter() {
+            if first { first = false } else { result.push(sep.clone()) }
+            result.push_all(v.as_slice())
+        }
+        result
+    }
+}
+
+/// An iterator that yields the element swaps needed to produce
+/// a sequence of all possible permutations for an indexed sequence of
+/// elements. Each permutation is only a single swap apart.
+///
+/// The Steinhaus-Johnson-Trotter algorithm is used.
+///
+/// Generates even and odd permutations alternately.
+///
+/// The last generated swap is always (0, 1), and it returns the
+/// sequence to its initial order.
+#[experimental]
+#[deriving(Clone)]
+pub struct ElementSwaps {
+    sdir: Vec<SizeDirection>,
+    /// If `true`, emit the last swap that returns the sequence to initial
+    /// state.
+    emit_reset: bool,
+    swaps_made : uint,
+}
+
+impl ElementSwaps {
+    /// Creates an `ElementSwaps` iterator for a sequence of `length` elements.
+    #[experimental]
+    pub fn new(length: uint) -> ElementSwaps {
+        // Initialize `sdir` with a direction that position should move in
+        // (all negative at the beginning) and the `size` of the
+        // element (equal to the original index).
+        ElementSwaps{
+            emit_reset: true,
+            sdir: range(0, length).map(|i| SizeDirection{ size: i, dir: Neg }).collect(),
+            swaps_made: 0
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Standard trait implementations for slices
+////////////////////////////////////////////////////////////////////////////////
+
 #[unstable = "trait is unstable"]
 impl<T> BorrowFrom<Vec<T>> for [T] {
     fn borrow_from(owned: &Vec<T>) -> &[T] { owned[] }
@@ -1327,7 +1095,7 @@ impl<T> BorrowFrom<Vec<T>> for [T] {
 
 #[unstable = "trait is unstable"]
 impl<T> BorrowFromMut<Vec<T>> for [T] {
-    fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { owned[mut] }
+    fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { owned.as_mut_slice_() }
 }
 
 #[unstable = "trait is unstable"]
@@ -1335,7 +1103,316 @@ impl<T: Clone> ToOwned<Vec<T>> for [T] {
     fn to_owned(&self) -> Vec<T> { self.to_vec() }
 }
 
-/// Unsafe operations
+////////////////////////////////////////////////////////////////////////////////
+// Iterators
+////////////////////////////////////////////////////////////////////////////////
+
+#[deriving(Copy, Clone)]
+enum Direction { Pos, Neg }
+
+/// An `Index` and `Direction` together.
+#[deriving(Copy, Clone)]
+struct SizeDirection {
+    size: uint,
+    dir: Direction,
+}
+
+impl Iterator<(uint, uint)> for ElementSwaps {
+    #[inline]
+    fn next(&mut self) -> Option<(uint, uint)> {
+        fn new_pos(i: uint, s: Direction) -> uint {
+            i + match s { Pos => 1, Neg => -1 }
+        }
+
+        // Find the index of the largest mobile element:
+        // The direction should point into the vector, and the
+        // swap should be with a smaller `size` element.
+        let max = self.sdir.iter().map(|&x| x).enumerate()
+                           .filter(|&(i, sd)|
+                                new_pos(i, sd.dir) < self.sdir.len() &&
+                                self.sdir[new_pos(i, sd.dir)].size < sd.size)
+                           .max_by(|&(_, sd)| sd.size);
+        match max {
+            Some((i, sd)) => {
+                let j = new_pos(i, sd.dir);
+                self.sdir.swap(i, j);
+
+                // Swap the direction of each larger SizeDirection
+                for x in self.sdir.iter_mut() {
+                    if x.size > sd.size {
+                        x.dir = match x.dir { Pos => Neg, Neg => Pos };
+                    }
+                }
+                self.swaps_made += 1;
+                Some((i, j))
+            },
+            None => if self.emit_reset {
+                self.emit_reset = false;
+                if self.sdir.len() > 1 {
+                    // The last swap
+                    self.swaps_made += 1;
+                    Some((0, 1))
+                } else {
+                    // Vector is of the form [] or [x], and the only permutation is itself
+                    self.swaps_made += 1;
+                    Some((0,0))
+                }
+            } else { None }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        // For a vector of size n, there are exactly n! permutations.
+        let n = range(2, self.sdir.len() + 1).product();
+        (n - self.swaps_made, Some(n - self.swaps_made))
+    }
+}
+
+/// An iterator that uses `ElementSwaps` to iterate through
+/// all possible permutations of a vector.
+///
+/// The first iteration yields a clone of the vector as it is,
+/// then each successive element is the vector with one
+/// swap applied.
+///
+/// Generates even and odd permutations alternately.
+#[unstable]
+pub struct Permutations<T> {
+    swaps: ElementSwaps,
+    v: Vec<T>,
+}
+
+#[unstable = "trait is unstable"]
+impl<T: Clone> Iterator<Vec<T>> for Permutations<T> {
+    #[inline]
+    fn next(&mut self) -> Option<Vec<T>> {
+        match self.swaps.next() {
+            None => None,
+            Some((0,0)) => Some(self.v.clone()),
+            Some((a, b)) => {
+                let elt = self.v.clone();
+                self.v.swap(a, b);
+                Some(elt)
+            }
+        }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        self.swaps.size_hint()
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sorting
+////////////////////////////////////////////////////////////////////////////////
+
+fn insertion_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
+    let len = v.len() as int;
+    let buf_v = v.as_mut_ptr();
+
+    // 1 <= i < len;
+    for i in range(1, len) {
+        // j satisfies: 0 <= j <= i;
+        let mut j = i;
+        unsafe {
+            // `i` is in bounds.
+            let read_ptr = buf_v.offset(i) as *const T;
+
+            // find where to insert, we need to do strict <,
+            // rather than <=, to maintain stability.
+
+            // 0 <= j - 1 < len, so .offset(j - 1) is in bounds.
+            while j > 0 &&
+                    compare(&*read_ptr, &*buf_v.offset(j - 1)) == Less {
+                j -= 1;
+            }
+
+            // shift everything to the right, to make space to
+            // insert this value.
+
+            // j + 1 could be `len` (for the last `i`), but in
+            // that case, `i == j` so we don't copy. The
+            // `.offset(j)` is always in bounds.
+
+            if i != j {
+                let tmp = ptr::read(read_ptr);
+                ptr::copy_memory(buf_v.offset(j + 1),
+                                 &*buf_v.offset(j),
+                                 (i - j) as uint);
+                ptr::copy_nonoverlapping_memory(buf_v.offset(j),
+                                                &tmp as *const T,
+                                                1);
+                mem::forget(tmp);
+            }
+        }
+    }
+}
+
+fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Ordering {
+    // warning: this wildly uses unsafe.
+    static BASE_INSERTION: uint = 32;
+    static LARGE_INSERTION: uint = 16;
+
+    // FIXME #12092: smaller insertion runs seems to make sorting
+    // vectors of large elements a little faster on some platforms,
+    // but hasn't been tested/tuned extensively
+    let insertion = if size_of::<T>() <= 16 {
+        BASE_INSERTION
+    } else {
+        LARGE_INSERTION
+    };
+
+    let len = v.len();
+
+    // short vectors get sorted in-place via insertion sort to avoid allocations
+    if len <= insertion {
+        insertion_sort(v, compare);
+        return;
+    }
+
+    // allocate some memory to use as scratch memory, we keep the
+    // length 0 so we can keep shallow copies of the contents of `v`
+    // without risking the dtors running on an object twice if
+    // `compare` panics.
+    let mut working_space = Vec::with_capacity(2 * len);
+    // these both are buffers of length `len`.
+    let mut buf_dat = working_space.as_mut_ptr();
+    let mut buf_tmp = unsafe {buf_dat.offset(len as int)};
+
+    // length `len`.
+    let buf_v = v.as_ptr();
+
+    // step 1. sort short runs with insertion sort. This takes the
+    // values from `v` and sorts them into `buf_dat`, leaving that
+    // with sorted runs of length INSERTION.
+
+    // We could hardcode the sorting comparisons here, and we could
+    // manipulate/step the pointers themselves, rather than repeatedly
+    // .offset-ing.
+    for start in range_step(0, len, insertion) {
+        // start <= i < len;
+        for i in range(start, cmp::min(start + insertion, len)) {
+            // j satisfies: start <= j <= i;
+            let mut j = i as int;
+            unsafe {
+                // `i` is in bounds.
+                let read_ptr = buf_v.offset(i as int);
+
+                // find where to insert, we need to do strict <,
+                // rather than <=, to maintain stability.
+
+                // start <= j - 1 < len, so .offset(j - 1) is in
+                // bounds.
+                while j > start as int &&
+                        compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less {
+                    j -= 1;
+                }
+
+                // shift everything to the right, to make space to
+                // insert this value.
+
+                // j + 1 could be `len` (for the last `i`), but in
+                // that case, `i == j` so we don't copy. The
+                // `.offset(j)` is always in bounds.
+                ptr::copy_memory(buf_dat.offset(j + 1),
+                                 &*buf_dat.offset(j),
+                                 i - j as uint);
+                ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
+            }
+        }
+    }
+
+    // step 2. merge the sorted runs.
+    let mut width = insertion;
+    while width < len {
+        // merge the sorted runs of length `width` in `buf_dat` two at
+        // a time, placing the result in `buf_tmp`.
+
+        // 0 <= start <= len.
+        for start in range_step(0, len, 2 * width) {
+            // manipulate pointers directly for speed (rather than
+            // using a `for` loop with `range` and `.offset` inside
+            // that loop).
+            unsafe {
+                // the end of the first run & start of the
+                // second. Offset of `len` is defined, since this is
+                // precisely one byte past the end of the object.
+                let right_start = buf_dat.offset(cmp::min(start + width, len) as int);
+                // end of the second. Similar reasoning to the above re safety.
+                let right_end_idx = cmp::min(start + 2 * width, len);
+                let right_end = buf_dat.offset(right_end_idx as int);
+
+                // the pointers to the elements under consideration
+                // from the two runs.
+
+                // both of these are in bounds.
+                let mut left = buf_dat.offset(start as int);
+                let mut right = right_start;
+
+                // where we're putting the results, it is a run of
+                // length `2*width`, so we step it once for each step
+                // of either `left` or `right`.  `buf_tmp` has length
+                // `len`, so these are in bounds.
+                let mut out = buf_tmp.offset(start as int);
+                let out_end = buf_tmp.offset(right_end_idx as int);
+
+                while out < out_end {
+                    // Either the left or the right run are exhausted,
+                    // so just copy the remainder from the other run
+                    // and move on; this gives a huge speed-up (order
+                    // of 25%) for mostly sorted vectors (the best
+                    // case).
+                    if left == right_start {
+                        // the number remaining in this run.
+                        let elems = (right_end as uint - right as uint) / mem::size_of::<T>();
+                        ptr::copy_nonoverlapping_memory(out, &*right, elems);
+                        break;
+                    } else if right == right_end {
+                        let elems = (right_start as uint - left as uint) / mem::size_of::<T>();
+                        ptr::copy_nonoverlapping_memory(out, &*left, elems);
+                        break;
+                    }
+
+                    // check which side is smaller, and that's the
+                    // next element for the new run.
+
+                    // `left < right_start` and `right < right_end`,
+                    // so these are valid.
+                    let to_copy = if compare(&*left, &*right) == Greater {
+                        step(&mut right)
+                    } else {
+                        step(&mut left)
+                    };
+                    ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
+                    step(&mut out);
+                }
+            }
+        }
+
+        mem::swap(&mut buf_dat, &mut buf_tmp);
+
+        width *= 2;
+    }
+
+    // write the result to `v` in one go, so that there are never two copies
+    // of the same object in `v`.
+    unsafe {
+        ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
+    }
+
+    // increment the pointer, returning the old pointer.
+    #[inline(always)]
+    unsafe fn step<T>(ptr: &mut *mut T) -> *mut T {
+        let old = *ptr;
+        *ptr = ptr.offset(1);
+        old
+    }
+}
+
+/// Deprecated, unsafe operations
+#[deprecated]
 pub mod raw {
     pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};
     pub use core::slice::raw::{shift_ptr, pop_ptr};
@@ -1344,11 +1421,14 @@ pub mod raw {
 #[cfg(test)]
 mod tests {
     use std::boxed::Box;
-    use prelude::*;
+    use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal};
+    use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt};
+    use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice};
+    use prelude::{RandomAccessIterator, Ord, SliceConcatExt};
     use core::cell::Cell;
     use core::default::Default;
     use core::mem;
-    use std::rand::{Rng, task_rng};
+    use std::rand::{Rng, thread_rng};
     use std::rc::Rc;
     use super::ElementSwaps;
 
@@ -1407,14 +1487,14 @@ mod tests {
 
     #[test]
     fn test_is_empty() {
-        let xs: [int, ..0] = [];
+        let xs: [int; 0] = [];
         assert!(xs.is_empty());
         assert!(![0i].is_empty());
     }
 
     #[test]
     fn test_len_divzero() {
-        type Z = [i8, ..0];
+        type Z = [i8; 0];
         let v0 : &[Z] = &[];
         let v1 : &[Z] = &[[]];
         let v2 : &[Z] = &[[], []];
@@ -1610,15 +1690,19 @@ mod tests {
     fn test_swap_remove() {
         let mut v = vec![1i, 2, 3, 4, 5];
         let mut e = v.swap_remove(0);
-        assert_eq!(e, Some(1));
+        assert_eq!(e, 1);
         assert_eq!(v, vec![5i, 2, 3, 4]);
         e = v.swap_remove(3);
-        assert_eq!(e, Some(4));
+        assert_eq!(e, 4);
         assert_eq!(v, vec![5i, 2, 3]);
+    }
 
-        e = v.swap_remove(3);
-        assert_eq!(e, None);
-        assert_eq!(v, vec![5i, 2, 3]);
+    #[test]
+    #[should_fail]
+    fn test_swap_remove_fail() {
+        let mut v = vec![1i];
+        let _ = v.swap_remove(0);
+        let _ = v.swap_remove(0);
     }
 
     #[test]
@@ -1777,7 +1861,7 @@ mod tests {
     #[test]
     fn test_permutations() {
         {
-            let v: [int, ..0] = [];
+            let v: [int; 0] = [];
             let mut it = v.permutations();
             let (min_size, max_opt) = it.size_hint();
             assert_eq!(min_size, 1);
@@ -1902,48 +1986,48 @@ mod tests {
     }
 
     #[test]
-    fn test_binary_search_elem() {
-        assert_eq!([1i,2,3,4,5].binary_search_elem(&5).found(), Some(4));
-        assert_eq!([1i,2,3,4,5].binary_search_elem(&4).found(), Some(3));
-        assert_eq!([1i,2,3,4,5].binary_search_elem(&3).found(), Some(2));
-        assert_eq!([1i,2,3,4,5].binary_search_elem(&2).found(), Some(1));
-        assert_eq!([1i,2,3,4,5].binary_search_elem(&1).found(), Some(0));
+    fn test_binary_search() {
+        assert_eq!([1i,2,3,4,5].binary_search(&5).ok(), Some(4));
+        assert_eq!([1i,2,3,4,5].binary_search(&4).ok(), Some(3));
+        assert_eq!([1i,2,3,4,5].binary_search(&3).ok(), Some(2));
+        assert_eq!([1i,2,3,4,5].binary_search(&2).ok(), Some(1));
+        assert_eq!([1i,2,3,4,5].binary_search(&1).ok(), Some(0));
 
-        assert_eq!([2i,4,6,8,10].binary_search_elem(&1).found(), None);
-        assert_eq!([2i,4,6,8,10].binary_search_elem(&5).found(), None);
-        assert_eq!([2i,4,6,8,10].binary_search_elem(&4).found(), Some(1));
-        assert_eq!([2i,4,6,8,10].binary_search_elem(&10).found(), Some(4));
+        assert_eq!([2i,4,6,8,10].binary_search(&1).ok(), None);
+        assert_eq!([2i,4,6,8,10].binary_search(&5).ok(), None);
+        assert_eq!([2i,4,6,8,10].binary_search(&4).ok(), Some(1));
+        assert_eq!([2i,4,6,8,10].binary_search(&10).ok(), Some(4));
 
-        assert_eq!([2i,4,6,8].binary_search_elem(&1).found(), None);
-        assert_eq!([2i,4,6,8].binary_search_elem(&5).found(), None);
-        assert_eq!([2i,4,6,8].binary_search_elem(&4).found(), Some(1));
-        assert_eq!([2i,4,6,8].binary_search_elem(&8).found(), Some(3));
+        assert_eq!([2i,4,6,8].binary_search(&1).ok(), None);
+        assert_eq!([2i,4,6,8].binary_search(&5).ok(), None);
+        assert_eq!([2i,4,6,8].binary_search(&4).ok(), Some(1));
+        assert_eq!([2i,4,6,8].binary_search(&8).ok(), Some(3));
 
-        assert_eq!([2i,4,6].binary_search_elem(&1).found(), None);
-        assert_eq!([2i,4,6].binary_search_elem(&5).found(), None);
-        assert_eq!([2i,4,6].binary_search_elem(&4).found(), Some(1));
-        assert_eq!([2i,4,6].binary_search_elem(&6).found(), Some(2));
+        assert_eq!([2i,4,6].binary_search(&1).ok(), None);
+        assert_eq!([2i,4,6].binary_search(&5).ok(), None);
+        assert_eq!([2i,4,6].binary_search(&4).ok(), Some(1));
+        assert_eq!([2i,4,6].binary_search(&6).ok(), Some(2));
 
-        assert_eq!([2i,4].binary_search_elem(&1).found(), None);
-        assert_eq!([2i,4].binary_search_elem(&5).found(), None);
-        assert_eq!([2i,4].binary_search_elem(&2).found(), Some(0));
-        assert_eq!([2i,4].binary_search_elem(&4).found(), Some(1));
+        assert_eq!([2i,4].binary_search(&1).ok(), None);
+        assert_eq!([2i,4].binary_search(&5).ok(), None);
+        assert_eq!([2i,4].binary_search(&2).ok(), Some(0));
+        assert_eq!([2i,4].binary_search(&4).ok(), Some(1));
 
-        assert_eq!([2i].binary_search_elem(&1).found(), None);
-        assert_eq!([2i].binary_search_elem(&5).found(), None);
-        assert_eq!([2i].binary_search_elem(&2).found(), Some(0));
+        assert_eq!([2i].binary_search(&1).ok(), None);
+        assert_eq!([2i].binary_search(&5).ok(), None);
+        assert_eq!([2i].binary_search(&2).ok(), Some(0));
 
-        assert_eq!([].binary_search_elem(&1i).found(), None);
-        assert_eq!([].binary_search_elem(&5i).found(), None);
+        assert_eq!([].binary_search(&1i).ok(), None);
+        assert_eq!([].binary_search(&5i).ok(), None);
 
-        assert!([1i,1,1,1,1].binary_search_elem(&1).found() != None);
-        assert!([1i,1,1,1,2].binary_search_elem(&1).found() != None);
-        assert!([1i,1,1,2,2].binary_search_elem(&1).found() != None);
-        assert!([1i,1,2,2,2].binary_search_elem(&1).found() != None);
-        assert_eq!([1i,2,2,2,2].binary_search_elem(&1).found(), Some(0));
+        assert!([1i,1,1,1,1].binary_search(&1).ok() != None);
+        assert!([1i,1,1,1,2].binary_search(&1).ok() != None);
+        assert!([1i,1,1,2,2].binary_search(&1).ok() != None);
+        assert!([1i,1,2,2,2].binary_search(&1).ok() != None);
+        assert_eq!([1i,2,2,2,2].binary_search(&1).ok(), Some(0));
 
-        assert_eq!([1i,2,3,4,5].binary_search_elem(&6).found(), None);
-        assert_eq!([1i,2,3,4,5].binary_search_elem(&0).found(), None);
+        assert_eq!([1i,2,3,4,5].binary_search(&6).ok(), None);
+        assert_eq!([1i,2,3,4,5].binary_search(&0).ok(), None);
     }
 
     #[test]
@@ -1964,7 +2048,7 @@ mod tests {
     fn test_sort() {
         for len in range(4u, 25) {
             for _ in range(0i, 100) {
-                let mut v = task_rng().gen_iter::<uint>().take(len)
+                let mut v = thread_rng().gen_iter::<uint>().take(len)
                                       .collect::<Vec<uint>>();
                 let mut v1 = v.clone();
 
@@ -1980,7 +2064,7 @@ mod tests {
         }
 
         // shouldn't panic
-        let mut v: [uint, .. 0] = [];
+        let mut v: [uint; 0] = [];
         v.sort();
 
         let mut v = [0xDEADBEEFu];
@@ -1992,7 +2076,7 @@ mod tests {
     fn test_sort_stability() {
         for len in range(4i, 25) {
             for _ in range(0u, 10) {
-                let mut counts = [0i, .. 10];
+                let mut counts = [0i; 10];
 
                 // create a vector like [(6, 1), (5, 1), (6, 2), ...],
                 // where the first item of each tuple is random, but
@@ -2000,7 +2084,7 @@ mod tests {
                 // number this element is, i.e. the second elements
                 // will occur in sorted order.
                 let mut v = range(0, len).map(|_| {
-                        let n = task_rng().gen::<uint>() % 10;
+                        let n = thread_rng().gen::<uint>() % 10;
                         counts[n] += 1;
                         (n, counts[n])
                     }).collect::<Vec<(uint, int)>>();
@@ -2037,26 +2121,28 @@ mod tests {
 
     #[test]
     fn test_concat() {
-        let v: [Vec<int>, ..0] = [];
-        assert_eq!(v.concat_vec(), vec![]);
-        assert_eq!([vec![1i], vec![2i,3i]].concat_vec(), vec![1, 2, 3]);
+        let v: [Vec<int>; 0] = [];
+        let c: Vec<int> = v.concat();
+        assert_eq!(c, []);
+        let d: Vec<int> = [vec![1i], vec![2i,3i]].concat();
+        assert_eq!(d, vec![1i, 2, 3]);
 
-        let v: [&[int], ..2] = [&[1], &[2, 3]];
-        assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 3]);
-        let v: [&[int], ..3] = [&[1], &[2], &[3]];
-        assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 0, 3]);
+        let v: [&[int]; 2] = [&[1], &[2, 3]];
+        assert_eq!(v.connect(&0), vec![1i, 0, 2, 3]);
+        let v: [&[int]; 3] = [&[1i], &[2], &[3]];
+        assert_eq!(v.connect(&0), vec![1i, 0, 2, 0, 3]);
     }
 
     #[test]
     fn test_connect() {
-        let v: [Vec<int>, ..0] = [];
+        let v: [Vec<int>; 0] = [];
         assert_eq!(v.connect_vec(&0), vec![]);
         assert_eq!([vec![1i], vec![2i, 3]].connect_vec(&0), vec![1, 0, 2, 3]);
         assert_eq!([vec![1i], vec![2i], vec![3i]].connect_vec(&0), vec![1, 0, 2, 0, 3]);
 
-        let v: [&[int], ..2] = [&[1], &[2, 3]];
+        let v: [&[int]; 2] = [&[1], &[2, 3]];
         assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 3]);
-        let v: [&[int], ..3] = [&[1], &[2], &[3]];
+        let v: [&[int]; 3] = [&[1], &[2], &[3]];
         assert_eq!(v.connect_vec(&0), vec![1, 0, 2, 0, 3]);
     }
 
@@ -2090,23 +2176,25 @@ mod tests {
     fn test_remove() {
         let mut a = vec![1i,2,3,4];
 
-        assert_eq!(a.remove(2), Some(3));
+        assert_eq!(a.remove(2), 3);
         assert_eq!(a, vec![1i,2,4]);
 
-        assert_eq!(a.remove(2), Some(4));
-        assert_eq!(a, vec![1i,2]);
-
-        assert_eq!(a.remove(2), None);
+        assert_eq!(a.remove(2), 4);
         assert_eq!(a, vec![1i,2]);
 
-        assert_eq!(a.remove(0), Some(1));
+        assert_eq!(a.remove(0), 1);
         assert_eq!(a, vec![2i]);
 
-        assert_eq!(a.remove(0), Some(2));
+        assert_eq!(a.remove(0), 2);
         assert_eq!(a, vec![]);
+    }
 
-        assert_eq!(a.remove(0), None);
-        assert_eq!(a.remove(10), None);
+    #[test]
+    #[should_fail]
+    fn test_remove_fail() {
+        let mut a = vec![1i];
+        let _ = a.remove(0);
+        let _ = a.remove(0);
     }
 
     #[test]
@@ -2492,14 +2580,14 @@ mod tests {
         assert!(a == [7i,2,3,4]);
         let mut a = [1i,2,3,4,5];
         let b = vec![5i,6,7,8,9,0];
-        assert_eq!(a[mut 2..4].move_from(b,1,6), 2);
+        assert_eq!(a.slice_mut(2, 4).move_from(b,1,6), 2);
         assert!(a == [1i,2,6,7,5]);
     }
 
     #[test]
     fn test_reverse_part() {
         let mut values = [1i,2,3,4,5];
-        values[mut 1..4].reverse();
+        values.slice_mut(1, 4).reverse();
         assert!(values == [1,4,3,2,5]);
     }
 
@@ -2546,9 +2634,9 @@ mod tests {
     fn test_bytes_set_memory() {
         use slice::bytes::MutableByteVector;
         let mut values = [1u8,2,3,4,5];
-        values[mut 0..5].set_memory(0xAB);
+        values.slice_mut(0, 5).set_memory(0xAB);
         assert!(values == [0xAB, 0xAB, 0xAB, 0xAB, 0xAB]);
-        values[mut 2..4].set_memory(0xFF);
+        values.slice_mut(2, 4).set_memory(0xFF);
         assert!(values == [0xAB, 0xAB, 0xFF, 0xFF, 0xAB]);
     }
 
@@ -2627,7 +2715,7 @@ mod tests {
         }
         assert_eq!(cnt, 11);
 
-        let xs: [Foo, ..3] = [Foo, Foo, Foo];
+        let xs: [Foo; 3] = [Foo, Foo, Foo];
         cnt = 0;
         for f in xs.iter() {
             assert!(*f == Foo);
@@ -2802,7 +2890,7 @@ mod bench {
         let xss: Vec<Vec<uint>> =
             Vec::from_fn(100, |i| range(0u, i).collect());
         b.iter(|| {
-            xss.as_slice().concat_vec()
+            xss.as_slice().concat();
         });
     }
 
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index bccd2a1198a..129ba77d9f7 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -77,87 +77,62 @@ use slice::SliceExt;
 use string::String;
 use unicode;
 use vec::Vec;
+use slice::SliceConcatExt;
 
 pub use core::str::{from_utf8, CharEq, Chars, CharIndices};
 pub use core::str::{Bytes, CharSplits, is_utf8};
-pub use core::str::{CharSplitsN, Lines, LinesAny, MatchIndices, StrSplits};
+pub use core::str::{CharSplitsN, Lines, LinesAny, MatchIndices, StrSplits, SplitStr};
 pub use core::str::{CharRange};
 pub use core::str::{FromStr, from_str, Utf8Error};
 pub use core::str::Str;
 pub use core::str::{from_utf8_unchecked, from_c_str};
 pub use unicode::str::{Words, Graphemes, GraphemeIndices};
-
-// FIXME(conventions): ensure bit/char conventions are followed by str's API
+pub use core::str::{Split, SplitTerminator};
+pub use core::str::{SplitN, RSplitN};
 
 /*
 Section: Creating a string
 */
 
-/// Methods for vectors of strings.
-#[unstable = "functionality may be replaced with iterators"]
-pub trait StrVector for Sized? {
-    /// Concatenates a vector of strings.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let first = "Restaurant at the End of the".to_string();
-    /// let second = " Universe".to_string();
-    /// let string_vec = vec![first, second];
-    /// assert_eq!(string_vec.concat(), "Restaurant at the End of the Universe".to_string());
-    /// ```
-    fn concat(&self) -> String;
-
-    /// Concatenates a vector of strings, placing a given separator between each.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// let first = "Roast".to_string();
-    /// let second = "Sirloin Steak".to_string();
-    /// let string_vec = vec![first, second];
-    /// assert_eq!(string_vec.connect(", "), "Roast, Sirloin Steak".to_string());
-    /// ```
-    fn connect(&self, sep: &str) -> String;
-}
-
-#[allow(deprecated)]
-impl<S: Str> StrVector for [S] {
+impl<S: Str> SliceConcatExt<str, String> for [S] {
     fn concat(&self) -> String {
-        if self.is_empty() {
+        let s = self.as_slice();
+
+        if s.is_empty() {
             return String::new();
         }
 
         // `len` calculation may overflow but push_str will check boundaries
-        let len = self.iter().map(|s| s.as_slice().len()).sum();
-
+        let len = s.iter().map(|s| s.as_slice().len()).sum();
         let mut result = String::with_capacity(len);
 
-        for s in self.iter() {
-            result.push_str(s.as_slice());
+        for s in s.iter() {
+            result.push_str(s.as_slice())
         }
 
         result
     }
 
     fn connect(&self, sep: &str) -> String {
-        if self.is_empty() {
+        let s = self.as_slice();
+
+        if s.is_empty() {
             return String::new();
         }
 
         // concat is faster
         if sep.is_empty() {
-            return self.concat();
+            return s.concat();
         }
 
         // this is wrong without the guarantee that `self` is non-empty
         // `len` calculation may overflow but push_str but will check boundaries
-        let len = sep.len() * (self.len() - 1)
-            + self.iter().map(|s| s.as_slice().len()).sum();
+        let len = sep.len() * (s.len() - 1)
+            + s.iter().map(|s| s.as_slice().len()).sum();
         let mut result = String::with_capacity(len);
         let mut first = true;
 
-        for s in self.iter() {
+        for s in s.iter() {
             if first {
                 first = false;
             } else {
@@ -169,18 +144,6 @@ impl<S: Str> StrVector for [S] {
     }
 }
 
-impl<S: Str, T: AsSlice<S>> StrVector for T {
-    #[inline]
-    fn concat(&self) -> String {
-        self.as_slice().concat()
-    }
-
-    #[inline]
-    fn connect(&self, sep: &str) -> String {
-        self.as_slice().connect(sep)
-    }
-}
-
 /*
 Section: Iterators
 */
@@ -221,7 +184,7 @@ pub struct Decompositions<'a> {
 impl<'a> Iterator<char> for Decompositions<'a> {
     #[inline]
     fn next(&mut self) -> Option<char> {
-        match self.buffer.head() {
+        match self.buffer.first() {
             Some(&(c, 0)) => {
                 self.sorted = false;
                 self.buffer.remove(0);
@@ -239,7 +202,7 @@ impl<'a> Iterator<char> for Decompositions<'a> {
                 let buffer = &mut self.buffer;
                 let sorted = &mut self.sorted;
                 {
-                    let callback = |d| {
+                    let callback = |&mut: d| {
                         let class =
                             unicode::char::canonical_combining_class(d);
                         if class == 0 && !*sorted {
@@ -268,13 +231,16 @@ impl<'a> Iterator<char> for Decompositions<'a> {
             self.sorted = true;
         }
 
-        match self.buffer.remove(0) {
-            Some((c, 0)) => {
-                self.sorted = false;
-                Some(c)
+        if self.buffer.is_empty() {
+            None
+        } else {
+            match self.buffer.remove(0) {
+                (c, 0) => {
+                    self.sorted = false;
+                    Some(c)
+                }
+                (c, _) => Some(c),
             }
-            Some((c, _)) => Some(c),
-            None => None
         }
     }
 
@@ -721,7 +687,7 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// // not found, so no change.
     /// assert_eq!(s.replace("cookie monster", "little lamb"), s);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
+    #[stable]
     fn replace(&self, from: &str, to: &str) -> String {
         let mut result = String::new();
         let mut last_end = 0;
@@ -747,7 +713,7 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
         if me.is_empty() { return t.chars().count(); }
         if t.is_empty() { return me.chars().count(); }
 
-        let mut dcol = Vec::from_fn(t.len() + 1, |x| x);
+        let mut dcol: Vec<_> = range(0, t.len() + 1).collect();
         let mut t_last = 0;
 
         for (i, sc) in me.chars().enumerate() {
@@ -828,36 +794,36 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
         }
     }
 
-    /// Returns true if one string contains another
+    /// Returns true if a string contains a string pattern.
     ///
     /// # Arguments
     ///
-    /// - needle - The string to look for
+    /// - pat - The string pattern to look for
     ///
     /// # Example
     ///
     /// ```rust
     /// assert!("bananas".contains("nana"));
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn contains(&self, needle: &str) -> bool {
-        core_str::StrExt::contains(self[], needle)
+    #[stable]
+    fn contains(&self, pat: &str) -> bool {
+        core_str::StrExt::contains(self[], pat)
     }
 
-    /// Returns true if a string contains a char.
+    /// Returns true if a string contains a char pattern.
     ///
     /// # Arguments
     ///
-    /// - needle - The char to look for
+    /// - pat - The char pattern to look for
     ///
     /// # Example
     ///
     /// ```rust
     /// assert!("hello".contains_char('e'));
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn contains_char(&self, needle: char) -> bool {
-        core_str::StrExt::contains_char(self[], needle)
+    #[unstable = "might get removed in favour of a more generic contains()"]
+    fn contains_char<P: CharEq>(&self, pat: P) -> bool {
+        core_str::StrExt::contains_char(self[], pat)
     }
 
     /// An iterator over the characters of `self`. Note, this iterates
@@ -894,7 +860,7 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     }
 
     /// An iterator over substrings of `self`, separated by characters
-    /// matched by `sep`.
+    /// matched by the pattern `pat`.
     ///
     /// # Example
     ///
@@ -911,13 +877,13 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let v: Vec<&str> = "".split('X').collect();
     /// assert_eq!(v, vec![""]);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn split<Sep: CharEq>(&self, sep: Sep) -> CharSplits<Sep> {
-        core_str::StrExt::split(self[], sep)
+    #[stable]
+    fn split<P: CharEq>(&self, pat: P) -> Split<P> {
+        core_str::StrExt::split(self[], pat)
     }
 
     /// An iterator over substrings of `self`, separated by characters
-    /// matched by `sep`, restricted to splitting at most `count`
+    /// matched by the pattern `pat`, restricted to splitting at most `count`
     /// times.
     ///
     /// # Example
@@ -938,13 +904,13 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let v: Vec<&str> = "".splitn(1, 'X').collect();
     /// assert_eq!(v, vec![""]);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<Sep> {
-        core_str::StrExt::splitn(self[], count, sep)
+    #[stable]
+    fn splitn<P: CharEq>(&self, count: uint, pat: P) -> SplitN<P> {
+        core_str::StrExt::splitn(self[], count, pat)
     }
 
     /// An iterator over substrings of `self`, separated by characters
-    /// matched by `sep`.
+    /// matched by the pattern `pat`.
     ///
     /// Equivalent to `split`, except that the trailing substring
     /// is skipped if empty (terminator semantics).
@@ -967,13 +933,13 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect();
     /// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn split_terminator<Sep: CharEq>(&self, sep: Sep) -> CharSplits<Sep> {
-        core_str::StrExt::split_terminator(self[], sep)
+    #[unstable = "might get removed"]
+    fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
+        core_str::StrExt::split_terminator(self[], pat)
     }
 
     /// An iterator over substrings of `self`, separated by characters
-    /// matched by `sep`, starting from the end of the string.
+    /// matched by the pattern `pat`, starting from the end of the string.
     /// Restricted to splitting at most `count` times.
     ///
     /// # Example
@@ -988,13 +954,13 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
     /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<Sep> {
-        core_str::StrExt::rsplitn(self[], count, sep)
+    #[stable]
+    fn rsplitn<P: CharEq>(&self, count: uint, pat: P) -> RSplitN<P> {
+        core_str::StrExt::rsplitn(self[], count, pat)
     }
 
     /// An iterator over the start and end indices of the disjoint
-    /// matches of `sep` within `self`.
+    /// matches of the pattern `pat` within `self`.
     ///
     /// That is, each returned value `(start, end)` satisfies
     /// `self.slice(start, end) == sep`. For matches of `sep` within
@@ -1013,12 +979,12 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let v: Vec<(uint, uint)> = "ababa".match_indices("aba").collect();
     /// assert_eq!(v, vec![(0, 3)]); // only the first `aba`
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a> {
-        core_str::StrExt::match_indices(self[], sep)
+    #[unstable = "might have its iterator type changed"]
+    fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> {
+        core_str::StrExt::match_indices(self[], pat)
     }
 
-    /// An iterator over the substrings of `self` separated by `sep`.
+    /// An iterator over the substrings of `self` separated by the pattern `sep`.
     ///
     /// # Example
     ///
@@ -1029,9 +995,9 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
     /// assert_eq!(v, vec!["1", "", "2"]);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn split_str<'a>(&'a self, s: &'a str) -> StrSplits<'a> {
-        core_str::StrExt::split_str(self[], s)
+    #[unstable = "might get removed in the future in favor of a more generic split()"]
+    fn split_str<'a>(&'a self, pat: &'a str) -> StrSplits<'a> {
+        core_str::StrExt::split_str(self[], pat)
     }
 
     /// An iterator over the lines of a string (subsequences separated
@@ -1204,85 +1170,106 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
         core_str::StrExt::slice_unchecked(self[], begin, end)
     }
 
-    /// Returns true if `needle` is a prefix of the string.
+    /// Returns true if the pattern `pat` is a prefix of the string.
     ///
     /// # Example
     ///
     /// ```rust
     /// assert!("banana".starts_with("ba"));
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn starts_with(&self, needle: &str) -> bool {
-        core_str::StrExt::starts_with(self[], needle)
+    #[stable]
+    fn starts_with(&self, pat: &str) -> bool {
+        core_str::StrExt::starts_with(self[], pat)
     }
 
-    /// Returns true if `needle` is a suffix of the string.
+    /// Returns true if the pattern `pat` is a suffix of the string.
     ///
     /// # Example
     ///
     /// ```rust
     /// assert!("banana".ends_with("nana"));
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn ends_with(&self, needle: &str) -> bool {
-        core_str::StrExt::ends_with(self[], needle)
+    #[stable]
+    fn ends_with(&self, pat: &str) -> bool {
+        core_str::StrExt::ends_with(self[], pat)
     }
 
-    /// Returns a string with characters that match `to_trim` removed from the left and the right.
+    /// Returns a string with all pre- and suffixes that match
+    /// the pattern `pat` repeatedly removed.
     ///
     /// # Arguments
     ///
-    /// * to_trim - a character matcher
+    /// * pat - a string pattern
     ///
     /// # Example
     ///
     /// ```rust
-    /// assert_eq!("11foo1bar11".trim_chars('1'), "foo1bar");
+    /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_chars(x), "foo1bar");
-    /// assert_eq!("123foo1bar123".trim_chars(|&: c: char| c.is_numeric()), "foo1bar");
+    /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
+    /// assert_eq!("123foo1bar123".trim_matches(|&: c: char| c.is_numeric()), "foo1bar");
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn trim_chars<C: CharEq>(&self, to_trim: C) -> &str {
-        core_str::StrExt::trim_chars(self[], to_trim)
+    #[stable]
+    fn trim_matches<P: CharEq>(&self, pat: P) -> &str {
+        core_str::StrExt::trim_matches(self[], pat)
+    }
+
+    /// Deprecated
+    #[deprecated = "Replaced by `trim_matches`"]
+    fn trim_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str {
+        self.trim_matches(to_trim)
     }
 
-    /// Returns a string with leading `chars_to_trim` removed.
+    /// Returns a string with all prefixes that match
+    /// the pattern `pat` repeatedly removed.
     ///
     /// # Arguments
     ///
-    /// * to_trim - a character matcher
+    /// * pat - a string pattern
     ///
     /// # Example
     ///
     /// ```rust
-    /// assert_eq!("11foo1bar11".trim_left_chars('1'), "foo1bar11");
+    /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_left_chars(x), "foo1bar12");
-    /// assert_eq!("123foo1bar123".trim_left_chars(|&: c: char| c.is_numeric()), "foo1bar123");
+    /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
+    /// assert_eq!("123foo1bar123".trim_left_matches(|&: c: char| c.is_numeric()), "foo1bar123");
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn trim_left_chars<C: CharEq>(&self, to_trim: C) -> &str {
-        core_str::StrExt::trim_left_chars(self[], to_trim)
+    #[stable]
+    fn trim_left_matches<P: CharEq>(&self, pat: P) -> &str {
+        core_str::StrExt::trim_left_matches(self[], pat)
+    }
+
+    /// Deprecated
+    #[deprecated = "Replaced by `trim_left_matches`"]
+    fn trim_left_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str {
+        self.trim_left_matches(to_trim)
     }
 
-    /// Returns a string with trailing `chars_to_trim` removed.
+    /// Returns a string with all suffixes that match
+    /// the pattern `pat` repeatedly removed.
     ///
     /// # Arguments
     ///
-    /// * to_trim - a character matcher
+    /// * pat - a string pattern
     ///
     /// # Example
     ///
     /// ```rust
-    /// assert_eq!("11foo1bar11".trim_right_chars('1'), "11foo1bar");
+    /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
     /// let x: &[_] = &['1', '2'];
-    /// assert_eq!("12foo1bar12".trim_right_chars(x), "12foo1bar");
-    /// assert_eq!("123foo1bar123".trim_right_chars(|&: c: char| c.is_numeric()), "123foo1bar");
+    /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+    /// assert_eq!("123foo1bar123".trim_right_matches(|&: c: char| c.is_numeric()), "123foo1bar");
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn trim_right_chars<C: CharEq>(&self, to_trim: C) -> &str {
-        core_str::StrExt::trim_right_chars(self[], to_trim)
+    #[stable]
+    fn trim_right_matches<P: CharEq>(&self, pat: P) -> &str {
+        core_str::StrExt::trim_right_matches(self[], pat)
+    }
+
+    /// Deprecated
+    #[deprecated = "Replaced by `trim_right_matches`"]
+    fn trim_right_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str {
+        self.trim_right_matches(to_trim)
     }
 
     /// Check that `index`-th byte lies at the start and/or end of a
@@ -1430,7 +1417,7 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     }
 
     /// Returns the byte index of the first character of `self` that
-    /// matches `search`.
+    /// matches the pattern `pat`.
     ///
     /// # Return value
     ///
@@ -1452,13 +1439,13 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!(s.find(x), None);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn find<C: CharEq>(&self, search: C) -> Option<uint> {
-        core_str::StrExt::find(self[], search)
+    #[stable]
+    fn find<P: CharEq>(&self, pat: P) -> Option<uint> {
+        core_str::StrExt::find(self[], pat)
     }
 
     /// Returns the byte index of the last character of `self` that
-    /// matches `search`.
+    /// matches the pattern `pat`.
     ///
     /// # Return value
     ///
@@ -1480,9 +1467,9 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!(s.rfind(x), None);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
-    fn rfind<C: CharEq>(&self, search: C) -> Option<uint> {
-        core_str::StrExt::rfind(self[], search)
+    #[stable]
+    fn rfind<P: CharEq>(&self, pat: P) -> Option<uint> {
+        core_str::StrExt::rfind(self[], pat)
     }
 
     /// Returns the byte index of the first matching substring
@@ -1504,7 +1491,7 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// assert_eq!(s.find_str("老虎 L"), Some(6));
     /// assert_eq!(s.find_str("muffin man"), None);
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
+    #[unstable = "might get removed in favor of a more generic find in the future"]
     fn find_str(&self, needle: &str) -> Option<uint> {
         core_str::StrExt::find_str(self[], needle)
     }
@@ -1546,7 +1533,7 @@ pub trait StrExt for Sized?: ops::Slice<uint, str> {
     /// assert!(string.subslice_offset(lines[1]) == 2); // &"b"
     /// assert!(string.subslice_offset(lines[2]) == 4); // &"c"
     /// ```
-    #[unstable = "awaiting pattern/matcher stabilization"]
+    #[unstable = "awaiting convention about comparability of arbitrary slices"]
     fn subslice_offset(&self, inner: &str) -> uint {
         core_str::StrExt::subslice_offset(self[], inner)
     }
@@ -1745,26 +1732,13 @@ impl StrExt for str {}
 
 #[cfg(test)]
 mod tests {
-    use std::iter::AdditiveIterator;
-    use std::iter::range;
-    use std::default::Default;
-    use std::char::Char;
-    use std::clone::Clone;
-    use std::cmp::{Ord, PartialOrd, Equiv};
-    use std::cmp::Ordering::{Equal, Greater, Less};
-    use std::option::Option::{mod, Some, None};
-    use std::result::Result::{Ok, Err};
-    use std::ptr::RawPtr;
-    use std::iter::{Iterator, IteratorExt, DoubleEndedIteratorExt};
+    use prelude::*;
 
-    use super::*;
+    use core::default::Default;
+    use core::iter::AdditiveIterator;
+    use super::{from_utf8, is_utf8, raw};
     use super::MaybeOwned::{Owned, Slice};
-    use std::slice::{AsSlice, SliceExt};
-    use string::{String, ToString};
-    use vec::Vec;
-    use slice::CloneSliceExt;
-
-    use unicode::char::UnicodeChar;
+    use super::Utf8Error;
 
     #[test]
     fn test_le() {
@@ -1884,22 +1858,12 @@ mod tests {
         assert_eq!("ะเทศไท", "ประเทศไทย中华Việt Nam".slice_chars(2, 8));
     }
 
-    struct S {
-        x: [String, .. 2]
-    }
-
-    impl AsSlice<String> for S {
-        fn as_slice<'a> (&'a self) -> &'a [String] {
-            &self.x
-        }
-    }
-
     fn s(x: &str) -> String { x.into_string() }
 
     macro_rules! test_concat {
         ($expected: expr, $string: expr) => {
             {
-                let s = $string.concat();
+                let s: String = $string.concat();
                 assert_eq!($expected, s);
             }
         }
@@ -1907,22 +1871,10 @@ mod tests {
 
     #[test]
     fn test_concat_for_different_types() {
-        test_concat!("ab", ["a", "b"]);
-        test_concat!("ab", [s("a"), s("b")]);
+        test_concat!("ab", vec![s("a"), s("b")]);
         test_concat!("ab", vec!["a", "b"]);
         test_concat!("ab", vec!["a", "b"].as_slice());
         test_concat!("ab", vec![s("a"), s("b")]);
-
-        let mut v0 = ["a", "b"];
-        let mut v1 = [s("a"), s("b")];
-        unsafe {
-            use std::c_vec::CVec;
-
-            test_concat!("ab", CVec::new(v0.as_mut_ptr(), v0.len()));
-            test_concat!("ab", CVec::new(v1.as_mut_ptr(), v1.len()));
-        }
-
-        test_concat!("ab", S { x: [s("a"), s("b")] });
     }
 
     #[test]
@@ -1951,17 +1903,6 @@ mod tests {
         test_connect!("a-b", vec!["a", "b"], hyphen.as_slice());
         test_connect!("a-b", vec!["a", "b"].as_slice(), "-");
         test_connect!("a-b", vec![s("a"), s("b")], "-");
-
-        let mut v0 = ["a", "b"];
-        let mut v1 = [s("a"), s("b")];
-        unsafe {
-            use std::c_vec::CVec;
-
-            test_connect!("a-b", CVec::new(v0.as_mut_ptr(), v0.len()), "-");
-            test_connect!("a-b", CVec::new(v1.as_mut_ptr(), v1.len()), hyphen.as_slice());
-        }
-
-        test_connect!("a-b", S { x: [s("a"), s("b")] }, "-");
     }
 
     #[test]
@@ -2576,7 +2517,7 @@ mod tests {
 
     #[test]
     fn test_chars_decoding() {
-        let mut bytes = [0u8, ..4];
+        let mut bytes = [0u8; 4];
         for c in range(0u32, 0x110000).filter_map(|c| ::core::char::from_u32(c)) {
             let len = c.encode_utf8(&mut bytes).unwrap_or(0);
             let s = ::core::str::from_utf8(bytes[..len]).unwrap();
@@ -2588,7 +2529,7 @@ mod tests {
 
     #[test]
     fn test_chars_rev_decoding() {
-        let mut bytes = [0u8, ..4];
+        let mut bytes = [0u8; 4];
         for c in range(0u32, 0x110000).filter_map(|c| ::core::char::from_u32(c)) {
             let len = c.encode_utf8(&mut bytes).unwrap_or(0);
             let s = ::core::str::from_utf8(bytes[..len]).unwrap();
@@ -2802,7 +2743,7 @@ mod tests {
         use core::iter::order;
         // official Unicode test data
         // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt
-        let test_same: [(_, &[_]), .. 325] = [
+        let test_same: [(_, &[_]); 325] = [
             ("\u{20}\u{20}", &["\u{20}", "\u{20}"]),
             ("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]),
             ("\u{20}\u{D}", &["\u{20}", "\u{D}"]),
@@ -3134,7 +3075,7 @@ mod tests {
             ("\u{646}\u{200D}\u{20}", &["\u{646}\u{200D}", "\u{20}"]),
         ];
 
-        let test_diff: [(_, &[_], &[_]), .. 23] = [
+        let test_diff: [(_, &[_], &[_]); 23] = [
             ("\u{20}\u{903}", &["\u{20}\u{903}"], &["\u{20}", "\u{903}"]), ("\u{20}\u{308}\u{903}",
             &["\u{20}\u{308}\u{903}"], &["\u{20}\u{308}", "\u{903}"]), ("\u{D}\u{308}\u{903}",
             &["\u{D}", "\u{308}\u{903}"], &["\u{D}", "\u{308}", "\u{903}"]), ("\u{A}\u{308}\u{903}",
@@ -3331,7 +3272,7 @@ mod tests {
 #[cfg(test)]
 mod bench {
     use super::*;
-    use prelude::*;
+    use prelude::{SliceExt, IteratorExt, DoubleEndedIteratorExt, SliceConcatExt};
     use test::Bencher;
     use test::black_box;
 
@@ -3494,7 +3435,7 @@ mod bench {
     fn bench_connect(b: &mut Bencher) {
         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
         let sep = "→";
-        let v = [s, s, s, s, s, s, s, s, s, s];
+        let v = vec![s, s, s, s, s, s, s, s, s, s];
         b.iter(|| {
             assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9);
         })
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 26ff3e86794..ae038a9f089 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -12,6 +12,8 @@
 
 //! An owned, growable string that enforces that its contents are valid UTF-8.
 
+#![stable]
+
 use core::prelude::*;
 
 use core::borrow::{Cow, IntoCow};
@@ -38,6 +40,18 @@ pub struct String {
     vec: Vec<u8>,
 }
 
+/// A possible error value from the `String::from_utf8` function.
+#[stable]
+pub struct FromUtf8Error {
+    bytes: Vec<u8>,
+    error: Utf8Error,
+}
+
+/// A possible error value from the `String::from_utf16` function.
+#[stable]
+#[allow(missing_copy_implementations)]
+pub struct FromUtf16Error(());
+
 impl String {
     /// Creates a new string buffer initialized with the empty string.
     ///
@@ -100,19 +114,20 @@ impl String {
     /// use std::str::Utf8Error;
     ///
     /// let hello_vec = vec![104, 101, 108, 108, 111];
-    /// let s = String::from_utf8(hello_vec);
-    /// assert_eq!(s, Ok("hello".to_string()));
+    /// let s = String::from_utf8(hello_vec).unwrap();
+    /// assert_eq!(s, "hello");
     ///
     /// let invalid_vec = vec![240, 144, 128];
-    /// let s = String::from_utf8(invalid_vec);
-    /// assert_eq!(s, Err((vec![240, 144, 128], Utf8Error::TooShort)));
+    /// let s = String::from_utf8(invalid_vec).err().unwrap();
+    /// assert_eq!(s.utf8_error(), Utf8Error::TooShort);
+    /// assert_eq!(s.into_bytes(), vec![240, 144, 128]);
     /// ```
     #[inline]
-    #[unstable = "error type may change"]
-    pub fn from_utf8(vec: Vec<u8>) -> Result<String, (Vec<u8>, Utf8Error)> {
+    #[stable]
+    pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
         match str::from_utf8(vec.as_slice()) {
             Ok(..) => Ok(String { vec: vec }),
-            Err(e) => Err((vec, e))
+            Err(e) => Err(FromUtf8Error { bytes: vec, error: e })
         }
     }
 
@@ -126,7 +141,7 @@ impl String {
     /// let output = String::from_utf8_lossy(input);
     /// assert_eq!(output.as_slice(), "Hello \u{FFFD}World");
     /// ```
-    #[unstable = "return type may change"]
+    #[stable]
     pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> {
         match str::from_utf8(v) {
             Ok(s) => return Cow::Borrowed(s),
@@ -138,7 +153,7 @@ impl String {
         let mut i = 0;
         let total = v.len();
         fn unsafe_get(xs: &[u8], i: uint) -> u8 {
-            unsafe { *xs.unsafe_get(i) }
+            unsafe { *xs.get_unchecked(i) }
         }
         fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 {
             if i >= total {
@@ -253,22 +268,23 @@ impl String {
     /// // 𝄞music
     /// let mut v = &mut [0xD834, 0xDD1E, 0x006d, 0x0075,
     ///                   0x0073, 0x0069, 0x0063];
-    /// assert_eq!(String::from_utf16(v), Some("𝄞music".to_string()));
+    /// assert_eq!(String::from_utf16(v).unwrap(),
+    ///            "𝄞music".to_string());
     ///
     /// // 𝄞mu<invalid>ic
     /// v[4] = 0xD800;
-    /// assert_eq!(String::from_utf16(v), None);
+    /// assert!(String::from_utf16(v).is_err());
     /// ```
-    #[unstable = "error value in return may change"]
-    pub fn from_utf16(v: &[u16]) -> Option<String> {
+    #[stable]
+    pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
         let mut s = String::with_capacity(v.len());
         for c in unicode_str::utf16_items(v) {
             match c {
                 Utf16Item::ScalarValue(c) => s.push(c),
-                Utf16Item::LoneSurrogate(_) => return None
+                Utf16Item::LoneSurrogate(_) => return Err(FromUtf16Error(())),
             }
         }
-        Some(s)
+        Ok(s)
     }
 
     /// Decode a UTF-16 encoded vector `v` into a string, replacing
@@ -295,12 +311,13 @@ impl String {
     /// # Examples
     ///
     /// ```rust
+    /// # #![allow(deprecated)]
     /// let chars = &['h', 'e', 'l', 'l', 'o'];
     /// let s = String::from_chars(chars);
     /// assert_eq!(s.as_slice(), "hello");
     /// ```
     #[inline]
-    #[unstable = "may be removed in favor of .collect()"]
+    #[deprecated = "use .collect() instead"]
     pub fn from_chars(chs: &[char]) -> String {
         chs.iter().map(|c| *c).collect()
     }
@@ -311,7 +328,7 @@ impl String {
     /// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
     /// * We assume that the `Vec` contains valid UTF-8.
     #[inline]
-    #[unstable = "function just moved from string::raw"]
+    #[stable]
     pub unsafe fn from_raw_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
         String {
             vec: Vec::from_raw_parts(buf, length, capacity),
@@ -346,7 +363,7 @@ impl String {
     /// it contains valid UTF-8. This is unsafe because it assumes that
     /// the UTF-8-ness of the vector has already been validated.
     #[inline]
-    #[unstable = "awaiting stabilization"]
+    #[stable]
     pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
         String { vec: bytes }
     }
@@ -371,12 +388,12 @@ impl String {
     /// # Examples
     ///
     /// ```
+    /// # #![allow(deprecated)]
     /// let s = String::from_char(5, 'a');
     /// assert_eq!(s.as_slice(), "aaaaa");
     /// ```
     #[inline]
-    #[unstable = "may be replaced with iterators, questionable usability, and \
-                  the name may change"]
+    #[deprecated = "use repeat(ch).take(length).collect() instead"]
     pub fn from_char(length: uint, ch: char) -> String {
         if length == 0 {
             return String::new()
@@ -402,7 +419,7 @@ impl String {
     /// assert_eq!(s.as_slice(), "foobar");
     /// ```
     #[inline]
-    #[unstable = "extra variants of `push`, could possibly be based on iterators"]
+    #[stable]
     pub fn push_str(&mut self, string: &str) {
         self.vec.push_all(string.as_bytes())
     }
@@ -412,19 +429,21 @@ impl String {
     /// # Examples
     ///
     /// ```
+    /// # #![allow(deprecated)]
     /// let mut s = String::from_str("foo");
     /// s.grow(5, 'Z');
     /// assert_eq!(s.as_slice(), "fooZZZZZ");
     /// ```
     #[inline]
-    #[unstable = "duplicate of iterator-based functionality"]
+    #[deprecated = "deprecated in favor of .extend(repeat(ch).take(count))"]
     pub fn grow(&mut self, count: uint, ch: char) {
         for _ in range(0, count) {
             self.push(ch)
         }
     }
 
-    /// Returns the number of bytes that this string buffer can hold without reallocating.
+    /// Returns the number of bytes that this string buffer can hold without
+    /// reallocating.
     ///
     /// # Examples
     ///
@@ -433,7 +452,7 @@ impl String {
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint {
         self.vec.capacity()
     }
@@ -444,8 +463,9 @@ impl String {
         self.vec.reserve(extra)
     }
 
-    /// Reserves capacity for at least `additional` more bytes to be inserted in the given
-    /// `String`. The collection may reserve more space to avoid frequent reallocations.
+    /// Reserves capacity for at least `additional` more bytes to be inserted
+    /// in the given `String`. The collection may reserve more space to avoid
+    /// frequent reallocations.
     ///
     /// # Panics
     ///
@@ -459,17 +479,18 @@ impl String {
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve(&mut self, additional: uint) {
         self.vec.reserve(additional)
     }
 
-    /// Reserves the minimum capacity for exactly `additional` more bytes to be inserted in the
-    /// given `String`. Does nothing if the capacity is already sufficient.
+    /// Reserves the minimum capacity for exactly `additional` more bytes to be
+    /// inserted in the given `String`. Does nothing if the capacity is already
+    /// sufficient.
     ///
-    /// Note that the allocator may give the collection more space than it requests. Therefore
-    /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
-    /// insertions are expected.
+    /// Note that the allocator may give the collection more space than it
+    /// requests. Therefore capacity can not be relied upon to be precisely
+    /// minimal. Prefer `reserve` if future insertions are expected.
     ///
     /// # Panics
     ///
@@ -483,7 +504,7 @@ impl String {
     /// assert!(s.capacity() >= 10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_exact(&mut self, additional: uint) {
         self.vec.reserve_exact(additional)
     }
@@ -500,7 +521,7 @@ impl String {
     /// assert_eq!(s.capacity(), 3);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn shrink_to_fit(&mut self) {
         self.vec.shrink_to_fit()
     }
@@ -517,7 +538,7 @@ impl String {
     /// assert_eq!(s.as_slice(), "abc123");
     /// ```
     #[inline]
-    #[stable = "function just renamed from push_char"]
+    #[stable]
     pub fn push(&mut self, ch: char) {
         if (ch as u32) < 0x80 {
             self.vec.push(ch as u8);
@@ -570,7 +591,7 @@ impl String {
     /// assert_eq!(s.as_slice(), "he");
     /// ```
     #[inline]
-    #[unstable = "the panic conventions for strings are under development"]
+    #[stable]
     pub fn truncate(&mut self, new_len: uint) {
         assert!(self.is_char_boundary(new_len));
         self.vec.truncate(new_len)
@@ -589,7 +610,7 @@ impl String {
     /// assert_eq!(s.pop(), None);
     /// ```
     #[inline]
-    #[unstable = "this function was just renamed from pop_char"]
+    #[stable]
     pub fn pop(&mut self) -> Option<char> {
         let len = self.len();
         if len == 0 {
@@ -604,7 +625,7 @@ impl String {
     }
 
     /// Removes the character from the string buffer at byte position `idx` and
-    /// returns it. Returns `None` if `idx` is out of bounds.
+    /// returns it.
     ///
     /// # Warning
     ///
@@ -613,23 +634,21 @@ impl String {
     ///
     /// # Panics
     ///
-    /// If `idx` does not lie on a character boundary, then this function will
-    /// panic.
+    /// If `idx` does not lie on a character boundary, or if it is out of
+    /// bounds, then this function will panic.
     ///
     /// # Examples
     ///
     /// ```
     /// let mut s = String::from_str("foo");
-    /// assert_eq!(s.remove(0), Some('f'));
-    /// assert_eq!(s.remove(1), Some('o'));
-    /// assert_eq!(s.remove(0), Some('o'));
-    /// assert_eq!(s.remove(0), None);
+    /// assert_eq!(s.remove(0), 'f');
+    /// assert_eq!(s.remove(1), 'o');
+    /// assert_eq!(s.remove(0), 'o');
     /// ```
-    #[unstable = "the panic semantics of this function and return type \
-                  may change"]
-    pub fn remove(&mut self, idx: uint) -> Option<char> {
+    #[stable]
+    pub fn remove(&mut self, idx: uint) -> char {
         let len = self.len();
-        if idx >= len { return None }
+        assert!(idx <= len);
 
         let CharRange { ch, next } = self.char_range_at(idx);
         unsafe {
@@ -638,7 +657,7 @@ impl String {
                              len - next);
             self.vec.set_len(len - (next - idx));
         }
-        Some(ch)
+        ch
     }
 
     /// Insert a character into the string buffer at byte position `idx`.
@@ -652,13 +671,13 @@ impl String {
     ///
     /// If `idx` does not lie on a character boundary or is out of bounds, then
     /// this function will panic.
-    #[unstable = "the panic semantics of this function are uncertain"]
+    #[stable]
     pub fn insert(&mut self, idx: uint, ch: char) {
         let len = self.len();
         assert!(idx <= len);
         assert!(self.is_char_boundary(idx));
         self.vec.reserve(4);
-        let mut bits = [0, ..4];
+        let mut bits = [0; 4];
         let amt = ch.encode_utf8(&mut bits).unwrap();
 
         unsafe {
@@ -688,7 +707,7 @@ impl String {
     /// }
     /// assert_eq!(s.as_slice(), "olleh");
     /// ```
-    #[unstable = "the name of this method may be changed"]
+    #[stable]
     pub unsafe fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec<u8> {
         &mut self.vec
     }
@@ -715,6 +734,7 @@ impl String {
     /// v.push('a');
     /// assert!(!v.is_empty());
     /// ```
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Truncates the string, returning it to 0 length.
@@ -733,6 +753,29 @@ impl String {
     }
 }
 
+impl FromUtf8Error {
+    /// Consume this error, returning the bytes that were attempted to make a
+    /// `String` with.
+    #[stable]
+    pub fn into_bytes(self) -> Vec<u8> { self.bytes }
+
+    /// Access the underlying UTF8-error that was the cause of this error.
+    #[stable]
+    pub fn utf8_error(&self) -> Utf8Error { self.error }
+}
+
+impl fmt::Show for FromUtf8Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.error.fmt(f)
+    }
+}
+
+impl fmt::Show for FromUtf16Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "invalid utf-16: lone surrogate found".fmt(f)
+    }
+}
+
 #[experimental = "waiting on FromIterator stabilization"]
 impl FromIterator<char> for String {
     fn from_iter<I:Iterator<char>>(iterator: I) -> String {
@@ -774,6 +817,7 @@ impl<'a> Extend<&'a str> for String {
     }
 }
 
+#[stable]
 impl PartialEq for String {
     #[inline]
     fn eq(&self, other: &String) -> bool { PartialEq::eq(&**self, &**other) }
@@ -783,6 +827,7 @@ impl PartialEq for String {
 
 macro_rules! impl_eq {
     ($lhs:ty, $rhs: ty) => {
+        #[stable]
         impl<'a> PartialEq<$rhs> for $lhs {
             #[inline]
             fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
@@ -790,6 +835,7 @@ macro_rules! impl_eq {
             fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
         }
 
+        #[stable]
         impl<'a> PartialEq<$lhs> for $rhs {
             #[inline]
             fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) }
@@ -803,6 +849,7 @@ macro_rules! impl_eq {
 impl_eq! { String, &'a str }
 impl_eq! { CowString<'a>, String }
 
+#[stable]
 impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
     #[inline]
     fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) }
@@ -810,6 +857,7 @@ impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
     fn ne(&self, other: &&'b str) -> bool { PartialEq::ne(&**self, &**other) }
 }
 
+#[stable]
 impl<'a, 'b> PartialEq<CowString<'a>> for &'b str {
     #[inline]
     fn eq(&self, other: &CowString<'a>) -> bool { PartialEq::eq(&**self, &**other) }
@@ -935,6 +983,7 @@ impl FromStr for String {
 }
 
 /// Trait for converting a type to a string, consuming it in the process.
+#[deprecated = "trait will be removed"]
 pub trait IntoString {
     /// Consume and convert to a string.
     fn into_string(self) -> String;
@@ -947,20 +996,11 @@ pub trait ToString {
 }
 
 impl<T: fmt::Show> ToString for T {
-    // NOTE(stage0): Remove cfg after a snapshot
-    #[cfg(not(stage0))]
     fn to_string(&self) -> String {
         let mut buf = Vec::<u8>::new();
         let _ = fmt::write(&mut buf, format_args!("{}", *self));
         String::from_utf8(buf).unwrap()
     }
-    // NOTE(stage0): Remove method after a snapshot
-    #[cfg(stage0)]
-    fn to_string(&self) -> String {
-        let mut buf = Vec::<u8>::new();
-        let _ = format_args!(|args| fmt::write(&mut buf, args), "{}", self);
-        String::from_utf8(buf).unwrap()
-    }
 }
 
 impl IntoCow<'static, String, str> for String {
@@ -1040,7 +1080,7 @@ mod tests {
     use prelude::*;
     use test::Bencher;
 
-    use str::{StrExt, Utf8Error};
+    use str::Utf8Error;
     use str;
     use super::as_string;
 
@@ -1059,16 +1099,17 @@ mod tests {
     #[test]
     fn test_from_utf8() {
         let xs = b"hello".to_vec();
-        assert_eq!(String::from_utf8(xs),
-                   Ok(String::from_str("hello")));
+        assert_eq!(String::from_utf8(xs).unwrap(),
+                   String::from_str("hello"));
 
         let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
-        assert_eq!(String::from_utf8(xs),
-                   Ok(String::from_str("ศไทย中华Việt Nam")));
+        assert_eq!(String::from_utf8(xs).unwrap(),
+                   String::from_str("ศไทย中华Việt Nam"));
 
         let xs = b"hello\xFF".to_vec();
-        assert_eq!(String::from_utf8(xs),
-                   Err((b"hello\xFF".to_vec(), Utf8Error::TooShort)));
+        let err = String::from_utf8(xs).err().unwrap();
+        assert_eq!(err.utf8_error(), Utf8Error::TooShort);
+        assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
     }
 
     #[test]
@@ -1173,15 +1214,15 @@ mod tests {
     fn test_utf16_invalid() {
         // completely positive cases tested above.
         // lead + eof
-        assert_eq!(String::from_utf16(&[0xD800]), None);
+        assert!(String::from_utf16(&[0xD800]).is_err());
         // lead + lead
-        assert_eq!(String::from_utf16(&[0xD800, 0xD800]), None);
+        assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
 
         // isolated trail
-        assert_eq!(String::from_utf16(&[0x0061, 0xDC00]), None);
+        assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
 
         // general
-        assert_eq!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]), None);
+        assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
     }
 
     #[test]
@@ -1314,12 +1355,10 @@ mod tests {
     #[test]
     fn remove() {
         let mut s = "ศไทย中华Việt Nam; foobar".to_string();;
-        assert_eq!(s.remove(0), Some('ศ'));
+        assert_eq!(s.remove(0), 'ศ');
         assert_eq!(s.len(), 33);
         assert_eq!(s, "ไทย中华Việt Nam; foobar");
-        assert_eq!(s.remove(33), None);
-        assert_eq!(s.remove(300), None);
-        assert_eq!(s.remove(17), Some('ệ'));
+        assert_eq!(s.remove(17), 'ệ');
         assert_eq!(s, "ไทย中华Vit Nam; foobar");
     }
 
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index e5c2ef9300e..4b7aa896870 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -144,26 +144,9 @@ pub struct Vec<T> {
 unsafe impl<T: Send> Send for Vec<T> { }
 unsafe impl<T: Sync> Sync for Vec<T> { }
 
-/// A clone-on-write vector
-pub type CowVec<'a, T> = Cow<'a, Vec<T>, [T]>;
-
-impl<'a, T> FromIterator<T> for CowVec<'a, T> where T: Clone {
-    fn from_iter<I: Iterator<T>>(it: I) -> CowVec<'a, T> {
-        Cow::Owned(FromIterator::from_iter(it))
-    }
-}
-
-impl<'a, T: 'a> IntoCow<'a, Vec<T>, [T]> for Vec<T> where T: Clone {
-    fn into_cow(self) -> CowVec<'a, T> {
-        Cow::Owned(self)
-    }
-}
-
-impl<'a, T> IntoCow<'a, Vec<T>, [T]> for &'a [T] where T: Clone {
-    fn into_cow(self) -> CowVec<'a, T> {
-        Cow::Borrowed(self)
-    }
-}
+////////////////////////////////////////////////////////////////////////////////
+// Inherent methods
+////////////////////////////////////////////////////////////////////////////////
 
 impl<T> Vec<T> {
     /// Constructs a new, empty `Vec<T>`.
@@ -192,8 +175,7 @@ impl<T> Vec<T> {
     ///
     /// It is important to note that this function does not specify the *length* of the returned
     /// vector, but only the *capacity*. (For an explanation of the difference between length and
-    /// capacity, see the main `Vec<T>` docs above, 'Capacity and reallocation'.) To create a
-    /// vector of a given length, use `Vec::from_elem` or `Vec::from_fn`.
+    /// capacity, see the main `Vec<T>` docs above, 'Capacity and reallocation'.)
     ///
     /// # Examples
     ///
@@ -227,30 +209,11 @@ impl<T> Vec<T> {
         }
     }
 
-    /// Creates and initializes a `Vec<T>`.
-    ///
-    /// Creates a `Vec<T>` of size `length` and initializes the elements to the value returned by
-    /// the closure `op`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let vec = Vec::from_fn(3, |idx| idx * 2);
-    /// assert_eq!(vec, vec![0, 2, 4]);
-    /// ```
+    /// Deprecated: use `iter::range(0, length).map(op).collect()` instead
     #[inline]
-    #[unstable = "the naming is uncertain as well as this migrating to unboxed \
-                  closures in the future"]
-    pub fn from_fn<F>(length: uint, mut op: F) -> Vec<T> where F: FnMut(uint) -> T {
-        unsafe {
-            let mut xs = Vec::with_capacity(length);
-            while xs.len < length {
-                let len = xs.len;
-                ptr::write(xs.unsafe_mut(len), op(len));
-                xs.len += 1;
-            }
-            xs
-        }
+    #[deprecated = "use iter::range(0, length).map(op).collect() instead"]
+    pub fn from_fn<F>(length: uint, op: F) -> Vec<T> where F: FnMut(uint) -> T {
+        range(0, length).map(op).collect()
     }
 
     /// Creates a `Vec<T>` directly from the raw components of another vector.
@@ -287,7 +250,7 @@ impl<T> Vec<T> {
     ///     }
     /// }
     /// ```
-    #[unstable = "needs finalization"]
+    #[stable]
     pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
                                  capacity: uint) -> Vec<T> {
         Vec { ptr: NonZero::new(ptr), len: length, cap: capacity }
@@ -299,7 +262,7 @@ impl<T> Vec<T> {
     /// owned by the returned `Vec<T>`. The elements of the buffer are copied into the vector
     /// without cloning, as if `ptr::read()` were called on them.
     #[inline]
-    #[unstable = "just renamed from raw::from_buf"]
+    #[unstable = "may be better expressed via composition"]
     pub unsafe fn from_raw_buf(ptr: *const T, elts: uint) -> Vec<T> {
         let mut dst = Vec::with_capacity(elts);
         dst.set_len(elts);
@@ -307,406 +270,15 @@ impl<T> Vec<T> {
         dst
     }
 
-    /// Consumes the `Vec<T>`, partitioning it based on a predicate.
-    ///
-    /// Partitions the `Vec<T>` into two `Vec<T>`s `(A,B)`, where all elements of `A` satisfy `f`
-    /// and all elements of `B` do not. The order of elements is preserved.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let vec = vec![1i, 2i, 3i, 4i];
-    /// let (even, odd) = vec.partition(|&n| n % 2 == 0);
-    /// assert_eq!(even, vec![2, 4]);
-    /// assert_eq!(odd, vec![1, 3]);
-    /// ```
-    #[inline]
-    #[experimental]
-    pub fn partition<F>(self, mut f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
-        let mut lefts  = Vec::new();
-        let mut rights = Vec::new();
-
-        for elt in self.into_iter() {
-            if f(&elt) {
-                lefts.push(elt);
-            } else {
-                rights.push(elt);
-            }
-        }
-
-        (lefts, rights)
-    }
-}
-
-impl<T: Clone> Vec<T> {
-    /// Constructs a `Vec<T>` with copies of a value.
-    ///
-    /// Creates a `Vec<T>` with `length` copies of `value`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let vec = Vec::from_elem(3, "hi");
-    /// println!("{}", vec); // prints [hi, hi, hi]
-    /// ```
+    /// Deprecated: use `into_iter().partition(f)` instead.
     #[inline]
-    #[unstable = "this functionality may become more generic over all collections"]
-    pub fn from_elem(length: uint, value: T) -> Vec<T> {
-        unsafe {
-            let mut xs = Vec::with_capacity(length);
-            while xs.len < length {
-                let len = xs.len;
-                ptr::write(xs.unsafe_mut(len),
-                           value.clone());
-                xs.len += 1;
-            }
-            xs
-        }
-    }
-
-    /// Appends all elements in a slice to the `Vec<T>`.
-    ///
-    /// Iterates over the slice `other`, clones each element, and then appends
-    /// it to this `Vec<T>`. The `other` vector is traversed in-order.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut vec = vec![1i];
-    /// vec.push_all(&[2i, 3, 4]);
-    /// assert_eq!(vec, vec![1, 2, 3, 4]);
-    /// ```
-    #[inline]
-    #[experimental]
-    pub fn push_all(&mut self, other: &[T]) {
-        self.reserve(other.len());
-
-        for i in range(0, other.len()) {
-            let len = self.len();
-
-            // Unsafe code so this can be optimised to a memcpy (or something similarly
-            // fast) when T is Copy. LLVM is easily confused, so any extra operations
-            // during the loop can prevent this optimisation.
-            unsafe {
-                ptr::write(
-                    self.unsafe_mut(len),
-                    other.unsafe_get(i).clone());
-                self.set_len(len + 1);
-            }
-        }
-    }
-
-    /// Grows the `Vec<T>` in-place.
-    ///
-    /// Adds `n` copies of `value` to the `Vec<T>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut vec = vec!["hello"];
-    /// vec.grow(2, "world");
-    /// assert_eq!(vec, vec!["hello", "world", "world"]);
-    /// ```
-    #[stable]
-    pub fn grow(&mut self, n: uint, value: T) {
-        self.reserve(n);
-        let mut i: uint = 0u;
-
-        while i < n {
-            self.push(value.clone());
-            i += 1u;
-        }
-    }
-
-    /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
-    ///
-    /// Calls either `extend()` or `truncate()` depending on whether `new_len`
-    /// is larger than the current value of `len()` or not.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut vec = vec!["hello"];
-    /// vec.resize(3, "world");
-    /// assert_eq!(vec, vec!["hello", "world", "world"]);
-    ///
-    /// let mut vec = vec![1i, 2, 3, 4];
-    /// vec.resize(2, 0);
-    /// assert_eq!(vec, vec![1, 2]);
-    /// ```
-    #[unstable = "matches collection reform specification; waiting for dust to settle"]
-    pub fn resize(&mut self, new_len: uint, value: T) {
-        let len = self.len();
-
-        if new_len > len {
-            self.extend(repeat(value).take(new_len - len));
-        } else {
-            self.truncate(new_len);
-        }
+    #[deprecated = "use into_iter().partition(f) instead"]
+    pub fn partition<F>(self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
+        self.into_iter().partition(f)
     }
 
-    /// Partitions a vector based on a predicate.
-    ///
-    /// Clones the elements of the vector, partitioning them into two `Vec<T>`s
-    /// `(a, b)`, where all elements of `a` satisfy `f` and all elements of `b`
-    /// do not. The order of elements is preserved.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let vec = vec![1i, 2, 3, 4];
-    /// let (even, odd) = vec.partitioned(|&n| n % 2 == 0);
-    /// assert_eq!(even, vec![2i, 4]);
-    /// assert_eq!(odd, vec![1i, 3]);
-    /// ```
-    #[experimental]
-    pub fn partitioned<F>(&self, mut f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
-        let mut lefts = Vec::new();
-        let mut rights = Vec::new();
-
-        for elt in self.iter() {
-            if f(elt) {
-                lefts.push(elt.clone());
-            } else {
-                rights.push(elt.clone());
-            }
-        }
-
-        (lefts, rights)
-    }
-}
-
-#[stable]
-impl<T:Clone> Clone for Vec<T> {
-    fn clone(&self) -> Vec<T> { self.as_slice().to_vec() }
-
-    fn clone_from(&mut self, other: &Vec<T>) {
-        // drop anything in self that will not be overwritten
-        if self.len() > other.len() {
-            self.truncate(other.len())
-        }
-
-        // reuse the contained values' allocations/resources.
-        for (place, thing) in self.iter_mut().zip(other.iter()) {
-            place.clone_from(thing)
-        }
-
-        // self.len <= other.len due to the truncate above, so the
-        // slice here is always in-bounds.
-        let slice = other[self.len()..];
-        self.push_all(slice);
-    }
-}
-
-#[experimental = "waiting on Index stability"]
-impl<T> Index<uint,T> for Vec<T> {
-    #[inline]
-    fn index<'a>(&'a self, index: &uint) -> &'a T {
-        &self.as_slice()[*index]
-    }
-}
-
-impl<T> IndexMut<uint,T> for Vec<T> {
-    #[inline]
-    fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut T {
-        &mut self.as_mut_slice()[*index]
-    }
-}
-
-impl<T> ops::Slice<uint, [T]> for Vec<T> {
-    #[inline]
-    fn as_slice_<'a>(&'a self) -> &'a [T] {
-        self.as_slice()
-    }
-
-    #[inline]
-    fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] {
-        self.as_slice().slice_from_or_fail(start)
-    }
-
-    #[inline]
-    fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] {
-        self.as_slice().slice_to_or_fail(end)
-    }
-    #[inline]
-    fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
-        self.as_slice().slice_or_fail(start, end)
-    }
-}
-
-impl<T> ops::SliceMut<uint, [T]> for Vec<T> {
-    #[inline]
-    fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
-        self.as_mut_slice()
-    }
-
-    #[inline]
-    fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
-        self.as_mut_slice().slice_from_or_fail_mut(start)
-    }
-
-    #[inline]
-    fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
-        self.as_mut_slice().slice_to_or_fail_mut(end)
-    }
-    #[inline]
-    fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
-        self.as_mut_slice().slice_or_fail_mut(start, end)
-    }
-}
-
-#[experimental = "waiting on Deref stability"]
-impl<T> ops::Deref<[T]> for Vec<T> {
-    fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() }
-}
-
-#[experimental = "waiting on DerefMut stability"]
-impl<T> ops::DerefMut<[T]> for Vec<T> {
-    fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() }
-}
-
-#[experimental = "waiting on FromIterator stability"]
-impl<T> FromIterator<T> for Vec<T> {
-    #[inline]
-    fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
-        let (lower, _) = iterator.size_hint();
-        let mut vector = Vec::with_capacity(lower);
-        for element in iterator {
-            vector.push(element)
-        }
-        vector
-    }
-}
-
-#[experimental = "waiting on Extend stability"]
-impl<T> Extend<T> for Vec<T> {
-    #[inline]
-    fn extend<I: Iterator<T>>(&mut self, mut iterator: I) {
-        let (lower, _) = iterator.size_hint();
-        self.reserve(lower);
-        for element in iterator {
-            self.push(element)
-        }
-    }
-}
-
-impl<A, B> PartialEq<Vec<B>> for Vec<A> where A: PartialEq<B> {
-    #[inline]
-    fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
-    #[inline]
-    fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
-}
-
-macro_rules! impl_eq {
-    ($lhs:ty, $rhs:ty) => {
-        impl<'b, A, B> PartialEq<$rhs> for $lhs where A: PartialEq<B> {
-            #[inline]
-            fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
-        }
-
-        impl<'b, A, B> PartialEq<$lhs> for $rhs where B: PartialEq<A> {
-            #[inline]
-            fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) }
-        }
-    }
-}
-
-impl_eq! { Vec<A>, &'b [B] }
-impl_eq! { Vec<A>, &'b mut [B] }
-
-impl<'a, A, B> PartialEq<Vec<B>> for CowVec<'a, A> where A: PartialEq<B> + Clone {
-    #[inline]
-    fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
-    #[inline]
-    fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
-}
-
-impl<'a, A, B> PartialEq<CowVec<'a, A>> for Vec<B> where A: Clone, B: PartialEq<A> {
-    #[inline]
-    fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
-    #[inline]
-    fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
-}
-
-macro_rules! impl_eq_for_cowvec {
-    ($rhs:ty) => {
-        impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq<B> + Clone {
-            #[inline]
-            fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
-        }
-
-        impl<'a, 'b, A, B> PartialEq<CowVec<'a, A>> for $rhs where A: Clone, B: PartialEq<A> {
-            #[inline]
-            fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
-        }
-    }
-}
-
-impl_eq_for_cowvec! { &'b [B] }
-impl_eq_for_cowvec! { &'b mut [B] }
-
-#[unstable = "waiting on PartialOrd stability"]
-impl<T: PartialOrd> PartialOrd for Vec<T> {
-    #[inline]
-    fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
-        self.as_slice().partial_cmp(other.as_slice())
-    }
-}
-
-#[unstable = "waiting on Eq stability"]
-impl<T: Eq> Eq for Vec<T> {}
-
-#[allow(deprecated)]
-#[deprecated = "Use overloaded `core::cmp::PartialEq`"]
-impl<T: PartialEq, Sized? V: AsSlice<T>> Equiv<V> for Vec<T> {
-    #[inline]
-    fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
-}
-
-#[unstable = "waiting on Ord stability"]
-impl<T: Ord> Ord for Vec<T> {
-    #[inline]
-    fn cmp(&self, other: &Vec<T>) -> Ordering {
-        self.as_slice().cmp(other.as_slice())
-    }
-}
-
-impl<S: hash::Writer, T: Hash<S>> Hash<S> for Vec<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.as_slice().hash(state);
-    }
-}
-
-// FIXME: #13996: need a way to mark the return value as `noalias`
-#[inline(never)]
-unsafe fn alloc_or_realloc<T>(ptr: *mut T, old_size: uint, size: uint) -> *mut T {
-    if old_size == 0 {
-        allocate(size, mem::min_align_of::<T>()) as *mut T
-    } else {
-        reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::<T>()) as *mut T
-    }
-}
-
-#[inline]
-unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
-    if mem::size_of::<T>() != 0 {
-        deallocate(ptr as *mut u8,
-                   len * mem::size_of::<T>(),
-                   mem::min_align_of::<T>())
-    }
-}
-
-impl<T> Vec<T> {
-    /// Returns the number of elements the vector can hold without reallocating.
+    /// Returns the number of elements the vector can hold without
+    /// reallocating.
     ///
     /// # Examples
     ///
@@ -740,22 +312,23 @@ impl<T> Vec<T> {
     /// vec.reserve(10);
     /// assert!(vec.capacity() >= 11);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve(&mut self, additional: uint) {
         if self.cap - self.len < additional {
             let err_msg = "Vec::reserve: `uint` overflow";
             let new_cap = self.len.checked_add(additional).expect(err_msg)
-                                  .checked_next_power_of_two().expect(err_msg);
+                .checked_next_power_of_two().expect(err_msg);
             self.grow_capacity(new_cap);
         }
     }
 
-    /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
-    /// given `Vec<T>`. Does nothing if the capacity is already sufficient.
+    /// Reserves the minimum capacity for exactly `additional` more elements to
+    /// be inserted in the given `Vec<T>`. Does nothing if the capacity is already
+    /// sufficient.
     ///
-    /// Note that the allocator may give the collection more space than it requests. Therefore
-    /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
-    /// insertions are expected.
+    /// Note that the allocator may give the collection more space than it
+    /// requests. Therefore capacity can not be relied upon to be precisely
+    /// minimal. Prefer `reserve` if future insertions are expected.
     ///
     /// # Panics
     ///
@@ -768,7 +341,7 @@ impl<T> Vec<T> {
     /// vec.reserve_exact(10);
     /// assert!(vec.capacity() >= 11);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_exact(&mut self, additional: uint) {
         if self.cap - self.len < additional {
             match self.len.checked_add(additional) {
@@ -780,17 +353,15 @@ impl<T> Vec<T> {
 
     /// Shrinks the capacity of the vector as much as possible.
     ///
-    /// It will drop down as close as possible to the length but the allocator may still inform the
-    /// vector that there is space for a few more elements.
+    /// It will drop down as close as possible to the length but the allocator
+    /// may still inform the vector that there is space for a few more elements.
     ///
     /// # Examples
     ///
     /// ```
     /// let mut vec: Vec<int> = Vec::with_capacity(10);
-    ///
     /// vec.push_all(&[1, 2, 3]);
     /// assert_eq!(vec.capacity(), 10);
-    ///
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
     /// ```
@@ -822,8 +393,9 @@ impl<T> Vec<T> {
 
     /// Convert the vector into Box<[T]>.
     ///
-    /// Note that this will drop any excess capacity. Calling this and converting back to a vector
-    /// with `into_vec()` is equivalent to calling `shrink_to_fit()`.
+    /// Note that this will drop any excess capacity. Calling this and
+    /// converting back to a vector with `into_vec()` is equivalent to calling
+    /// `shrink_to_fit()`.
     #[experimental]
     pub fn into_boxed_slice(mut self) -> Box<[T]> {
         self.shrink_to_fit();
@@ -846,7 +418,7 @@ impl<T> Vec<T> {
     /// vec.truncate(2);
     /// assert_eq!(vec, vec![1, 2]);
     /// ```
-    #[unstable = "matches collection reform specification; waiting on panic semantics"]
+    #[stable]
     pub fn truncate(&mut self, len: uint) {
         unsafe {
             // drop any extra elements
@@ -854,7 +426,7 @@ impl<T> Vec<T> {
                 // decrement len before the read(), so a panic on Drop doesn't
                 // re-drop the just-failed value.
                 self.len -= 1;
-                ptr::read(self.unsafe_get(self.len));
+                ptr::read(self.get_unchecked(self.len));
             }
         }
     }
@@ -880,21 +452,21 @@ impl<T> Vec<T> {
         }
     }
 
-    /// Creates a consuming iterator, that is, one that moves each value out of the vector (from
-    /// start to end). The vector cannot be used after calling this.
+    /// Creates a consuming iterator, that is, one that moves each value out of
+    /// the vector (from start to end). The vector cannot be used after calling
+    /// this.
     ///
     /// # Examples
     ///
     /// ```
     /// let v = vec!["a".to_string(), "b".to_string()];
-    ///
     /// for s in v.into_iter() {
     ///     // s has type String, not &String
     ///     println!("{}", s);
     /// }
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<T> {
         unsafe {
             let ptr = *self.ptr;
@@ -912,8 +484,9 @@ impl<T> Vec<T> {
 
     /// Sets the length of a vector.
     ///
-    /// This will explicitly set the size of the vector, without actually modifying its buffers, so
-    /// it is up to the caller to ensure that the vector is actually the specified size.
+    /// This will explicitly set the size of the vector, without actually
+    /// modifying its buffers, so it is up to the caller to ensure that the
+    /// vector is actually the specified size.
     ///
     /// # Examples
     ///
@@ -929,44 +502,41 @@ impl<T> Vec<T> {
         self.len = len;
     }
 
-    /// Removes an element from anywhere in the vector and return it, replacing it with the last
-    /// element.
+    /// Removes an element from anywhere in the vector and return it, replacing
+    /// it with the last element.
     ///
     /// This does not preserve ordering, but is O(1).
     ///
-    /// Returns `None` if `index` is out of bounds.
+    /// # Panics
+    ///
+    /// Panics if `index` is out of bounds.
     ///
     /// # Examples
     ///
     /// ```
     /// let mut v = vec!["foo", "bar", "baz", "qux"];
     ///
-    /// assert_eq!(v.swap_remove(1), Some("bar"));
+    /// assert_eq!(v.swap_remove(1), "bar");
     /// assert_eq!(v, vec!["foo", "qux", "baz"]);
     ///
-    /// assert_eq!(v.swap_remove(0), Some("foo"));
+    /// assert_eq!(v.swap_remove(0), "foo");
     /// assert_eq!(v, vec!["baz", "qux"]);
-    ///
-    /// assert_eq!(v.swap_remove(2), None);
     /// ```
     #[inline]
-    #[unstable = "the naming of this function may be altered"]
-    pub fn swap_remove(&mut self, index: uint) -> Option<T> {
+    #[stable]
+    pub fn swap_remove(&mut self, index: uint) -> T {
         let length = self.len();
-        if length > 0 && index < length - 1 {
-            self.swap(index, length - 1);
-        } else if index >= length {
-            return None
-        }
-        self.pop()
+        self.swap(index, length - 1);
+        self.pop().unwrap()
     }
 
-    /// Inserts an element at position `index` within the vector, shifting all elements after
-    /// position `i` one position to the right.
+    /// Inserts an element at position `index` within the vector, shifting all
+    /// elements after position `i` one position to the right.
     ///
     /// # Panics
     ///
-    /// Panics if `index` is not between `0` and the vector's length (both bounds inclusive).
+    /// Panics if `index` is not between `0` and the vector's length (both
+    /// bounds inclusive).
     ///
     /// # Examples
     ///
@@ -977,7 +547,7 @@ impl<T> Vec<T> {
     /// vec.insert(4, 5);
     /// assert_eq!(vec, vec![1, 4, 2, 3, 5]);
     /// ```
-    #[unstable = "panic semantics need settling"]
+    #[stable]
     pub fn insert(&mut self, index: uint, element: T) {
         let len = self.len();
         assert!(index <= len);
@@ -999,49 +569,46 @@ impl<T> Vec<T> {
         }
     }
 
-    /// Removes and returns the element at position `index` within the vector, shifting all
-    /// elements after position `index` one position to the left. Returns `None` if `i` is out of
-    /// bounds.
+    /// Removes and returns the element at position `index` within the vector,
+    /// shifting all elements after position `index` one position to the left.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `i` is out of bounds.
     ///
     /// # Examples
     ///
     /// ```
     /// let mut v = vec![1i, 2, 3];
-    /// assert_eq!(v.remove(1), Some(2));
-    /// assert_eq!(v, vec![1, 3]);
-    ///
-    /// assert_eq!(v.remove(4), None);
-    /// // v is unchanged:
+    /// assert_eq!(v.remove(1), 2);
     /// assert_eq!(v, vec![1, 3]);
     /// ```
-    #[unstable = "panic semantics need settling"]
-    pub fn remove(&mut self, index: uint) -> Option<T> {
+    #[stable]
+    pub fn remove(&mut self, index: uint) -> T {
         let len = self.len();
-        if index < len {
-            unsafe { // infallible
-                let ret;
-                {
-                    // the place we are taking from.
-                    let ptr = self.as_mut_ptr().offset(index as int);
-                    // copy it out, unsafely having a copy of the value on
-                    // the stack and in the vector at the same time.
-                    ret = Some(ptr::read(ptr as *const T));
-
-                    // Shift everything down to fill in that spot.
-                    ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
-                }
-                self.set_len(len - 1);
-                ret
+        assert!(index < len);
+        unsafe { // infallible
+            let ret;
+            {
+                // the place we are taking from.
+                let ptr = self.as_mut_ptr().offset(index as int);
+                // copy it out, unsafely having a copy of the value on
+                // the stack and in the vector at the same time.
+                ret = ptr::read(ptr as *const T);
+
+                // Shift everything down to fill in that spot.
+                ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
             }
-        } else {
-            None
+            self.set_len(len - 1);
+            ret
         }
     }
 
     /// Retains only the elements specified by the predicate.
     ///
-    /// In other words, remove all elements `e` such that `f(&e)` returns false. This method
-    /// operates in place and preserves the order of the retained elements.
+    /// In other words, remove all elements `e` such that `f(&e)` returns false.
+    /// This method operates in place and preserves the order of the retained
+    /// elements.
     ///
     /// # Examples
     ///
@@ -1050,7 +617,7 @@ impl<T> Vec<T> {
     /// vec.retain(|&x| x%2 == 0);
     /// assert_eq!(vec, vec![2, 4]);
     /// ```
-    #[unstable = "the closure argument may become an unboxed closure"]
+    #[stable]
     pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
         let len = self.len();
         let mut del = 0u;
@@ -1070,24 +637,10 @@ impl<T> Vec<T> {
         }
     }
 
-    /// Expands a vector in place, initializing the new elements to the result of a function.
-    ///
-    /// The vector is grown by `n` elements. The i-th new element are initialized to the value
-    /// returned by `f(i)` where `i` is in the range [0, n).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let mut vec = vec![0u, 1];
-    /// vec.grow_fn(3, |i| i);
-    /// assert_eq!(vec, vec![0, 1, 0, 1, 2]);
-    /// ```
-    #[unstable = "this function may be renamed or change to unboxed closures"]
-    pub fn grow_fn<F>(&mut self, n: uint, mut f: F) where F: FnMut(uint) -> T {
-        self.reserve(n);
-        for i in range(0u, n) {
-            self.push(f(i));
-        }
+    /// Deprecated: use `extend(range(0, n).map(f))` instead.
+    #[deprecated = "use extend(range(0, n).map(f)) instead"]
+    pub fn grow_fn<F>(&mut self, n: uint, f: F) where F: FnMut(uint) -> T {
+        self.extend(range(0, n).map(f));
     }
 
     /// Appends an element to the back of a collection.
@@ -1107,7 +660,8 @@ impl<T> Vec<T> {
     #[stable]
     pub fn push(&mut self, value: T) {
         if mem::size_of::<T>() == 0 {
-            // zero-size types consume no memory, so we can't rely on the address space running out
+            // zero-size types consume no memory, so we can't rely on the
+            // address space running out
             self.len = self.len.checked_add(1).expect("length overflow");
             unsafe { mem::forget(value); }
             return
@@ -1148,7 +702,7 @@ impl<T> Vec<T> {
         } else {
             unsafe {
                 self.len -= 1;
-                Some(ptr::read(self.unsafe_get(self.len())))
+                Some(ptr::read(self.get_unchecked(self.len())))
             }
         }
     }
@@ -1225,29 +779,287 @@ impl<T> Vec<T> {
     /// v.push(1i);
     /// assert!(!v.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
-    /// Reserves capacity for exactly `capacity` elements in the given vector.
+    /// Converts a `Vec<T>` to a `Vec<U>` where `T` and `U` have the same
+    /// size and in case they are not zero-sized the same minimal alignment.
     ///
-    /// If the capacity for `self` is already equal to or greater than the
-    /// requested capacity, then no action is taken.
-    fn grow_capacity(&mut self, capacity: uint) {
-        if mem::size_of::<T>() == 0 { return }
+    /// # Panics
+    ///
+    /// Panics if `T` and `U` have differing sizes or are not zero-sized and
+    /// have differing minimal alignments.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v = vec![0u, 1, 2];
+    /// let w = v.map_in_place(|i| i + 3);
+    /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice());
+    ///
+    /// #[deriving(PartialEq, Show)]
+    /// struct Newtype(u8);
+    /// let bytes = vec![0x11, 0x22];
+    /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
+    /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice());
+    /// ```
+    #[experimental = "API may change to provide stronger guarantees"]
+    pub fn map_in_place<U, F>(self, mut f: F) -> Vec<U> where F: FnMut(T) -> U {
+        // FIXME: Assert statically that the types `T` and `U` have the same
+        // size.
+        assert!(mem::size_of::<T>() == mem::size_of::<U>());
 
-        if capacity > self.cap {
-            let size = capacity.checked_mul(mem::size_of::<T>())
-                               .expect("capacity overflow");
+        let mut vec = self;
+
+        if mem::size_of::<T>() != 0 {
+            // FIXME: Assert statically that the types `T` and `U` have the
+            // same minimal alignment in case they are not zero-sized.
+
+            // These asserts are necessary because the `min_align_of` of the
+            // types are passed to the allocator by `Vec`.
+            assert!(mem::min_align_of::<T>() == mem::min_align_of::<U>());
+
+            // This `as int` cast is safe, because the size of the elements of the
+            // vector is not 0, and:
+            //
+            // 1) If the size of the elements in the vector is 1, the `int` may
+            //    overflow, but it has the correct bit pattern so that the
+            //    `.offset()` function will work.
+            //
+            //    Example:
+            //        Address space 0x0-0xF.
+            //        `u8` array at: 0x1.
+            //        Size of `u8` array: 0x8.
+            //        Calculated `offset`: -0x8.
+            //        After `array.offset(offset)`: 0x9.
+            //        (0x1 + 0x8 = 0x1 - 0x8)
+            //
+            // 2) If the size of the elements in the vector is >1, the `uint` ->
+            //    `int` conversion can't overflow.
+            let offset = vec.len() as int;
+            let start = vec.as_mut_ptr();
+
+            let mut pv = PartialVecNonZeroSized {
+                vec: vec,
+
+                start_t: start,
+                // This points inside the vector, as the vector has length
+                // `offset`.
+                end_t: unsafe { start.offset(offset) },
+                start_u: start as *mut U,
+                end_u: start as *mut U,
+            };
+            //  start_t
+            //  start_u
+            //  |
+            // +-+-+-+-+-+-+
+            // |T|T|T|...|T|
+            // +-+-+-+-+-+-+
+            //  |           |
+            //  end_u       end_t
+
+            while pv.end_u as *mut T != pv.end_t {
+                unsafe {
+                    //  start_u start_t
+                    //  |       |
+                    // +-+-+-+-+-+-+-+-+-+
+                    // |U|...|U|T|T|...|T|
+                    // +-+-+-+-+-+-+-+-+-+
+                    //          |         |
+                    //          end_u     end_t
+
+                    let t = ptr::read(pv.start_t as *const T);
+                    //  start_u start_t
+                    //  |       |
+                    // +-+-+-+-+-+-+-+-+-+
+                    // |U|...|U|X|T|...|T|
+                    // +-+-+-+-+-+-+-+-+-+
+                    //          |         |
+                    //          end_u     end_t
+                    // We must not panic here, one cell is marked as `T`
+                    // although it is not `T`.
+
+                    pv.start_t = pv.start_t.offset(1);
+                    //  start_u   start_t
+                    //  |         |
+                    // +-+-+-+-+-+-+-+-+-+
+                    // |U|...|U|X|T|...|T|
+                    // +-+-+-+-+-+-+-+-+-+
+                    //          |         |
+                    //          end_u     end_t
+                    // We may panic again.
+
+                    // The function given by the user might panic.
+                    let u = f(t);
+
+                    ptr::write(pv.end_u, u);
+                    //  start_u   start_t
+                    //  |         |
+                    // +-+-+-+-+-+-+-+-+-+
+                    // |U|...|U|U|T|...|T|
+                    // +-+-+-+-+-+-+-+-+-+
+                    //          |         |
+                    //          end_u     end_t
+                    // We should not panic here, because that would leak the `U`
+                    // pointed to by `end_u`.
+
+                    pv.end_u = pv.end_u.offset(1);
+                    //  start_u   start_t
+                    //  |         |
+                    // +-+-+-+-+-+-+-+-+-+
+                    // |U|...|U|U|T|...|T|
+                    // +-+-+-+-+-+-+-+-+-+
+                    //            |       |
+                    //            end_u   end_t
+                    // We may panic again.
+                }
+            }
+
+            //  start_u     start_t
+            //  |           |
+            // +-+-+-+-+-+-+
+            // |U|...|U|U|U|
+            // +-+-+-+-+-+-+
+            //              |
+            //              end_t
+            //              end_u
+            // Extract `vec` and prevent the destructor of
+            // `PartialVecNonZeroSized` from running. Note that none of the
+            // function calls can panic, thus no resources can be leaked (as the
+            // `vec` member of `PartialVec` is the only one which holds
+            // allocations -- and it is returned from this function. None of
+            // this can panic.
             unsafe {
-                let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::<T>(), size);
-                if ptr.is_null() { ::alloc::oom() }
-                self.ptr = NonZero::new(ptr);
+                let vec_len = pv.vec.len();
+                let vec_cap = pv.vec.capacity();
+                let vec_ptr = pv.vec.as_mut_ptr() as *mut U;
+                mem::forget(pv);
+                Vec::from_raw_parts(vec_ptr, vec_len, vec_cap)
             }
-            self.cap = capacity;
+        } else {
+            // Put the `Vec` into the `PartialVecZeroSized` structure and
+            // prevent the destructor of the `Vec` from running. Since the
+            // `Vec` contained zero-sized objects, it did not allocate, so we
+            // are not leaking memory here.
+            let mut pv = PartialVecZeroSized::<T,U> {
+                num_t: vec.len(),
+                num_u: 0,
+                marker_t: InvariantType,
+                marker_u: InvariantType,
+            };
+            unsafe { mem::forget(vec); }
+
+            while pv.num_t != 0 {
+                unsafe {
+                    // Create a `T` out of thin air and decrement `num_t`. This
+                    // must not panic between these steps, as otherwise a
+                    // destructor of `T` which doesn't exist runs.
+                    let t = mem::uninitialized();
+                    pv.num_t -= 1;
+
+                    // The function given by the user might panic.
+                    let u = f(t);
+
+                    // Forget the `U` and increment `num_u`. This increment
+                    // cannot overflow the `uint` as we only do this for a
+                    // number of times that fits into a `uint` (and start with
+                    // `0`). Again, we should not panic between these steps.
+                    mem::forget(u);
+                    pv.num_u += 1;
+                }
+            }
+            // Create a `Vec` from our `PartialVecZeroSized` and make sure the
+            // destructor of the latter will not run. None of this can panic.
+            let mut result = Vec::new();
+            unsafe {
+                result.set_len(pv.num_u);
+                mem::forget(pv);
+            }
+            result
         }
     }
 }
 
+impl<T: Clone> Vec<T> {
+    /// Deprecated: use `repeat(value).take(length).collect()` instead.
+    #[inline]
+    #[deprecated = "use repeat(value).take(length).collect() instead"]
+    pub fn from_elem(length: uint, value: T) -> Vec<T> {
+        repeat(value).take(length).collect()
+    }
+
+    /// Resizes the `Vec` in-place so that `len()` is equal to `new_len`.
+    ///
+    /// Calls either `extend()` or `truncate()` depending on whether `new_len`
+    /// is larger than the current value of `len()` or not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut vec = vec!["hello"];
+    /// vec.resize(3, "world");
+    /// assert_eq!(vec, vec!["hello", "world", "world"]);
+    ///
+    /// let mut vec = vec![1i, 2, 3, 4];
+    /// vec.resize(2, 0);
+    /// assert_eq!(vec, vec![1, 2]);
+    /// ```
+    #[unstable = "matches collection reform specification; waiting for dust to settle"]
+    pub fn resize(&mut self, new_len: uint, value: T) {
+        let len = self.len();
+
+        if new_len > len {
+            self.extend(repeat(value).take(new_len - len));
+        } else {
+            self.truncate(new_len);
+        }
+    }
+
+    /// Appends all elements in a slice to the `Vec`.
+    ///
+    /// Iterates over the slice `other`, clones each element, and then appends
+    /// it to this `Vec`. The `other` vector is traversed in-order.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut vec = vec![1i];
+    /// vec.push_all(&[2i, 3, 4]);
+    /// assert_eq!(vec, vec![1, 2, 3, 4]);
+    /// ```
+    #[inline]
+    #[experimental = "likely to be replaced by a more optimized extend"]
+    pub fn push_all(&mut self, other: &[T]) {
+        self.reserve(other.len());
+
+        for i in range(0, other.len()) {
+            let len = self.len();
+
+            // Unsafe code so this can be optimised to a memcpy (or something similarly
+            // fast) when T is Copy. LLVM is easily confused, so any extra operations
+            // during the loop can prevent this optimisation.
+            unsafe {
+                ptr::write(
+                    self.get_unchecked_mut(len),
+                    other.get_unchecked(i).clone());
+                self.set_len(len + 1);
+            }
+        }
+    }
+
+    /// Deprecated: use `extend(repeat(value).take(n))` instead
+    #[deprecated = "use extend(repeat(value).take(n)) instead"]
+    pub fn grow(&mut self, n: uint, value: T) {
+        self.extend(repeat(value).take(n))
+    }
+
+    /// Deprecated: use `iter().cloned().partition(f)` instead.
+    #[deprecated = "use iter().cloned().partition(f) instead"]
+    pub fn partitioned<F>(&self, f: F) -> (Vec<T>, Vec<T>) where F: FnMut(&T) -> bool {
+        self.iter().cloned().partition(f)
+    }
+}
+
 impl<T: PartialEq> Vec<T> {
     /// Removes consecutive repeated elements in the vector.
     ///
@@ -1262,7 +1074,7 @@ impl<T: PartialEq> Vec<T> {
     ///
     /// assert_eq!(vec, vec![1i, 2, 3, 2]);
     /// ```
-    #[unstable = "this function may be renamed"]
+    #[stable]
     pub fn dedup(&mut self) {
         unsafe {
             // Although we have a mutable reference to `self`, we cannot make
@@ -1348,6 +1160,274 @@ impl<T: PartialEq> Vec<T> {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Public free fns
+////////////////////////////////////////////////////////////////////////////////
+
+/// Deprecated: use `unzip` directly on the iterator instead.
+#[deprecated = "use unzip directly on the iterator instead"]
+pub fn unzip<T, U, V: Iterator<(T, U)>>(iter: V) -> (Vec<T>, Vec<U>) {
+    iter.unzip()
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Internal methods and functions
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T> Vec<T> {
+    /// Reserves capacity for exactly `capacity` elements in the given vector.
+    ///
+    /// If the capacity for `self` is already equal to or greater than the
+    /// requested capacity, then no action is taken.
+    fn grow_capacity(&mut self, capacity: uint) {
+        if mem::size_of::<T>() == 0 { return }
+
+        if capacity > self.cap {
+            let size = capacity.checked_mul(mem::size_of::<T>())
+                               .expect("capacity overflow");
+            unsafe {
+                let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::<T>(), size);
+                if ptr.is_null() { ::alloc::oom() }
+                self.ptr = NonZero::new(ptr);
+            }
+            self.cap = capacity;
+        }
+    }
+}
+
+// FIXME: #13996: need a way to mark the return value as `noalias`
+#[inline(never)]
+unsafe fn alloc_or_realloc<T>(ptr: *mut T, old_size: uint, size: uint) -> *mut T {
+    if old_size == 0 {
+        allocate(size, mem::min_align_of::<T>()) as *mut T
+    } else {
+        reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::<T>()) as *mut T
+    }
+}
+
+#[inline]
+unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
+    if mem::size_of::<T>() != 0 {
+        deallocate(ptr as *mut u8,
+                   len * mem::size_of::<T>(),
+                   mem::min_align_of::<T>())
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Common trait implementations for Vec
+////////////////////////////////////////////////////////////////////////////////
+
+#[unstable]
+impl<T:Clone> Clone for Vec<T> {
+    fn clone(&self) -> Vec<T> { self.as_slice().to_vec() }
+
+    fn clone_from(&mut self, other: &Vec<T>) {
+        // drop anything in self that will not be overwritten
+        if self.len() > other.len() {
+            self.truncate(other.len())
+        }
+
+        // reuse the contained values' allocations/resources.
+        for (place, thing) in self.iter_mut().zip(other.iter()) {
+            place.clone_from(thing)
+        }
+
+        // self.len <= other.len due to the truncate above, so the
+        // slice here is always in-bounds.
+        let slice = other[self.len()..];
+        self.push_all(slice);
+    }
+}
+
+impl<S: hash::Writer, T: Hash<S>> Hash<S> for Vec<T> {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        self.as_slice().hash(state);
+    }
+}
+
+#[experimental = "waiting on Index stability"]
+impl<T> Index<uint,T> for Vec<T> {
+    #[inline]
+    fn index<'a>(&'a self, index: &uint) -> &'a T {
+        &self.as_slice()[*index]
+    }
+}
+
+impl<T> IndexMut<uint,T> for Vec<T> {
+    #[inline]
+    fn index_mut<'a>(&'a mut self, index: &uint) -> &'a mut T {
+        &mut self.as_mut_slice()[*index]
+    }
+}
+
+impl<T> ops::Slice<uint, [T]> for Vec<T> {
+    #[inline]
+    fn as_slice_<'a>(&'a self) -> &'a [T] {
+        self.as_slice()
+    }
+
+    #[inline]
+    fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] {
+        self.as_slice().slice_from_or_fail(start)
+    }
+
+    #[inline]
+    fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] {
+        self.as_slice().slice_to_or_fail(end)
+    }
+    #[inline]
+    fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
+        self.as_slice().slice_or_fail(start, end)
+    }
+}
+
+impl<T> ops::SliceMut<uint, [T]> for Vec<T> {
+    #[inline]
+    fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
+        self.as_mut_slice()
+    }
+
+    #[inline]
+    fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
+        self.as_mut_slice().slice_from_or_fail_mut(start)
+    }
+
+    #[inline]
+    fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
+        self.as_mut_slice().slice_to_or_fail_mut(end)
+    }
+    #[inline]
+    fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
+        self.as_mut_slice().slice_or_fail_mut(start, end)
+    }
+}
+
+#[experimental = "waiting on Deref stability"]
+impl<T> ops::Deref<[T]> for Vec<T> {
+    fn deref<'a>(&'a self) -> &'a [T] { self.as_slice() }
+}
+
+#[experimental = "waiting on DerefMut stability"]
+impl<T> ops::DerefMut<[T]> for Vec<T> {
+    fn deref_mut<'a>(&'a mut self) -> &'a mut [T] { self.as_mut_slice() }
+}
+
+#[experimental = "waiting on FromIterator stability"]
+impl<T> FromIterator<T> for Vec<T> {
+    #[inline]
+    fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
+        let (lower, _) = iterator.size_hint();
+        let mut vector = Vec::with_capacity(lower);
+        for element in iterator {
+            vector.push(element)
+        }
+        vector
+    }
+}
+
+#[experimental = "waiting on Extend stability"]
+impl<T> Extend<T> for Vec<T> {
+    #[inline]
+    fn extend<I: Iterator<T>>(&mut self, mut iterator: I) {
+        let (lower, _) = iterator.size_hint();
+        self.reserve(lower);
+        for element in iterator {
+            self.push(element)
+        }
+    }
+}
+
+impl<A, B> PartialEq<Vec<B>> for Vec<A> where A: PartialEq<B> {
+    #[inline]
+    fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
+    #[inline]
+    fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
+}
+
+macro_rules! impl_eq {
+    ($lhs:ty, $rhs:ty) => {
+        impl<'b, A, B> PartialEq<$rhs> for $lhs where A: PartialEq<B> {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
+            #[inline]
+            fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
+        }
+
+        impl<'b, A, B> PartialEq<$lhs> for $rhs where B: PartialEq<A> {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) }
+            #[inline]
+            fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) }
+        }
+    }
+}
+
+impl_eq! { Vec<A>, &'b [B] }
+impl_eq! { Vec<A>, &'b mut [B] }
+
+impl<'a, A, B> PartialEq<Vec<B>> for CowVec<'a, A> where A: PartialEq<B> + Clone {
+    #[inline]
+    fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
+    #[inline]
+    fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
+}
+
+impl<'a, A, B> PartialEq<CowVec<'a, A>> for Vec<B> where A: Clone, B: PartialEq<A> {
+    #[inline]
+    fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
+    #[inline]
+    fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
+}
+
+macro_rules! impl_eq_for_cowvec {
+    ($rhs:ty) => {
+        impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq<B> + Clone {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
+            #[inline]
+            fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
+        }
+
+        impl<'a, 'b, A, B> PartialEq<CowVec<'a, A>> for $rhs where A: Clone, B: PartialEq<A> {
+            #[inline]
+            fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
+            #[inline]
+            fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
+        }
+    }
+}
+
+impl_eq_for_cowvec! { &'b [B] }
+impl_eq_for_cowvec! { &'b mut [B] }
+
+#[unstable = "waiting on PartialOrd stability"]
+impl<T: PartialOrd> PartialOrd for Vec<T> {
+    #[inline]
+    fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
+        self.as_slice().partial_cmp(other.as_slice())
+    }
+}
+
+#[unstable = "waiting on Eq stability"]
+impl<T: Eq> Eq for Vec<T> {}
+
+#[allow(deprecated)]
+#[deprecated = "Use overloaded `core::cmp::PartialEq`"]
+impl<T: PartialEq, Sized? V: AsSlice<T>> Equiv<V> for Vec<T> {
+    #[inline]
+    fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
+}
+
+#[unstable = "waiting on Ord stability"]
+impl<T: Ord> Ord for Vec<T> {
+    #[inline]
+    fn cmp(&self, other: &Vec<T>) -> Ordering {
+        self.as_slice().cmp(other.as_slice())
+    }
+}
+
 impl<T> AsSlice<T> for Vec<T> {
     /// Returns a slice into `self`.
     ///
@@ -1410,7 +1490,45 @@ impl<T:fmt::Show> fmt::Show for Vec<T> {
     }
 }
 
+impl<'a> fmt::FormatWriter for Vec<u8> {
+    fn write(&mut self, buf: &[u8]) -> fmt::Result {
+        self.push_all(buf);
+        Ok(())
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Clone-on-write
+////////////////////////////////////////////////////////////////////////////////
+
+#[experimental = "unclear how valuable this alias is"]
+/// A clone-on-write vector
+pub type CowVec<'a, T> = Cow<'a, Vec<T>, [T]>;
+
+impl<'a, T> FromIterator<T> for CowVec<'a, T> where T: Clone {
+    fn from_iter<I: Iterator<T>>(it: I) -> CowVec<'a, T> {
+        Cow::Owned(FromIterator::from_iter(it))
+    }
+}
+
+impl<'a, T: 'a> IntoCow<'a, Vec<T>, [T]> for Vec<T> where T: Clone {
+    fn into_cow(self) -> CowVec<'a, T> {
+        Cow::Owned(self)
+    }
+}
+
+impl<'a, T> IntoCow<'a, Vec<T>, [T]> for &'a [T] where T: Clone {
+    fn into_cow(self) -> CowVec<'a, T> {
+        Cow::Borrowed(self)
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Iterators
+////////////////////////////////////////////////////////////////////////////////
+
 /// An iterator that moves out of a vector.
+#[stable]
 pub struct IntoIter<T> {
     allocation: *mut T, // the block of memory allocated for the vector
     cap: uint, // the capacity of the vector
@@ -1418,9 +1536,12 @@ pub struct IntoIter<T> {
     end: *const T
 }
 
+#[deprecated = "use IntoIter instead"]
+pub type MoveItems<T> = IntoIter<T>;
+
 impl<T> IntoIter<T> {
-    /// Drops all items that have not yet been moved and returns the empty vector.
     #[inline]
+    /// Drops all items that have not yet been moved and returns the empty vector.
     #[unstable]
     pub fn into_inner(mut self) -> Vec<T> {
         unsafe {
@@ -1510,6 +1631,7 @@ impl<T> Drop for IntoIter<T> {
 
 /// An iterator that drains a vector.
 #[unsafe_no_drop_flag]
+#[unstable = "recently added as part of collections reform 2"]
 pub struct Drain<'a, T> {
     ptr: *const T,
     end: *const T,
@@ -1586,22 +1708,9 @@ impl<'a, T> Drop for Drain<'a, T> {
     }
 }
 
-/// Converts an iterator of pairs into a pair of vectors.
-///
-/// Returns a tuple containing two vectors where the i-th element of the first vector contains the
-/// first element of the i-th tuple of the input iterator, and the i-th element of the second
-/// vector contains the second element of the i-th tuple of the input iterator.
-#[unstable = "this functionality may become more generic over time"]
-pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
-    let (lo, _) = iter.size_hint();
-    let mut ts = Vec::with_capacity(lo);
-    let mut us = Vec::with_capacity(lo);
-    for (t, u) in iter {
-        ts.push(t);
-        us.push(u);
-    }
-    (ts, us)
-}
+////////////////////////////////////////////////////////////////////////////////
+// Conversion from &[T] to &Vec<T>
+////////////////////////////////////////////////////////////////////////////////
 
 /// Wrapper type providing a `&Vec<T>` reference via `Deref`.
 #[experimental]
@@ -1610,6 +1719,7 @@ pub struct DerefVec<'a, T> {
     l: ContravariantLifetime<'a>
 }
 
+#[experimental]
 impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> {
     fn deref<'b>(&'b self) -> &'b Vec<T> {
         &self.x
@@ -1618,6 +1728,7 @@ impl<'a, T> Deref<Vec<T>> for DerefVec<'a, T> {
 
 // Prevent the inner `Vec<T>` from attempting to deallocate memory.
 #[unsafe_destructor]
+#[experimental]
 impl<'a, T> Drop for DerefVec<'a, T> {
     fn drop(&mut self) {
         self.x.len = 0;
@@ -1636,6 +1747,10 @@ pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Raw module (deprecated)
+////////////////////////////////////////////////////////////////////////////////
+
 /// Unsafe vector operations.
 #[deprecated]
 pub mod raw {
@@ -1652,6 +1767,10 @@ pub mod raw {
     }
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// Partial vec, used for map_in_place
+////////////////////////////////////////////////////////////////////////////////
+
 /// An owned, partially type-converted vector of elements with non-zero size.
 ///
 /// `T` and `U` must have the same, non-zero size. They must also have the same
@@ -1723,211 +1842,6 @@ impl<T,U> Drop for PartialVecZeroSized<T,U> {
     }
 }
 
-impl<T> Vec<T> {
-    /// Converts a `Vec<T>` to a `Vec<U>` where `T` and `U` have the same
-    /// size and in case they are not zero-sized the same minimal alignment.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `T` and `U` have differing sizes or are not zero-sized and
-    /// have differing minimal alignments.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// let v = vec![0u, 1, 2];
-    /// let w = v.map_in_place(|i| i + 3);
-    /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice());
-    ///
-    /// #[deriving(PartialEq, Show)]
-    /// struct Newtype(u8);
-    /// let bytes = vec![0x11, 0x22];
-    /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
-    /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice());
-    /// ```
-    pub fn map_in_place<U, F>(self, mut f: F) -> Vec<U> where F: FnMut(T) -> U {
-        // FIXME: Assert statically that the types `T` and `U` have the same
-        // size.
-        assert!(mem::size_of::<T>() == mem::size_of::<U>());
-
-        let mut vec = self;
-
-        if mem::size_of::<T>() != 0 {
-            // FIXME: Assert statically that the types `T` and `U` have the
-            // same minimal alignment in case they are not zero-sized.
-
-            // These asserts are necessary because the `min_align_of` of the
-            // types are passed to the allocator by `Vec`.
-            assert!(mem::min_align_of::<T>() == mem::min_align_of::<U>());
-
-            // This `as int` cast is safe, because the size of the elements of the
-            // vector is not 0, and:
-            //
-            // 1) If the size of the elements in the vector is 1, the `int` may
-            //    overflow, but it has the correct bit pattern so that the
-            //    `.offset()` function will work.
-            //
-            //    Example:
-            //        Address space 0x0-0xF.
-            //        `u8` array at: 0x1.
-            //        Size of `u8` array: 0x8.
-            //        Calculated `offset`: -0x8.
-            //        After `array.offset(offset)`: 0x9.
-            //        (0x1 + 0x8 = 0x1 - 0x8)
-            //
-            // 2) If the size of the elements in the vector is >1, the `uint` ->
-            //    `int` conversion can't overflow.
-            let offset = vec.len() as int;
-            let start = vec.as_mut_ptr();
-
-            let mut pv = PartialVecNonZeroSized {
-                vec: vec,
-
-                start_t: start,
-                // This points inside the vector, as the vector has length
-                // `offset`.
-                end_t: unsafe { start.offset(offset) },
-                start_u: start as *mut U,
-                end_u: start as *mut U,
-            };
-            //  start_t
-            //  start_u
-            //  |
-            // +-+-+-+-+-+-+
-            // |T|T|T|...|T|
-            // +-+-+-+-+-+-+
-            //  |           |
-            //  end_u       end_t
-
-            while pv.end_u as *mut T != pv.end_t {
-                unsafe {
-                    //  start_u start_t
-                    //  |       |
-                    // +-+-+-+-+-+-+-+-+-+
-                    // |U|...|U|T|T|...|T|
-                    // +-+-+-+-+-+-+-+-+-+
-                    //          |         |
-                    //          end_u     end_t
-
-                    let t = ptr::read(pv.start_t as *const T);
-                    //  start_u start_t
-                    //  |       |
-                    // +-+-+-+-+-+-+-+-+-+
-                    // |U|...|U|X|T|...|T|
-                    // +-+-+-+-+-+-+-+-+-+
-                    //          |         |
-                    //          end_u     end_t
-                    // We must not panic here, one cell is marked as `T`
-                    // although it is not `T`.
-
-                    pv.start_t = pv.start_t.offset(1);
-                    //  start_u   start_t
-                    //  |         |
-                    // +-+-+-+-+-+-+-+-+-+
-                    // |U|...|U|X|T|...|T|
-                    // +-+-+-+-+-+-+-+-+-+
-                    //          |         |
-                    //          end_u     end_t
-                    // We may panic again.
-
-                    // The function given by the user might panic.
-                    let u = f(t);
-
-                    ptr::write(pv.end_u, u);
-                    //  start_u   start_t
-                    //  |         |
-                    // +-+-+-+-+-+-+-+-+-+
-                    // |U|...|U|U|T|...|T|
-                    // +-+-+-+-+-+-+-+-+-+
-                    //          |         |
-                    //          end_u     end_t
-                    // We should not panic here, because that would leak the `U`
-                    // pointed to by `end_u`.
-
-                    pv.end_u = pv.end_u.offset(1);
-                    //  start_u   start_t
-                    //  |         |
-                    // +-+-+-+-+-+-+-+-+-+
-                    // |U|...|U|U|T|...|T|
-                    // +-+-+-+-+-+-+-+-+-+
-                    //            |       |
-                    //            end_u   end_t
-                    // We may panic again.
-                }
-            }
-
-            //  start_u     start_t
-            //  |           |
-            // +-+-+-+-+-+-+
-            // |U|...|U|U|U|
-            // +-+-+-+-+-+-+
-            //              |
-            //              end_t
-            //              end_u
-            // Extract `vec` and prevent the destructor of
-            // `PartialVecNonZeroSized` from running. Note that none of the
-            // function calls can panic, thus no resources can be leaked (as the
-            // `vec` member of `PartialVec` is the only one which holds
-            // allocations -- and it is returned from this function. None of
-            // this can panic.
-            unsafe {
-                let vec_len = pv.vec.len();
-                let vec_cap = pv.vec.capacity();
-                let vec_ptr = pv.vec.as_mut_ptr() as *mut U;
-                mem::forget(pv);
-                Vec::from_raw_parts(vec_ptr, vec_len, vec_cap)
-            }
-        } else {
-            // Put the `Vec` into the `PartialVecZeroSized` structure and
-            // prevent the destructor of the `Vec` from running. Since the
-            // `Vec` contained zero-sized objects, it did not allocate, so we
-            // are not leaking memory here.
-            let mut pv = PartialVecZeroSized::<T,U> {
-                num_t: vec.len(),
-                num_u: 0,
-                marker_t: InvariantType,
-                marker_u: InvariantType,
-            };
-            unsafe { mem::forget(vec); }
-
-            while pv.num_t != 0 {
-                unsafe {
-                    // Create a `T` out of thin air and decrement `num_t`. This
-                    // must not panic between these steps, as otherwise a
-                    // destructor of `T` which doesn't exist runs.
-                    let t = mem::uninitialized();
-                    pv.num_t -= 1;
-
-                    // The function given by the user might panic.
-                    let u = f(t);
-
-                    // Forget the `U` and increment `num_u`. This increment
-                    // cannot overflow the `uint` as we only do this for a
-                    // number of times that fits into a `uint` (and start with
-                    // `0`). Again, we should not panic between these steps.
-                    mem::forget(u);
-                    pv.num_u += 1;
-                }
-            }
-            // Create a `Vec` from our `PartialVecZeroSized` and make sure the
-            // destructor of the latter will not run. None of this can panic.
-            let mut result = Vec::new();
-            unsafe {
-                result.set_len(pv.num_u);
-                mem::forget(pv);
-            }
-            result
-        }
-    }
-}
-
-impl<'a> fmt::FormatWriter for Vec<u8> {
-    fn write(&mut self, buf: &[u8]) -> fmt::Result {
-        self.push_all(buf);
-        Ok(())
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use prelude::*;
@@ -2295,9 +2209,10 @@ mod tests {
     }
 
     #[test]
+    #[should_fail]
     fn test_swap_remove_empty() {
         let mut vec: Vec<uint> = vec!();
-        assert_eq!(vec.swap_remove(0), None);
+        vec.swap_remove(0);
     }
 
     #[test]
diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs
index 063366c8d9c..172fd56ed39 100644
--- a/src/libcollections/vec_map.rs
+++ b/src/libcollections/vec_map.rs
@@ -107,7 +107,7 @@ impl<V> VecMap<V> {
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::new();
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> VecMap<V> { VecMap { v: vec![] } }
 
     /// Creates an empty `VecMap` with space for at least `capacity`
@@ -119,7 +119,7 @@ impl<V> VecMap<V> {
     /// use std::collections::VecMap;
     /// let mut map: VecMap<&str> = VecMap::with_capacity(10);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn with_capacity(capacity: uint) -> VecMap<V> {
         VecMap { v: Vec::with_capacity(capacity) }
     }
@@ -135,7 +135,7 @@ impl<V> VecMap<V> {
     /// assert!(map.capacity() >= 10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint {
         self.v.capacity()
     }
@@ -154,7 +154,7 @@ impl<V> VecMap<V> {
     /// map.reserve_len(10);
     /// assert!(map.capacity() >= 10);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_len(&mut self, len: uint) {
         let cur_len = self.v.len();
         if len >= cur_len {
@@ -178,7 +178,7 @@ impl<V> VecMap<V> {
     /// map.reserve_len_exact(10);
     /// assert!(map.capacity() >= 10);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve_len_exact(&mut self, len: uint) {
         let cur_len = self.v.len();
         if len >= cur_len {
@@ -188,7 +188,7 @@ impl<V> VecMap<V> {
 
     /// Returns an iterator visiting all keys in ascending order by the keys.
     /// The iterator's element type is `uint`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn keys<'r>(&'r self) -> Keys<'r, V> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((uint, &'r V)) -> uint = first; // coerce to fn pointer
@@ -198,7 +198,7 @@ impl<V> VecMap<V> {
 
     /// Returns an iterator visiting all values in ascending order by the keys.
     /// The iterator's element type is `&'r V`.
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn values<'r>(&'r self) -> Values<'r, V> {
         fn second<A, B>((_, b): (A, B)) -> B { b }
         let second: fn((uint, &'r V)) -> &'r V = second; // coerce to fn pointer
@@ -224,7 +224,7 @@ impl<V> VecMap<V> {
     ///     println!("{}: {}", key, value);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn iter<'r>(&'r self) -> Iter<'r, V> {
         Iter {
             front: 0,
@@ -255,7 +255,7 @@ impl<V> VecMap<V> {
     ///     assert_eq!(value, &"x");
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn iter_mut<'r>(&'r mut self) -> IterMut<'r, V> {
         IterMut {
             front: 0,
@@ -283,7 +283,7 @@ impl<V> VecMap<V> {
     ///
     /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(&mut self) -> IntoIter<V> {
         fn filter<A>((i, v): (uint, Option<A>)) -> Option<(uint, A)> {
             v.map(|v| (i, v))
@@ -306,7 +306,7 @@ impl<V> VecMap<V> {
     /// a.insert(1, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint {
         self.v.iter().filter(|elt| elt.is_some()).count()
     }
@@ -323,7 +323,7 @@ impl<V> VecMap<V> {
     /// a.insert(1, "a");
     /// assert!(!a.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool {
         self.v.iter().all(|elt| elt.is_none())
     }
@@ -340,7 +340,7 @@ impl<V> VecMap<V> {
     /// a.clear();
     /// assert!(a.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) { self.v.clear() }
 
     /// Deprecated: Renamed to `get`.
@@ -361,7 +361,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.get(&1), Some(&"a"));
     /// assert_eq!(map.get(&2), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get(&self, key: &uint) -> Option<&V> {
         if *key < self.v.len() {
             match self.v[*key] {
@@ -386,7 +386,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn contains_key(&self, key: &uint) -> bool {
         self.get(key).is_some()
     }
@@ -412,7 +412,7 @@ impl<V> VecMap<V> {
     /// }
     /// assert_eq!(map[1], "b");
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get_mut(&mut self, key: &uint) -> Option<&mut V> {
         if *key < self.v.len() {
             match *(&mut self.v[*key]) {
@@ -446,11 +446,11 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.insert(37, "c"), Some("b"));
     /// assert_eq!(map[37], "c");
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn insert(&mut self, key: uint, value: V) -> Option<V> {
         let len = self.v.len();
         if len <= key {
-            self.v.grow_fn(key - len + 1, |_| None);
+            self.v.extend(range(0, key - len + 1).map(|_| None));
         }
         replace(&mut self.v[key], Some(value))
     }
@@ -474,7 +474,7 @@ impl<V> VecMap<V> {
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn remove(&mut self, key: &uint) -> Option<V> {
         if *key >= self.v.len() {
             return None;
@@ -484,50 +484,15 @@ impl<V> VecMap<V> {
 }
 
 impl<V:Clone> VecMap<V> {
-    /// Updates a value in the map. If the key already exists in the map,
-    /// modifies the value with `ff` taking `oldval, newval`.
-    /// Otherwise, sets the value to `newval`.
-    /// Returns `true` if the key did not already exist in the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::VecMap;
-    ///
-    /// let mut map = VecMap::new();
-    ///
-    /// // Key does not exist, will do a simple insert
-    /// assert!(map.update(1, vec![1i, 2], |mut old, new| { old.extend(new.into_iter()); old }));
-    /// assert_eq!(map[1], vec![1i, 2]);
-    ///
-    /// // Key exists, update the value
-    /// assert!(!map.update(1, vec![3i, 4], |mut old, new| { old.extend(new.into_iter()); old }));
-    /// assert_eq!(map[1], vec![1i, 2, 3, 4]);
-    /// ```
+    /// Deprecated: Use the entry API when available; shouldn't matter anyway, access is cheap.
+    #[deprecated = "Use the entry API when available; shouldn't matter anyway, access is cheap"]
+    #[allow(deprecated)]
     pub fn update<F>(&mut self, key: uint, newval: V, ff: F) -> bool where F: FnOnce(V, V) -> V {
         self.update_with_key(key, newval, move |_k, v, v1| ff(v,v1))
     }
 
-    /// Updates a value in the map. If the key already exists in the map,
-    /// modifies the value with `ff` taking `key, oldval, newval`.
-    /// Otherwise, sets the value to `newval`.
-    /// Returns `true` if the key did not already exist in the map.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::VecMap;
-    ///
-    /// let mut map = VecMap::new();
-    ///
-    /// // Key does not exist, will do a simple insert
-    /// assert!(map.update_with_key(7, 10, |key, old, new| (old + new) % key));
-    /// assert_eq!(map[7], 10);
-    ///
-    /// // Key exists, update the value
-    /// assert!(!map.update_with_key(7, 20, |key, old, new| (old + new) % key));
-    /// assert_eq!(map[7], 2);
-    /// ```
+    /// Deprecated: Use the entry API when available; shouldn't matter anyway, access is cheap.
+    #[deprecated = "Use the entry API when available; shouldn't matter anyway, access is cheap"]
     pub fn update_with_key<F>(&mut self, key: uint, val: V, ff: F) -> bool where
         F: FnOnce(uint, V, V) -> V
     {
@@ -539,14 +504,17 @@ impl<V:Clone> VecMap<V> {
     }
 }
 
+#[stable]
 impl<V: PartialEq> PartialEq for VecMap<V> {
     fn eq(&self, other: &VecMap<V>) -> bool {
         iter::order::eq(self.iter(), other.iter())
     }
 }
 
+#[stable]
 impl<V: Eq> Eq for VecMap<V> {}
 
+#[stable]
 impl<V: PartialOrd> PartialOrd for VecMap<V> {
     #[inline]
     fn partial_cmp(&self, other: &VecMap<V>) -> Option<Ordering> {
@@ -554,6 +522,7 @@ impl<V: PartialOrd> PartialOrd for VecMap<V> {
     }
 }
 
+#[stable]
 impl<V: Ord> Ord for VecMap<V> {
     #[inline]
     fn cmp(&self, other: &VecMap<V>) -> Ordering {
@@ -561,6 +530,7 @@ impl<V: Ord> Ord for VecMap<V> {
     }
 }
 
+#[stable]
 impl<V: fmt::Show> fmt::Show for VecMap<V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "{{"));
@@ -574,6 +544,7 @@ impl<V: fmt::Show> fmt::Show for VecMap<V> {
     }
 }
 
+#[stable]
 impl<V> FromIterator<(uint, V)> for VecMap<V> {
     fn from_iter<Iter: Iterator<(uint, V)>>(iter: Iter) -> VecMap<V> {
         let mut map = VecMap::new();
@@ -582,6 +553,7 @@ impl<V> FromIterator<(uint, V)> for VecMap<V> {
     }
 }
 
+#[stable]
 impl<V> Extend<(uint, V)> for VecMap<V> {
     fn extend<Iter: Iterator<(uint, V)>>(&mut self, mut iter: Iter) {
         for (k, v) in iter {
@@ -590,6 +562,7 @@ impl<V> Extend<(uint, V)> for VecMap<V> {
     }
 }
 
+#[stable]
 impl<V> Index<uint, V> for VecMap<V> {
     #[inline]
     fn index<'a>(&'a self, i: &uint) -> &'a V {
@@ -597,6 +570,7 @@ impl<V> Index<uint, V> for VecMap<V> {
     }
 }
 
+#[stable]
 impl<V> IndexMut<uint, V> for VecMap<V> {
     #[inline]
     fn index_mut<'a>(&'a mut self, i: &uint) -> &'a mut V {
@@ -606,6 +580,7 @@ impl<V> IndexMut<uint, V> for VecMap<V> {
 
 macro_rules! iterator {
     (impl $name:ident -> $elem:ty, $($getter:ident),+) => {
+        #[stable]
         impl<'a, V> Iterator<$elem> for $name<'a, V> {
             #[inline]
             fn next(&mut self) -> Option<$elem> {
@@ -638,6 +613,7 @@ macro_rules! iterator {
 
 macro_rules! double_ended_iterator {
     (impl $name:ident -> $elem:ty, $($getter:ident),+) => {
+        #[stable]
         impl<'a, V> DoubleEndedIterator<$elem> for $name<'a, V> {
             #[inline]
             fn next_back(&mut self) -> Option<$elem> {
@@ -663,17 +639,30 @@ macro_rules! double_ended_iterator {
 }
 
 /// An iterator over the key-value pairs of a map.
+#[stable]
 pub struct Iter<'a, V:'a> {
     front: uint,
     back: uint,
     iter: slice::Iter<'a, Option<V>>
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, V> Clone for Iter<'a, V> {
+    fn clone(&self) -> Iter<'a, V> {
+        Iter {
+            front: self.front,
+            back: self.back,
+            iter: self.iter.clone()
+        }
+    }
+}
+
 iterator! { impl Iter -> (uint, &'a V), as_ref }
 double_ended_iterator! { impl Iter -> (uint, &'a V), as_ref }
 
 /// An iterator over the key-value pairs of a map, with the
 /// values being mutable.
+#[stable]
 pub struct IterMut<'a, V:'a> {
     front: uint,
     back: uint,
@@ -684,16 +673,37 @@ iterator! { impl IterMut -> (uint, &'a mut V), as_mut }
 double_ended_iterator! { impl IterMut -> (uint, &'a mut V), as_mut }
 
 /// An iterator over the keys of a map.
+#[stable]
 pub struct Keys<'a, V: 'a> {
     iter: Map<(uint, &'a V), uint, Iter<'a, V>, fn((uint, &'a V)) -> uint>
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, V> Clone for Keys<'a, V> {
+    fn clone(&self) -> Keys<'a, V> {
+        Keys {
+            iter: self.iter.clone()
+        }
+    }
+}
+
 /// An iterator over the values of a map.
+#[stable]
 pub struct Values<'a, V: 'a> {
     iter: Map<(uint, &'a V), &'a V, Iter<'a, V>, fn((uint, &'a V)) -> &'a V>
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, V> Clone for Values<'a, V> {
+    fn clone(&self) -> Values<'a, V> {
+        Values {
+            iter: self.iter.clone()
+        }
+    }
+}
+
 /// A consuming iterator over the key-value pairs of a map.
+#[stable]
 pub struct IntoIter<V> {
     iter: FilterMap<
     (uint, Option<V>),
@@ -702,28 +712,32 @@ pub struct IntoIter<V> {
     fn((uint, Option<V>)) -> Option<(uint, V)>>
 }
 
+#[stable]
 impl<'a, V> Iterator<uint> for Keys<'a, V> {
     fn next(&mut self) -> Option<uint> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
+#[stable]
 impl<'a, V> DoubleEndedIterator<uint> for Keys<'a, V> {
     fn next_back(&mut self) -> Option<uint> { self.iter.next_back() }
 }
 
-
+#[stable]
 impl<'a, V> Iterator<&'a V> for Values<'a, V> {
     fn next(&mut self) -> Option<(&'a V)> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
+#[stable]
 impl<'a, V> DoubleEndedIterator<&'a V> for Values<'a, V> {
     fn next_back(&mut self) -> Option<(&'a V)> { self.iter.next_back() }
 }
 
-
+#[stable]
 impl<V> Iterator<(uint, V)> for IntoIter<V> {
     fn next(&mut self) -> Option<(uint, V)> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
+#[stable]
 impl<V> DoubleEndedIterator<(uint, V)> for IntoIter<V> {
     fn next_back(&mut self) -> Option<(uint, V)> { self.iter.next_back() }
 }
diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index e85a132ed36..28563a60b61 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array.rs
@@ -26,32 +26,33 @@ macro_rules! array_impls {
     ($($N:expr)+) => {
         $(
             #[stable]
-            impl<T:Copy> Clone for [T, ..$N] {
-                fn clone(&self) -> [T, ..$N] {
+            impl<T:Copy> Clone for [T; $N] {
+                fn clone(&self) -> [T; $N] {
                     *self
                 }
             }
 
             #[unstable = "waiting for Show to stabilize"]
-            impl<T:fmt::Show> fmt::Show for [T, ..$N] {
+            impl<T:fmt::Show> fmt::Show for [T; $N] {
                 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                     fmt::Show::fmt(&self[], f)
                 }
             }
 
-            #[unstable = "waiting for PartialEq to stabilize"]
-            impl<A, B> PartialEq<[B, ..$N]> for [A, ..$N] where A: PartialEq<B> {
+            #[stable]
+            impl<A, B> PartialEq<[B; $N]> for [A; $N] where A: PartialEq<B> {
                 #[inline]
-                fn eq(&self, other: &[B, ..$N]) -> bool {
+                fn eq(&self, other: &[B; $N]) -> bool {
                     self[] == other[]
                 }
                 #[inline]
-                fn ne(&self, other: &[B, ..$N]) -> bool {
+                fn ne(&self, other: &[B; $N]) -> bool {
                     self[] != other[]
                 }
             }
 
-            impl<'a, A, B, Rhs> PartialEq<Rhs> for [A, ..$N] where
+            #[stable]
+            impl<'a, A, B, Rhs> PartialEq<Rhs> for [A; $N] where
                 A: PartialEq<B>,
                 Rhs: Deref<[B]>,
             {
@@ -61,47 +62,48 @@ macro_rules! array_impls {
                 fn ne(&self, other: &Rhs) -> bool { PartialEq::ne(self[], &**other) }
             }
 
-            impl<'a, A, B, Lhs> PartialEq<[B, ..$N]> for Lhs where
+            #[stable]
+            impl<'a, A, B, Lhs> PartialEq<[B; $N]> for Lhs where
                 A: PartialEq<B>,
                 Lhs: Deref<[A]>
             {
                 #[inline(always)]
-                fn eq(&self, other: &[B, ..$N]) -> bool { PartialEq::eq(&**self, other[]) }
+                fn eq(&self, other: &[B; $N]) -> bool { PartialEq::eq(&**self, other[]) }
                 #[inline(always)]
-                fn ne(&self, other: &[B, ..$N]) -> bool { PartialEq::ne(&**self, other[]) }
+                fn ne(&self, other: &[B; $N]) -> bool { PartialEq::ne(&**self, other[]) }
             }
 
-            #[unstable = "waiting for Eq to stabilize"]
-            impl<T:Eq> Eq for [T, ..$N] { }
+            #[stable]
+            impl<T:Eq> Eq for [T; $N] { }
 
-            #[unstable = "waiting for PartialOrd to stabilize"]
-            impl<T:PartialOrd> PartialOrd for [T, ..$N] {
+            #[stable]
+            impl<T:PartialOrd> PartialOrd for [T; $N] {
                 #[inline]
-                fn partial_cmp(&self, other: &[T, ..$N]) -> Option<Ordering> {
+                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                     PartialOrd::partial_cmp(&self[], &other[])
                 }
                 #[inline]
-                fn lt(&self, other: &[T, ..$N]) -> bool {
+                fn lt(&self, other: &[T; $N]) -> bool {
                     PartialOrd::lt(&self[], &other[])
                 }
                 #[inline]
-                fn le(&self, other: &[T, ..$N]) -> bool {
+                fn le(&self, other: &[T; $N]) -> bool {
                     PartialOrd::le(&self[], &other[])
                 }
                 #[inline]
-                fn ge(&self, other: &[T, ..$N]) -> bool {
+                fn ge(&self, other: &[T; $N]) -> bool {
                     PartialOrd::ge(&self[], &other[])
                 }
                 #[inline]
-                fn gt(&self, other: &[T, ..$N]) -> bool {
+                fn gt(&self, other: &[T; $N]) -> bool {
                     PartialOrd::gt(&self[], &other[])
                 }
             }
 
-            #[unstable = "waiting for Ord to stabilize"]
-            impl<T:Ord> Ord for [T, ..$N] {
+            #[stable]
+            impl<T:Ord> Ord for [T; $N] {
                 #[inline]
-                fn cmp(&self, other: &[T, ..$N]) -> Ordering {
+                fn cmp(&self, other: &[T; $N]) -> Ordering {
                     Ord::cmp(&self[], &other[])
                 }
             }
diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs
index 9452d0a64bf..6a40915f4dd 100644
--- a/src/libcore/atomic.rs
+++ b/src/libcore/atomic.rs
@@ -12,7 +12,7 @@
 
 #![stable]
 
-pub use self::Ordering::*;
+use self::Ordering::*;
 
 use kinds::Sync;
 
diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs
index 9bbcf67773e..3a2cb8ea7d9 100644
--- a/src/libcore/borrow.rs
+++ b/src/libcore/borrow.rs
@@ -200,8 +200,10 @@ impl<'a, T, Sized? B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T>  {
     }
 }
 
+#[stable]
 impl<'a, T, Sized? B> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}
 
+#[stable]
 impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
     #[inline]
     fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
@@ -209,6 +211,7 @@ impl<'a, T, Sized? B> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
     }
 }
 
+#[stable]
 impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
     B: PartialEq<C> + ToOwned<T>,
     C: ToOwned<U>,
@@ -219,6 +222,7 @@ impl<'a, 'b, T, U, Sized? B, Sized? C> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B
     }
 }
 
+#[stable]
 impl<'a, T, Sized? B> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
     #[inline]
     fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index b45424a5eed..4b246860006 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -158,7 +158,8 @@
 use clone::Clone;
 use cmp::PartialEq;
 use default::Default;
-use kinds::{marker, Copy};
+use fmt;
+use kinds::{Copy, Send};
 use ops::{Deref, DerefMut, Drop};
 use option::Option;
 use option::Option::{None, Some};
@@ -167,7 +168,6 @@ use option::Option::{None, Some};
 #[stable]
 pub struct Cell<T> {
     value: UnsafeCell<T>,
-    noshare: marker::NoSync,
 }
 
 impl<T:Copy> Cell<T> {
@@ -176,7 +176,6 @@ impl<T:Copy> Cell<T> {
     pub fn new(value: T) -> Cell<T> {
         Cell {
             value: UnsafeCell::new(value),
-            noshare: marker::NoSync,
         }
     }
 
@@ -209,6 +208,9 @@ impl<T:Copy> Cell<T> {
 }
 
 #[stable]
+unsafe impl<T> Send for Cell<T> where T: Send {}
+
+#[stable]
 impl<T:Copy> Clone for Cell<T> {
     fn clone(&self) -> Cell<T> {
         Cell::new(self.get())
@@ -223,7 +225,7 @@ impl<T:Default + Copy> Default for Cell<T> {
     }
 }
 
-#[unstable = "waiting for `PartialEq` trait to become stable"]
+#[stable]
 impl<T:PartialEq + Copy> PartialEq for Cell<T> {
     fn eq(&self, other: &Cell<T>) -> bool {
         self.get() == other.get()
@@ -235,7 +237,6 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
 pub struct RefCell<T> {
     value: UnsafeCell<T>,
     borrow: Cell<BorrowFlag>,
-    noshare: marker::NoSync,
 }
 
 // Values [1, MAX-1] represent the number of `Ref` active
@@ -251,7 +252,6 @@ impl<T> RefCell<T> {
         RefCell {
             value: UnsafeCell::new(value),
             borrow: Cell::new(UNUSED),
-            noshare: marker::NoSync,
         }
     }
 
@@ -342,6 +342,9 @@ impl<T> RefCell<T> {
 }
 
 #[stable]
+unsafe impl<T> Send for RefCell<T> where T: Send {}
+
+#[stable]
 impl<T: Clone> Clone for RefCell<T> {
     fn clone(&self) -> RefCell<T> {
         RefCell::new(self.borrow().clone())
@@ -356,13 +359,23 @@ impl<T:Default> Default for RefCell<T> {
     }
 }
 
-#[unstable = "waiting for `PartialEq` to become stable"]
+#[stable]
 impl<T: PartialEq> PartialEq for RefCell<T> {
     fn eq(&self, other: &RefCell<T>) -> bool {
         *self.borrow() == *other.borrow()
     }
 }
 
+#[unstable]
+impl<T:fmt::Show> fmt::Show for RefCell<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.try_borrow() {
+            Some(val) => write!(f, "{}", val),
+            None => write!(f, "<borrowed RefCell>")
+        }
+    }
+}
+
 struct BorrowRef<'b> {
     _borrow: &'b Cell<BorrowFlag>,
 }
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index 9c12b3f68d3..f0151dda8d7 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -430,11 +430,13 @@ impl Char for char {
 
 /// An iterator over the characters that represent a `char`, as escaped by
 /// Rust's unicode escaping rules.
+#[deriving(Clone)]
 pub struct EscapeUnicode {
     c: char,
     state: EscapeUnicodeState
 }
 
+#[deriving(Clone)]
 enum EscapeUnicodeState {
     Backslash,
     Type,
@@ -486,10 +488,12 @@ impl Iterator<char> for EscapeUnicode {
 
 /// An iterator over the characters that represent a `char`, escaped
 /// for maximum portability.
+#[deriving(Clone)]
 pub struct EscapeDefault {
     state: EscapeDefaultState
 }
 
+#[deriving(Clone)]
 enum EscapeDefaultState {
     Backslash(char),
     Char(char),
@@ -513,4 +517,3 @@ impl Iterator<char> for EscapeDefault {
         }
     }
 }
-
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index 686ccf6f1a2..5d84d0c7797 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -36,7 +36,7 @@ pub trait Clone {
     /// but can be overridden to reuse the resources of `a` to avoid unnecessary
     /// allocations.
     #[inline(always)]
-    #[unstable = "this function rarely unused"]
+    #[unstable = "this function is rarely used"]
     fn clone_from(&mut self, source: &Self) {
         *self = source.clone()
     }
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 4d72fb8ac92..38906892a33 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -46,27 +46,37 @@ use self::Ordering::*;
 use kinds::Sized;
 use option::Option::{mod, Some, None};
 
-/// Trait for values that can be compared for equality and inequality.
+/// Trait for equality comparisons which are [partial equivalence relations](
+/// http://en.wikipedia.org/wiki/Partial_equivalence_relation).
 ///
-/// This trait allows for partial equality, for types that do not have an
+/// This trait allows for partial equality, for types that do not have a full
 /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
 /// so floating point types implement `PartialEq` but not `Eq`.
 ///
+/// Formally, the equality must be (for all `a`, `b` and `c`):
+///
+/// - symmetric: `a == b` implies `b == a`; and
+/// - transitive: `a == b` and `b == c` implies `a == c`.
+///
+/// Note that these requirements mean that the trait itself must be
+/// implemented symmetrically and transitively: if `T: PartialEq<U>`
+/// and `U: PartialEq<V>` then `U: PartialEq<T>` and `T:
+/// PartialEq<V>`.
+///
 /// PartialEq only requires the `eq` method to be implemented; `ne` is defined
 /// in terms of it by default. Any manual implementation of `ne` *must* respect
 /// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
 /// only if `a != b`.
-///
-/// Eventually, this will be implemented by default for types that implement
-/// `Eq`.
 #[lang="eq"]
-#[unstable = "Definition may change slightly after trait reform"]
+#[stable]
 pub trait PartialEq<Sized? Rhs = Self> for Sized? {
     /// This method tests for `self` and `other` values to be equal, and is used by `==`.
+    #[stable]
     fn eq(&self, other: &Rhs) -> bool;
 
     /// This method tests for `!=`.
     #[inline]
+    #[stable]
     fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
 }
 
@@ -79,8 +89,8 @@ pub trait PartialEq<Sized? Rhs = Self> for Sized? {
 /// - reflexive: `a == a`;
 /// - symmetric: `a == b` implies `b == a`; and
 /// - transitive: `a == b` and `b == c` implies `a == c`.
-#[unstable = "Definition may change slightly after trait reform"]
-pub trait Eq<Sized? Rhs = Self> for Sized?: PartialEq<Rhs> {
+#[stable]
+pub trait Eq for Sized?: PartialEq<Self> {
     // FIXME #13101: this method is used solely by #[deriving] to
     // assert that every component of a type implements #[deriving]
     // itself, the current deriving infrastructure means doing this
@@ -97,12 +107,15 @@ pub trait Eq<Sized? Rhs = Self> for Sized?: PartialEq<Rhs> {
 #[deriving(Clone, Copy, PartialEq, Show)]
 #[stable]
 pub enum Ordering {
-   /// An ordering where a compared value is less [than another].
-   Less = -1i,
-   /// An ordering where a compared value is equal [to another].
-   Equal = 0i,
-   /// An ordering where a compared value is greater [than another].
-   Greater = 1i,
+    /// An ordering where a compared value is less [than another].
+    #[stable]
+    Less = -1i,
+    /// An ordering where a compared value is equal [to another].
+    #[stable]
+    Equal = 0i,
+    /// An ordering where a compared value is greater [than another].
+    #[stable]
+    Greater = 1i,
 }
 
 impl Ordering {
@@ -127,7 +140,7 @@ impl Ordering {
     /// assert!(data == b);
     /// ```
     #[inline]
-    #[experimental]
+    #[stable]
     pub fn reverse(self) -> Ordering {
         unsafe {
             // this compiles really nicely (to a single instruction);
@@ -150,8 +163,8 @@ impl Ordering {
 ///   true; and
 /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
 ///   both `==` and `>`.
-#[unstable = "Definition may change slightly after trait reform"]
-pub trait Ord<Sized? Rhs = Self> for Sized?: Eq<Rhs> + PartialOrd<Rhs> {
+#[stable]
+pub trait Ord for Sized?: Eq + PartialOrd<Self> {
     /// This method returns an ordering between `self` and `other` values.
     ///
     /// By convention, `self.cmp(&other)` returns the ordering matching
@@ -164,23 +177,26 @@ pub trait Ord<Sized? Rhs = Self> for Sized?: Eq<Rhs> + PartialOrd<Rhs> {
     /// assert_eq!(10u.cmp(&5),  Greater);  // because 10 > 5
     /// assert_eq!( 5u.cmp(&5),  Equal);    // because 5 == 5
     /// ```
-    fn cmp(&self, other: &Rhs) -> Ordering;
+    #[stable]
+    fn cmp(&self, other: &Self) -> Ordering;
 }
 
-#[unstable = "Trait is unstable."]
+#[stable]
 impl Eq for Ordering {}
 
-#[unstable = "Trait is unstable."]
+#[stable]
 impl Ord for Ordering {
     #[inline]
+    #[stable]
     fn cmp(&self, other: &Ordering) -> Ordering {
         (*self as int).cmp(&(*other as int))
     }
 }
 
-#[unstable = "Trait is unstable."]
+#[stable]
 impl PartialOrd for Ordering {
     #[inline]
+    #[stable]
     fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
         (*self as int).partial_cmp(&(*other as int))
     }
@@ -188,6 +204,17 @@ impl PartialOrd for Ordering {
 
 /// Trait for values that can be compared for a sort-order.
 ///
+/// The comparison must satisfy, for all `a`, `b` and `c`:
+///
+/// - antisymmetry: if `a < b` then `!(a > b)` and vice versa; and
+/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for
+///   both `==` and `>`.
+///
+/// Note that these requirements mean that the trait itself must be
+/// implemented symmetrically and transitively: if `T: PartialOrd<U>`
+/// and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
+/// PartialOrd<V>`.
+///
 /// PartialOrd only requires implementation of the `partial_cmp` method,
 /// with the others generated from default implementations.
 ///
@@ -196,14 +223,16 @@ impl PartialOrd for Ordering {
 /// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
 /// 5.11).
 #[lang="ord"]
-#[unstable = "Definition may change slightly after trait reform"]
+#[stable]
 pub trait PartialOrd<Sized? Rhs = Self> for Sized?: PartialEq<Rhs> {
     /// This method returns an ordering between `self` and `other` values
     /// if one exists.
+    #[stable]
     fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
 
     /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
     #[inline]
+    #[stable]
     fn lt(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Less) => true,
@@ -213,6 +242,7 @@ pub trait PartialOrd<Sized? Rhs = Self> for Sized?: PartialEq<Rhs> {
 
     /// This method tests less than or equal to (`<=`).
     #[inline]
+    #[stable]
     fn le(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Less) | Some(Equal) => true,
@@ -222,6 +252,7 @@ pub trait PartialOrd<Sized? Rhs = Self> for Sized?: PartialEq<Rhs> {
 
     /// This method tests greater than (`>`).
     #[inline]
+    #[stable]
     fn gt(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Greater) => true,
@@ -231,6 +262,7 @@ pub trait PartialOrd<Sized? Rhs = Self> for Sized?: PartialEq<Rhs> {
 
     /// This method tests greater than or equal to (`>=`).
     #[inline]
+    #[stable]
     fn ge(&self, other: &Rhs) -> bool {
         match self.partial_cmp(other) {
             Some(Greater) | Some(Equal) => true,
@@ -299,7 +331,7 @@ mod impls {
 
     macro_rules! partial_eq_impl {
         ($($t:ty)*) => ($(
-            #[unstable = "Trait is unstable."]
+            #[stable]
             impl PartialEq for $t {
                 #[inline]
                 fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
@@ -309,7 +341,7 @@ mod impls {
         )*)
     }
 
-    #[unstable = "Trait is unstable."]
+    #[stable]
     impl PartialEq for () {
         #[inline]
         fn eq(&self, _other: &()) -> bool { true }
@@ -323,7 +355,7 @@ mod impls {
 
     macro_rules! eq_impl {
         ($($t:ty)*) => ($(
-            #[unstable = "Trait is unstable."]
+            #[stable]
             impl Eq for $t {}
         )*)
     }
@@ -332,7 +364,7 @@ mod impls {
 
     macro_rules! partial_ord_impl {
         ($($t:ty)*) => ($(
-            #[unstable = "Trait is unstable."]
+            #[stable]
             impl PartialOrd for $t {
                 #[inline]
                 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
@@ -355,7 +387,7 @@ mod impls {
         )*)
     }
 
-    #[unstable = "Trait is unstable."]
+    #[stable]
     impl PartialOrd for () {
         #[inline]
         fn partial_cmp(&self, _: &()) -> Option<Ordering> {
@@ -363,7 +395,7 @@ mod impls {
         }
     }
 
-    #[unstable = "Trait is unstable."]
+    #[stable]
     impl PartialOrd for bool {
         #[inline]
         fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
@@ -375,7 +407,7 @@ mod impls {
 
     macro_rules! ord_impl {
         ($($t:ty)*) => ($(
-            #[unstable = "Trait is unstable."]
+            #[stable]
             impl Ord for $t {
                 #[inline]
                 fn cmp(&self, other: &$t) -> Ordering {
@@ -387,13 +419,13 @@ mod impls {
         )*)
     }
 
-    #[unstable = "Trait is unstable."]
+    #[stable]
     impl Ord for () {
         #[inline]
         fn cmp(&self, _other: &()) -> Ordering { Equal }
     }
 
-    #[unstable = "Trait is unstable."]
+    #[stable]
     impl Ord for bool {
         #[inline]
         fn cmp(&self, other: &bool) -> Ordering {
@@ -405,68 +437,69 @@ mod impls {
 
     // & pointers
 
-    #[unstable = "Trait is unstable."]
+    #[stable]
     impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) }
         #[inline]
         fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) }
     }
-    #[unstable = "Trait is unstable."]
-    impl<'a, Sized? T: PartialOrd> PartialOrd for &'a T {
+    #[stable]
+    impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b B> for &'a A where A: PartialOrd<B> {
         #[inline]
-        fn partial_cmp(&self, other: &&'a T) -> Option<Ordering> {
+        fn partial_cmp(&self, other: &&'b B) -> Option<Ordering> {
             PartialOrd::partial_cmp(*self, *other)
         }
         #[inline]
-        fn lt(&self, other: & &'a T) -> bool { PartialOrd::lt(*self, *other) }
+        fn lt(&self, other: & &'b B) -> bool { PartialOrd::lt(*self, *other) }
         #[inline]
-        fn le(&self, other: & &'a T) -> bool { PartialOrd::le(*self, *other) }
+        fn le(&self, other: & &'b B) -> bool { PartialOrd::le(*self, *other) }
         #[inline]
-        fn ge(&self, other: & &'a T) -> bool { PartialOrd::ge(*self, *other) }
+        fn ge(&self, other: & &'b B) -> bool { PartialOrd::ge(*self, *other) }
         #[inline]
-        fn gt(&self, other: & &'a T) -> bool { PartialOrd::gt(*self, *other) }
+        fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) }
     }
-    #[unstable = "Trait is unstable."]
-    impl<'a, Sized? T: Ord> Ord for &'a T {
+    #[stable]
+    impl<'a, Sized? A> Ord for &'a A where A: Ord {
         #[inline]
-        fn cmp(&self, other: & &'a T) -> Ordering { Ord::cmp(*self, *other) }
+        fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) }
     }
-    #[unstable = "Trait is unstable."]
-    impl<'a, Sized? T: Eq> Eq for &'a T {}
+    #[stable]
+    impl<'a, Sized? A> Eq for &'a A where A: Eq {}
 
     // &mut pointers
 
-    #[unstable = "Trait is unstable."]
+    #[stable]
     impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a mut A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
         #[inline]
         fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
     }
-    #[unstable = "Trait is unstable."]
-    impl<'a, Sized? T: PartialOrd> PartialOrd for &'a mut T {
+    #[stable]
+    impl<'a, 'b, Sized? A, Sized? B> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd<B> {
         #[inline]
-        fn partial_cmp(&self, other: &&'a mut T) -> Option<Ordering> {
+        fn partial_cmp(&self, other: &&'b mut B) -> Option<Ordering> {
             PartialOrd::partial_cmp(*self, *other)
         }
         #[inline]
-        fn lt(&self, other: &&'a mut T) -> bool { PartialOrd::lt(*self, *other) }
+        fn lt(&self, other: &&'b mut B) -> bool { PartialOrd::lt(*self, *other) }
         #[inline]
-        fn le(&self, other: &&'a mut T) -> bool { PartialOrd::le(*self, *other) }
+        fn le(&self, other: &&'b mut B) -> bool { PartialOrd::le(*self, *other) }
         #[inline]
-        fn ge(&self, other: &&'a mut T) -> bool { PartialOrd::ge(*self, *other) }
+        fn ge(&self, other: &&'b mut B) -> bool { PartialOrd::ge(*self, *other) }
         #[inline]
-        fn gt(&self, other: &&'a mut T) -> bool { PartialOrd::gt(*self, *other) }
+        fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) }
     }
-    #[unstable = "Trait is unstable."]
-    impl<'a, Sized? T: Ord> Ord for &'a mut T {
+    #[stable]
+    impl<'a, Sized? A> Ord for &'a mut A where A: Ord {
         #[inline]
-        fn cmp(&self, other: &&'a mut T) -> Ordering { Ord::cmp(*self, *other) }
+        fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) }
     }
-    #[unstable = "Trait is unstable."]
-    impl<'a, Sized? T: Eq> Eq for &'a mut T {}
+    #[stable]
+    impl<'a, Sized? A> Eq for &'a mut A where A: Eq {}
 
+    #[stable]
     impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b mut B> for &'a A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
@@ -474,6 +507,7 @@ mod impls {
         fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
     }
 
+    #[stable]
     impl<'a, 'b, Sized? A, Sized? B> PartialEq<&'b B> for &'a mut A where A: PartialEq<B> {
         #[inline]
         fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) }
diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs
index 47701ab8ffd..e1728d762ed 100644
--- a/src/libcore/fmt/float.rs
+++ b/src/libcore/fmt/float.rs
@@ -123,7 +123,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
     // For an f64 the exponent is in the range of [-1022, 1023] for base 2, so
     // we may have up to that many digits. Give ourselves some extra wiggle room
     // otherwise as well.
-    let mut buf = [0u8, ..1536];
+    let mut buf = [0u8; 1536];
     let mut end = 0;
     let radix_gen: T = cast(radix as int).unwrap();
 
@@ -179,7 +179,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
         _ => ()
     }
 
-    buf[mut ..end].reverse();
+    buf.slice_to_mut(end).reverse();
 
     // Remember start of the fractional digits.
     // Points one beyond end of buf if none get generated,
@@ -225,10 +225,10 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
         // cut off the one extra digit, and depending on its value
         // round the remaining ones.
         if limit_digits && dig == digit_count {
-            let ascii2value = |chr: u8| {
+            let ascii2value = |&: chr: u8| {
                 (chr as char).to_digit(radix).unwrap()
             };
-            let value2ascii = |val: uint| {
+            let value2ascii = |&: val: uint| {
                 char::from_digit(val, radix).unwrap() as u8
             };
 
@@ -316,7 +316,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
 
             impl<'a> fmt::FormatWriter for Filler<'a> {
                 fn write(&mut self, bytes: &[u8]) -> fmt::Result {
-                    slice::bytes::copy_memory(self.buf[mut *self.end..],
+                    slice::bytes::copy_memory(self.buf.slice_from_mut(*self.end),
                                               bytes);
                     *self.end += bytes.len();
                     Ok(())
@@ -325,18 +325,9 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
 
             let mut filler = Filler { buf: &mut buf, end: &mut end };
             match sign {
-                // NOTE(stage0): Remove cfg after a snapshot
-                #[cfg(not(stage0))]
                 SignNeg => {
                     let _ = fmt::write(&mut filler, format_args!("{:-}", exp));
                 }
-                // NOTE(stage0): Remove match arm after a snapshot
-                #[cfg(stage0)]
-                SignNeg => {
-                    let _ = format_args!(|args| {
-                        fmt::write(&mut filler, args)
-                    }, "{:-}", exp);
-                }
             }
         }
     }
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index b050b98de2f..87fcb12e29f 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -70,21 +70,11 @@ pub trait FormatWriter {
     /// This function will return an instance of `FormatError` on error.
     fn write(&mut self, bytes: &[u8]) -> Result;
 
-    // NOTE(stage0): Remove cfg after a snapshot
-    #[cfg(not(stage0))]
     /// Glue for usage of the `write!` macro with implementers of this trait.
     ///
     /// This method should generally not be invoked manually, but rather through
     /// the `write!` macro itself.
     fn write_fmt(&mut self, args: Arguments) -> Result { write(self, args) }
-
-    // NOTE(stage0): Remove method after a snapshot
-    #[cfg(stage0)]
-    /// Glue for usage of the `write!` macro with implementers of this trait.
-    ///
-    /// This method should generally not be invoked manually, but rather through
-    /// the `write!` macro itself.
-    fn write_fmt(&mut self, args: &Arguments) -> Result { write(self, args) }
 }
 
 /// A struct to represent both where to emit formatting strings to and how they
@@ -204,17 +194,9 @@ pub struct Arguments<'a> {
 }
 
 impl<'a> Show for Arguments<'a> {
-    // NOTE(stage0): Remove cfg after a snapshot
-    #[cfg(not(stage0))]
     fn fmt(&self, fmt: &mut Formatter) -> Result {
         write(fmt.buf, *self)
     }
-
-    // NOTE(stage0): Remove method after a snapshot
-    #[cfg(stage0)]
-    fn fmt(&self, fmt: &mut Formatter) -> Result {
-        write(fmt.buf, self)
-    }
 }
 
 /// When a format is not otherwise specified, types are formatted by ascribing
@@ -287,8 +269,6 @@ static DEFAULT_ARGUMENT: rt::Argument<'static> = rt::Argument {
     }
 };
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// The `write` function takes an output stream, a precompiled format string,
 /// and a list of arguments. The arguments will be formatted according to the
 /// specified format string into the output stream provided.
@@ -342,61 +322,6 @@ pub fn write(output: &mut FormatWriter, args: Arguments) -> Result {
     Ok(())
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-/// The `write` function takes an output stream, a precompiled format string,
-/// and a list of arguments. The arguments will be formatted according to the
-/// specified format string into the output stream provided.
-///
-/// # Arguments
-///
-///   * output - the buffer to write output to
-///   * args - the precompiled arguments generated by `format_args!`
-#[experimental = "libcore and I/O have yet to be reconciled, and this is an \
-                  implementation detail which should not otherwise be exported"]
-pub fn write(output: &mut FormatWriter, args: &Arguments) -> Result {
-    let mut formatter = Formatter {
-        flags: 0,
-        width: None,
-        precision: None,
-        buf: output,
-        align: rt::AlignUnknown,
-        fill: ' ',
-        args: args.args,
-        curarg: args.args.iter(),
-    };
-
-    let mut pieces = args.pieces.iter();
-
-    match args.fmt {
-        None => {
-            // We can use default formatting parameters for all arguments.
-            for _ in range(0, args.args.len()) {
-                try!(formatter.buf.write(pieces.next().unwrap().as_bytes()));
-                try!(formatter.run(&DEFAULT_ARGUMENT));
-            }
-        }
-        Some(fmt) => {
-            // Every spec has a corresponding argument that is preceded by
-            // a string piece.
-            for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
-                try!(formatter.buf.write(piece.as_bytes()));
-                try!(formatter.run(arg));
-            }
-        }
-    }
-
-    // There can be only one trailing string piece left.
-    match pieces.next() {
-        Some(piece) => {
-            try!(formatter.buf.write(piece.as_bytes()));
-        }
-        None => {}
-    }
-
-    Ok(())
-}
-
 impl<'a> Formatter<'a> {
 
     // First up is the collection of functions used to execute a format string
@@ -473,9 +398,9 @@ impl<'a> Formatter<'a> {
         }
 
         // Writes the sign if it exists, and then the prefix if it was requested
-        let write_prefix = |f: &mut Formatter| {
+        let write_prefix = |&: f: &mut Formatter| {
             for c in sign.into_iter() {
-                let mut b = [0, ..4];
+                let mut b = [0; 4];
                 let n = c.encode_utf8(&mut b).unwrap_or(0);
                 try!(f.buf.write(b[..n]));
             }
@@ -580,7 +505,7 @@ impl<'a> Formatter<'a> {
             rt::AlignCenter => (padding / 2, (padding + 1) / 2),
         };
 
-        let mut fill = [0u8, ..4];
+        let mut fill = [0u8; 4];
         let len = self.fill.encode_utf8(&mut fill).unwrap_or(0);
 
         for _ in range(0, pre_pad) {
@@ -603,22 +528,12 @@ impl<'a> Formatter<'a> {
         self.buf.write(data)
     }
 
-    // NOTE(stage0): Remove cfg after a snapshot
-    #[cfg(not(stage0))]
     /// Writes some formatted information into this instance
     #[unstable = "reconciling core and I/O may alter this definition"]
     pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
         write(self.buf, fmt)
     }
 
-    // NOTE(stage0): Remove method after a snapshot
-    #[cfg(stage0)]
-    /// Writes some formatted information into this instance
-    #[unstable = "reconciling core and I/O may alter this definition"]
-    pub fn write_fmt(&mut self, fmt: &Arguments) -> Result {
-        write(self.buf, fmt)
-    }
-
     /// Flags for formatting (packed version of rt::Flag)
     #[experimental = "return type may change and method was just created"]
     pub fn flags(&self) -> uint { self.flags }
@@ -691,7 +606,7 @@ impl Show for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
         use char::Char;
 
-        let mut utf8 = [0u8, ..4];
+        let mut utf8 = [0u8; 4];
         let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
         let s: &str = unsafe { mem::transmute(utf8[..amt]) };
         Show::fmt(s, f)
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index cd8f226172a..7de3e847dc6 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -37,7 +37,7 @@ trait GenericRadix {
         // characters for a base 2 number.
         let zero = Int::zero();
         let is_positive = x >= zero;
-        let mut buf = [0u8, ..64];
+        let mut buf = [0u8; 64];
         let mut curr = buf.len();
         let base = cast(self.base()).unwrap();
         if is_positive {
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index c1aa605a455..d4d241752f2 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -100,7 +100,7 @@ macro_rules! impl_hash {
         impl<S: Writer> Hash<S> for $ty {
             #[inline]
             fn hash(&self, state: &mut S) {
-                let a: [u8, ..::$ty::BYTES] = unsafe {
+                let a: [u8; ::$ty::BYTES] = unsafe {
                     mem::transmute((*self as $uty).to_le() as $ty)
                 };
                 state.write(a.as_slice())
diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs
index ab6b0986c68..51c0827186d 100644
--- a/src/libcore/hash/sip.rs
+++ b/src/libcore/hash/sip.rs
@@ -292,7 +292,7 @@ mod tests {
     #[test]
     #[allow(unused_must_use)]
     fn test_siphash() {
-        let vecs : [[u8, ..8], ..64] = [
+        let vecs : [[u8; 8]; 64] = [
             [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
             [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
             [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
@@ -366,7 +366,7 @@ mod tests {
         let mut state_inc = SipState::new_with_keys(k0, k1);
         let mut state_full = SipState::new_with_keys(k0, k1);
 
-        fn to_hex_str(r: &[u8, ..8]) -> String {
+        fn to_hex_str(r: &[u8; 8]) -> String {
             let mut s = String::new();
             for b in r.iter() {
                 s.push_str(format!("{}", fmt::radix(*b, 16)).as_slice());
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 9c3e53a1ace..7c53503b1ce 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -59,6 +59,7 @@ pub use self::MinMaxResult::*;
 use clone::Clone;
 use cmp;
 use cmp::Ord;
+use default::Default;
 use mem;
 use num::{ToPrimitive, Int};
 use ops::{Add, Deref, FnMut};
@@ -68,20 +69,6 @@ use uint;
 
 #[deprecated = "renamed to Extend"] pub use self::Extend as Extendable;
 
-/// Conversion from an `Iterator`
-#[unstable = "may be replaced by a more general conversion trait"]
-pub trait FromIterator<A> {
-    /// Build a container with elements from an external iterator.
-    fn from_iter<T: Iterator<A>>(iterator: T) -> Self;
-}
-
-/// A type growable from an `Iterator` implementation
-#[unstable = "just renamed as part of collections reform"]
-pub trait Extend<A> {
-    /// Extend a container with the elements yielded by an arbitrary iterator
-    fn extend<T: Iterator<A>>(&mut self, iterator: T);
-}
-
 /// An interface for dealing with "external iterators". These types of iterators
 /// can be resumed at any time as all state is stored internally as opposed to
 /// being located on the call stack.
@@ -106,6 +93,20 @@ pub trait Iterator<A> {
     fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
 }
 
+/// Conversion from an `Iterator`
+#[unstable = "may be replaced by a more general conversion trait"]
+pub trait FromIterator<A> {
+    /// Build a container with elements from an external iterator.
+    fn from_iter<T: Iterator<A>>(iterator: T) -> Self;
+}
+
+/// A type growable from an `Iterator` implementation
+#[unstable = "just renamed as part of collections reform"]
+pub trait Extend<A> {
+    /// Extend a container with the elements yielded by an arbitrary iterator
+    fn extend<T: Iterator<A>>(&mut self, iterator: T);
+}
+
 #[unstable = "new convention for extension traits"]
 /// An extension trait providing numerous methods applicable to all iterators.
 pub trait IteratorExt<A>: Iterator<A> {
@@ -223,7 +224,6 @@ pub trait IteratorExt<A>: Iterator<A> {
         Enumerate{iter: self, count: 0}
     }
 
-
     /// Creates an iterator that has a `.peek()` method
     /// that returns an optional reference to the next element.
     ///
@@ -471,6 +471,35 @@ pub trait IteratorExt<A>: Iterator<A> {
         FromIterator::from_iter(self)
     }
 
+    /// Loops through the entire iterator, collecting all of the elements into
+    /// one of two containers, depending on a predicate. The elements of the
+    /// first container satisfy the predicate, while the elements of the second
+    /// do not.
+    ///
+    /// ```
+    /// let vec = vec![1i, 2i, 3i, 4i];
+    /// let (even, odd): (Vec<int>, Vec<int>) = vec.into_iter().partition(|&n| n % 2 == 0);
+    /// assert_eq!(even, vec![2, 4]);
+    /// assert_eq!(odd, vec![1, 3]);
+    /// ```
+    #[unstable = "recently added as part of collections reform"]
+    fn partition<B, F>(mut self, mut f: F) -> (B, B) where
+        B: Default + Extend<A>, F: FnMut(&A) -> bool
+    {
+        let mut left: B = Default::default();
+        let mut right: B = Default::default();
+
+        for x in self {
+            if f(&x) {
+                left.extend(Some(x).into_iter())
+            } else {
+                right.extend(Some(x).into_iter())
+            }
+        }
+
+        (left, right)
+    }
+
     /// Loops through `n` iterations, returning the `n`th element of the
     /// iterator.
     ///
@@ -661,6 +690,42 @@ pub trait IteratorExt<A>: Iterator<A> {
 #[unstable = "trait is unstable"]
 impl<A, I> IteratorExt<A> for I where I: Iterator<A> {}
 
+/// Extention trait for iterators of pairs.
+#[unstable = "newly added trait, likely to be merged with IteratorExt"]
+pub trait IteratorPairExt<A, B>: Iterator<(A, B)> {
+    /// Converts an iterator of pairs into a pair of containers.
+    ///
+    /// Loops through the entire iterator, collecting the first component of
+    /// each item into one new container, and the second component into another.
+    fn unzip<FromA, FromB>(mut self) -> (FromA, FromB) where
+        FromA: Default + Extend<A>, FromB: Default + Extend<B>
+    {
+        struct SizeHint<A>(uint, Option<uint>);
+        impl<A> Iterator<A> for SizeHint<A> {
+            fn next(&mut self) -> Option<A> { None }
+            fn size_hint(&self) -> (uint, Option<uint>) {
+                (self.0, self.1)
+            }
+        }
+
+        let (lo, hi) = self.size_hint();
+        let mut ts: FromA = Default::default();
+        let mut us: FromB = Default::default();
+
+        ts.extend(SizeHint(lo, hi));
+        us.extend(SizeHint(lo, hi));
+
+        for (t, u) in self {
+            ts.extend(Some(t).into_iter());
+            us.extend(Some(u).into_iter());
+        }
+
+        (ts, us)
+    }
+}
+
+impl<A, B, I> IteratorPairExt<A, B> for I where I: Iterator<(A, B)> {}
+
 /// A range iterator able to yield elements from both ends
 ///
 /// A `DoubleEndedIterator` can be thought of as a deque in that `next()` and `next_back()` exhaust
@@ -972,7 +1037,7 @@ pub trait IteratorOrdExt<A> {
     /// ```rust
     /// use std::iter::{NoElements, OneElement, MinMax};
     ///
-    /// let v: [int, ..0] = [];
+    /// let v: [int; 0] = [];
     /// assert_eq!(v.iter().min_max(), NoElements);
     ///
     /// let v = [1i];
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
index 2cd9e7c4509..e8fbd9d930f 100644
--- a/src/libcore/macros.rs
+++ b/src/libcore/macros.rs
@@ -10,8 +10,6 @@
 
 #![macro_escape]
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Entry point of task panic, for details, see std::macros
 #[macro_export]
 macro_rules! panic {
@@ -32,44 +30,6 @@ macro_rules! panic {
     });
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// Entry point of task panic, for details, see std::macros
-#[macro_export]
-macro_rules! panic {
-    () => (
-        panic!("{}", "explicit panic")
-    );
-    ($msg:expr) => ({
-        static _MSG_FILE_LINE: (&'static str, &'static str, uint) = ($msg, file!(), line!());
-        ::core::panicking::panic(&_MSG_FILE_LINE)
-    });
-    ($fmt:expr, $($arg:tt)*) => ({
-        // a closure can't have return type !, so we need a full
-        // function to pass to format_args!, *and* we need the
-        // file and line numbers right here; so an inner bare fn
-        // is our only choice.
-        //
-        // LLVM doesn't tend to inline this, presumably because begin_unwind_fmt
-        // is #[cold] and #[inline(never)] and because this is flagged as cold
-        // as returning !. We really do want this to be inlined, however,
-        // because it's just a tiny wrapper. Small wins (156K to 149K in size)
-        // were seen when forcing this to be inlined, and that number just goes
-        // up with the number of calls to panic!()
-        //
-        // The leading _'s are to avoid dead code warnings if this is
-        // used inside a dead function. Just `#[allow(dead_code)]` is
-        // insufficient, since the user may have
-        // `#[forbid(dead_code)]` and which cannot be overridden.
-        #[inline(always)]
-        fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! {
-            static _FILE_LINE: (&'static str, uint) = (file!(), line!());
-            ::core::panicking::panic_fmt(fmt, &_FILE_LINE)
-        }
-        format_args!(_run_fmt, $fmt, $($arg)*)
-    });
-}
-
 /// Runtime assertion, for details see std::macros
 #[macro_export]
 macro_rules! assert {
@@ -85,16 +45,6 @@ macro_rules! assert {
     );
 }
 
-/// Runtime assertion, only without `--cfg ndebug`
-#[macro_export]
-macro_rules! debug_assert {
-    ($(a:tt)*) => ({
-        if cfg!(not(ndebug)) {
-            assert!($($a)*);
-        }
-    })
-}
-
 /// Runtime assertion for equality, for details see std::macros
 #[macro_export]
 macro_rules! assert_eq {
@@ -117,7 +67,7 @@ macro_rules! debug_assert_eq {
     })
 }
 
-/// Runtime assertion, disableable at compile time
+/// Runtime assertion, disableable at compile time with `--cfg ndebug`
 #[macro_export]
 macro_rules! debug_assert {
     ($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })
@@ -129,25 +79,12 @@ macro_rules! try {
     ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(e) })
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Writing a formatted string into a writer
 #[macro_export]
 macro_rules! write {
     ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// Writing a formatted string into a writer
-#[macro_export]
-macro_rules! write {
-    ($dst:expr, $($arg:tt)*) => ({
-        let dst = &mut *$dst;
-        format_args!(|args| { dst.write_fmt(args) }, $($arg)*)
-    })
-}
-
 /// Writing a formatted string plus a newline into a writer
 #[macro_export]
 macro_rules! writeln {
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index a2ef8d484a7..15016562699 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -314,60 +314,6 @@ rem_float_impl! { f64, fmod }
 /// ```
 /// use std::ops::Neg;
 ///
-/// #[deriving(Copy)]
-/// struct Foo;
-///
-/// impl Neg<Foo> for Foo {
-///     fn neg(&self) -> Foo {
-///         println!("Negating!");
-///         *self
-///     }
-/// }
-///
-/// fn main() {
-///     -Foo;
-/// }
-/// ```
-// NOTE(stage0): Remove trait after a snapshot
-#[cfg(stage0)]
-#[lang="neg"]
-pub trait Neg<Result> for Sized? {
-    /// The method for the unary `-` operator
-    fn neg(&self) -> Result;
-}
-
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-macro_rules! neg_impl {
-    ($($t:ty)*) => ($(
-        impl Neg<$t> for $t {
-            #[inline]
-            fn neg(&self) -> $t { -*self }
-        }
-    )*)
-}
-
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-macro_rules! neg_uint_impl {
-    ($t:ty, $t_signed:ty) => {
-        impl Neg<$t> for $t {
-            #[inline]
-            fn neg(&self) -> $t { -(*self as $t_signed) as $t }
-        }
-    }
-}
-
-/// The `Neg` trait is used to specify the functionality of unary `-`.
-///
-/// # Example
-///
-/// A trivial implementation of `Neg`. When `-Foo` happens, it ends up calling
-/// `neg`, and therefore, `main` prints `Negating!`.
-///
-/// ```
-/// use std::ops::Neg;
-///
 /// struct Foo;
 ///
 /// impl Copy for Foo {}
@@ -383,14 +329,12 @@ macro_rules! neg_uint_impl {
 ///     -Foo;
 /// }
 /// ```
-#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
 #[lang="neg"]
 pub trait Neg<Result> {
     /// The method for the unary `-` operator
     fn neg(self) -> Result;
 }
 
-#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
 macro_rules! neg_impl {
     ($($t:ty)*) => ($(
         impl Neg<$t> for $t {
@@ -400,7 +344,6 @@ macro_rules! neg_impl {
     )*)
 }
 
-#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
 macro_rules! neg_uint_impl {
     ($t:ty, $t_signed:ty) => {
         impl Neg<$t> for $t {
@@ -429,50 +372,6 @@ neg_uint_impl! { u64, i64 }
 /// ```
 /// use std::ops::Not;
 ///
-/// #[deriving(Copy)]
-/// struct Foo;
-///
-/// impl Not<Foo> for Foo {
-///     fn not(&self) -> Foo {
-///         println!("Not-ing!");
-///         *self
-///     }
-/// }
-///
-/// fn main() {
-///     !Foo;
-/// }
-/// ```
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-#[lang="not"]
-pub trait Not<Result> for Sized? {
-    /// The method for the unary `!` operator
-    fn not(&self) -> Result;
-}
-
-
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-macro_rules! not_impl {
-    ($($t:ty)*) => ($(
-        impl Not<$t> for $t {
-            #[inline]
-            fn not(&self) -> $t { !*self }
-        }
-    )*)
-}
-
-/// The `Not` trait is used to specify the functionality of unary `!`.
-///
-/// # Example
-///
-/// A trivial implementation of `Not`. When `!Foo` happens, it ends up calling
-/// `not`, and therefore, `main` prints `Not-ing!`.
-///
-/// ```
-/// use std::ops::Not;
-///
 /// struct Foo;
 ///
 /// impl Copy for Foo {}
@@ -488,14 +387,12 @@ macro_rules! not_impl {
 ///     !Foo;
 /// }
 /// ```
-#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
 #[lang="not"]
 pub trait Not<Result> {
     /// The method for the unary `!` operator
     fn not(self) -> Result;
 }
 
-#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
 macro_rules! not_impl {
     ($($t:ty)*) => ($(
         impl Not<$t> for $t {
@@ -946,6 +843,14 @@ impl<Idx: Clone + Step> Iterator<Idx> for RangeFrom<Idx> {
     }
 }
 
+/// A range which is only bounded above.
+#[deriving(Copy)]
+#[lang="range_to"]
+pub struct RangeTo<Idx> {
+    /// The upper bound of the range (exclusive).
+    pub end: Idx,
+}
+
 
 /// The `Deref` trait is used to specify the functionality of dereferencing
 /// operations like `*v`.
diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs
index 32f09a4c17f..61b4284e1dd 100644
--- a/src/libcore/panicking.rs
+++ b/src/libcore/panicking.rs
@@ -31,11 +31,7 @@
 #![allow(dead_code, missing_docs)]
 
 use fmt;
-// NOTE(stage0): Remove import after a snapshot
-#[cfg(stage0)] use intrinsics;
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 #[cold] #[inline(never)] // this is the slow path, always
 #[lang="panic"]
 pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
@@ -43,22 +39,6 @@ pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
     panic_fmt(format_args!("{}", expr), &(file, line))
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-#[cold] #[inline(never)] // this is the slow path, always
-#[lang="panic"]
-pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
-    let (expr, file, line) = *expr_file_line;
-    let ref file_line = (file, line);
-    format_args!(|args| -> () {
-        panic_fmt(args, file_line);
-    }, "{}", expr);
-
-    unsafe { intrinsics::abort() }
-}
-
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 #[cold] #[inline(never)]
 #[lang="panic_bounds_check"]
 fn panic_bounds_check(file_line: &(&'static str, uint),
@@ -67,20 +47,6 @@ fn panic_bounds_check(file_line: &(&'static str, uint),
                            len, index), file_line)
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-#[cold] #[inline(never)]
-#[lang="panic_bounds_check"]
-fn panic_bounds_check(file_line: &(&'static str, uint),
-                     index: uint, len: uint) -> ! {
-    format_args!(|args| -> () {
-        panic_fmt(args, file_line);
-    }, "index out of bounds: the len is {} but the index is {}", len, index);
-    unsafe { intrinsics::abort() }
-}
-
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 #[cold] #[inline(never)]
 pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
     #[allow(improper_ctypes)]
@@ -91,18 +57,3 @@ pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
     let (file, line) = *file_line;
     unsafe { panic_impl(fmt, file, line) }
 }
-
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-#[cold] #[inline(never)]
-pub fn panic_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
-    #[allow(improper_ctypes)]
-    extern {
-        #[lang = "panic_fmt"]
-        fn panic_impl(fmt: &fmt::Arguments, file: &'static str,
-                        line: uint) -> !;
-
-    }
-    let (file, line) = *file_line;
-    unsafe { panic_impl(fmt, file, line) }
-}
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 1fc377cda0a..210850be13a 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -44,10 +44,10 @@ pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
 pub use iter::{Extend, IteratorExt};
 pub use iter::{Iterator, DoubleEndedIterator, DoubleEndedIteratorExt};
 pub use iter::{IteratorCloneExt, CloneIteratorExt};
-pub use iter::{IteratorOrdExt, ExactSizeIterator};
+pub use iter::{IteratorOrdExt, ExactSizeIterator, IteratorPairExt};
 pub use option::Option::{mod, Some, None};
-pub use ptr::RawPtr;
+pub use ptr::{PtrExt, MutPtrExt};
 pub use result::Result::{mod, Ok, Err};
-pub use str::{Str, StrExt};
-pub use slice::{PartialEqSliceExt, OrdSliceExt};
 pub use slice::{AsSlice, SliceExt};
+pub use slice::{PartialEqSliceExt, OrdSliceExt};
+pub use str::{Str, StrExt};
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 8c724b4d852..faf1d781465 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -16,11 +16,10 @@
 //! typically limited to a few patterns.
 //!
 //! Use the [`null` function](fn.null.html) to create null pointers,
-//! the [`is_null`](trait.RawPtr.html#tymethod.is_null)
-//! and [`is_not_null`](trait.RawPtr.html#method.is_not_null)
-//! methods of the [`RawPtr` trait](trait.RawPtr.html) to check for null.
-//! The `RawPtr` trait is imported by the prelude, so `is_null` etc.
-//! work everywhere. The `RawPtr` also defines the `offset` method,
+//! the [`is_null`](trait.PtrExt.html#tymethod.is_null)
+//! methods of the [`PtrExt` trait](trait.PtrExt.html) to check for null.
+//! The `PtrExt` trait is imported by the prelude, so `is_null` etc.
+//! work everywhere. The `PtrExt` also defines the `offset` method,
 //! for pointer math.
 //!
 //! # Common ways to create unsafe pointers
@@ -87,16 +86,16 @@
 //! but C APIs hand out a lot of pointers generally, so are a common source
 //! of unsafe pointers in Rust.
 
+#![stable]
+
 use mem;
 use clone::Clone;
 use intrinsics;
+use option::Option::{mod, Some, None};
 use kinds::{Send, Sync};
-use option::Option;
-use option::Option::{Some, None};
 
 use cmp::{PartialEq, Eq, Ord, PartialOrd, Equiv};
-use cmp::Ordering;
-use cmp::Ordering::{Less, Equal, Greater};
+use cmp::Ordering::{mod, Less, Equal, Greater};
 
 // FIXME #19649: instrinsic docs don't render, so these have no docs :(
 
@@ -121,7 +120,7 @@ pub use intrinsics::set_memory;
 /// assert!(p.is_null());
 /// ```
 #[inline]
-#[unstable = "may need a different name after pending changes to pointer types"]
+#[stable]
 pub fn null<T>() -> *const T { 0 as *const T }
 
 /// Creates a null mutable raw pointer.
@@ -135,31 +134,31 @@ pub fn null<T>() -> *const T { 0 as *const T }
 /// assert!(p.is_null());
 /// ```
 #[inline]
-#[unstable = "may need a different name after pending changes to pointer types"]
+#[stable]
 pub fn null_mut<T>() -> *mut T { 0 as *mut T }
 
-/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be `0`.
+/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be
+/// `0`.
 ///
 /// # Safety
 ///
-/// Beyond accepting a raw pointer, this is unsafe because it will not drop the contents of `dst`,
-/// and may be used to create invalid instances of `T`.
+/// Beyond accepting a raw pointer, this is unsafe because it will not drop the
+/// contents of `dst`, and may be used to create invalid instances of `T`.
 #[inline]
-#[experimental = "uncertain about naming and semantics"]
-#[allow(experimental)]
+#[unstable = "may play a larger role in std::ptr future extensions"]
 pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
     set_memory(dst, 0, count);
 }
 
 /// Swaps the values at two mutable locations of the same type, without
-/// deinitialising either. They may overlap, unlike `mem::swap` which is otherwise
-/// equivalent.
+/// deinitialising either. They may overlap, unlike `mem::swap` which is
+/// otherwise equivalent.
 ///
 /// # Safety
 ///
 /// This is only unsafe because it accepts a raw pointer.
 #[inline]
-#[unstable]
+#[stable]
 pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     // Give ourselves some scratch space to work with
     let mut tmp: T = mem::uninitialized();
@@ -183,7 +182,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 /// This is only unsafe because it accepts a raw pointer.
 /// Otherwise, this operation is identical to `mem::replace`.
 #[inline]
-#[unstable]
+#[stable]
 pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
     mem::swap(mem::transmute(dest), &mut src); // cannot overlap
     src
@@ -201,7 +200,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
 /// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
 /// because it will attempt to drop the value previously at `*src`.
 #[inline(always)]
-#[unstable]
+#[stable]
 pub unsafe fn read<T>(src: *const T) -> T {
     let mut tmp: T = mem::uninitialized();
     copy_nonoverlapping_memory(&mut tmp, src, 1);
@@ -214,8 +213,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
 ///
 /// This is unsafe for the same reasons that `read` is unsafe.
 #[inline(always)]
-#[experimental]
-#[allow(experimental)]
+#[unstable = "may play a larger role in std::ptr future extensions"]
 pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
     // Copy the data out from `dest`:
     let tmp = read(&*dest);
@@ -226,8 +224,8 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
     tmp
 }
 
-/// Overwrites a memory location with the given value without reading or dropping
-/// the old value.
+/// Overwrites a memory location with the given value without reading or
+/// dropping the old value.
 ///
 /// # Safety
 ///
@@ -235,36 +233,44 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
 /// not drop the contents of `dst`. This could leak allocations or resources,
 /// so care must be taken not to overwrite an object that should be dropped.
 ///
-/// This is appropriate for initializing uninitialized memory, or overwritting memory
-/// that has previously been `read` from.
+/// This is appropriate for initializing uninitialized memory, or overwritting
+/// memory that has previously been `read` from.
 #[inline]
-#[unstable]
+#[stable]
 pub unsafe fn write<T>(dst: *mut T, src: T) {
     intrinsics::move_val_init(&mut *dst, src)
 }
 
 /// Methods on raw pointers
-pub trait RawPtr<T> {
-    /// Returns a null raw pointer.
+#[stable]
+pub trait PtrExt<T> {
+    /// Returns the null pointer.
+    #[deprecated = "call ptr::null instead"]
     fn null() -> Self;
 
     /// Returns true if the pointer is null.
-    fn is_null(&self) -> bool;
+    #[stable]
+    fn is_null(self) -> bool;
 
-    /// Returns true if the pointer is not null.
-    fn is_not_null(&self) -> bool { !self.is_null() }
+    /// Returns true if the pointer is not equal to the null pointer.
+    #[deprecated = "use !p.is_null() instead"]
+    fn is_not_null(self) -> bool { !self.is_null() }
 
-    /// Returns the address of the pointer.
-    fn to_uint(&self) -> uint;
+    /// Returns true if the pointer is not null.
+    #[deprecated = "use `as uint` instead"]
+    fn to_uint(self) -> uint;
 
-    /// Returns `None` if the pointer is null, or else returns a reference to the
-    /// value wrapped in `Some`.
+    /// Returns `None` if the pointer is null, or else returns a reference to
+    /// the value wrapped in `Some`.
     ///
     /// # Safety
     ///
-    /// While this method and its mutable counterpart are useful for null-safety,
-    /// it is important to note that this is still an unsafe operation because
-    /// the returned value could be pointing to invalid memory.
+    /// While this method and its mutable counterpart are useful for
+    /// null-safety, it is important to note that this is still an unsafe
+    /// operation because the returned value could be pointing to invalid
+    /// memory.
+    #[unstable = "Option is not clearly the right return type, and we may want \
+                  to tie the return lifetime to a borrow of the raw pointer"]
     unsafe fn as_ref<'a>(&self) -> Option<&'a T>;
 
     /// Calculates the offset from a pointer. `count` is in units of T; e.g. a
@@ -272,39 +278,51 @@ pub trait RawPtr<T> {
     ///
     /// # Safety
     ///
-    /// The offset must be in-bounds of the object, or one-byte-past-the-end. Otherwise
-    /// `offset` invokes Undefined Behaviour, regardless of whether the pointer is used.
+    /// The offset must be in-bounds of the object, or one-byte-past-the-end.
+    /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
+    /// the pointer is used.
+    #[stable]
     unsafe fn offset(self, count: int) -> Self;
 }
 
 /// Methods on mutable raw pointers
-pub trait RawMutPtr<T>{
-    /// Returns `None` if the pointer is null, or else returns a mutable reference
-    /// to the value wrapped in `Some`.
+#[stable]
+pub trait MutPtrExt<T>{
+    /// Returns `None` if the pointer is null, or else returns a mutable
+    /// reference to the value wrapped in `Some`.
     ///
     /// # Safety
     ///
     /// As with `as_ref`, this is unsafe because it cannot verify the validity
     /// of the returned pointer.
+    #[unstable = "Option is not clearly the right return type, and we may want \
+                  to tie the return lifetime to a borrow of the raw pointer"]
     unsafe fn as_mut<'a>(&self) -> Option<&'a mut T>;
 }
 
-impl<T> RawPtr<T> for *const T {
+#[stable]
+impl<T> PtrExt<T> for *const T {
     #[inline]
+    #[deprecated = "call ptr::null instead"]
     fn null() -> *const T { null() }
 
     #[inline]
-    fn is_null(&self) -> bool { *self == RawPtr::null() }
+    #[stable]
+    fn is_null(self) -> bool { self as uint == 0 }
 
     #[inline]
-    fn to_uint(&self) -> uint { *self as uint }
+    #[deprecated = "use `as uint` instead"]
+    fn to_uint(self) -> uint { self as uint }
 
     #[inline]
+    #[stable]
     unsafe fn offset(self, count: int) -> *const T {
         intrinsics::offset(self, count)
     }
 
     #[inline]
+    #[unstable = "return value does not necessarily convey all possible \
+                  information"]
     unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
         if self.is_null() {
             None
@@ -314,22 +332,29 @@ impl<T> RawPtr<T> for *const T {
     }
 }
 
-impl<T> RawPtr<T> for *mut T {
+#[stable]
+impl<T> PtrExt<T> for *mut T {
     #[inline]
+    #[deprecated = "call ptr::null instead"]
     fn null() -> *mut T { null_mut() }
 
     #[inline]
-    fn is_null(&self) -> bool { *self == RawPtr::null() }
+    #[stable]
+    fn is_null(self) -> bool { self as uint == 0 }
 
     #[inline]
-    fn to_uint(&self) -> uint { *self as uint }
+    #[deprecated = "use `as uint` instead"]
+    fn to_uint(self) -> uint { self as uint }
 
     #[inline]
+    #[stable]
     unsafe fn offset(self, count: int) -> *mut T {
         intrinsics::offset(self as *const T, count) as *mut T
     }
 
     #[inline]
+    #[unstable = "return value does not necessarily convey all possible \
+                  information"]
     unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
         if self.is_null() {
             None
@@ -339,8 +364,11 @@ impl<T> RawPtr<T> for *mut T {
     }
 }
 
-impl<T> RawMutPtr<T> for *mut T {
+#[stable]
+impl<T> MutPtrExt<T> for *mut T {
     #[inline]
+    #[unstable = "return value does not necessarily convey all possible \
+                  information"]
     unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> {
         if self.is_null() {
             None
@@ -351,6 +379,7 @@ impl<T> RawMutPtr<T> for *mut T {
 }
 
 // Equality for pointers
+#[stable]
 impl<T> PartialEq for *const T {
     #[inline]
     fn eq(&self, other: &*const T) -> bool {
@@ -360,8 +389,10 @@ impl<T> PartialEq for *const T {
     fn ne(&self, other: &*const T) -> bool { !self.eq(other) }
 }
 
+#[stable]
 impl<T> Eq for *const T {}
 
+#[stable]
 impl<T> PartialEq for *mut T {
     #[inline]
     fn eq(&self, other: &*mut T) -> bool {
@@ -371,6 +402,7 @@ impl<T> PartialEq for *mut T {
     fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
 }
 
+#[stable]
 impl<T> Eq for *mut T {}
 
 // Equivalence for pointers
@@ -411,6 +443,7 @@ mod externfnpointers {
     use mem;
     use cmp::PartialEq;
 
+    #[stable]
     impl<_R> PartialEq for extern "C" fn() -> _R {
         #[inline]
         fn eq(&self, other: &extern "C" fn() -> _R) -> bool {
@@ -421,6 +454,7 @@ mod externfnpointers {
     }
     macro_rules! fnptreq {
         ($($p:ident),*) => {
+            #[stable]
             impl<_R,$($p),*> PartialEq for extern "C" fn($($p),*) -> _R {
                 #[inline]
                 fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
@@ -440,6 +474,7 @@ mod externfnpointers {
 }
 
 // Comparison for pointers
+#[stable]
 impl<T> Ord for *const T {
     #[inline]
     fn cmp(&self, other: &*const T) -> Ordering {
@@ -453,6 +488,7 @@ impl<T> Ord for *const T {
     }
 }
 
+#[stable]
 impl<T> PartialOrd for *const T {
     #[inline]
     fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
@@ -472,6 +508,7 @@ impl<T> PartialOrd for *const T {
     fn ge(&self, other: &*const T) -> bool { *self >= *other }
 }
 
+#[stable]
 impl<T> Ord for *mut T {
     #[inline]
     fn cmp(&self, other: &*mut T) -> Ordering {
@@ -485,6 +522,7 @@ impl<T> Ord for *mut T {
     }
 }
 
+#[stable]
 impl<T> PartialOrd for *mut T {
     #[inline]
     fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
@@ -510,28 +548,33 @@ impl<T> PartialOrd for *mut T {
 /// raw `*mut T` (which conveys no particular ownership semantics).
 /// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
 /// internally use raw pointers to manage the memory that they own.
+#[unstable = "recently added to this module"]
 pub struct Unique<T>(pub *mut T);
 
 /// `Unique` pointers are `Send` if `T` is `Send` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
+#[unstable = "recently added to this module"]
 unsafe impl<T:Send> Send for Unique<T> { }
 
 /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
+#[unstable = "recently added to this module"]
 unsafe impl<T:Sync> Sync for Unique<T> { }
 
 impl<T> Unique<T> {
     /// Returns a null Unique.
+    #[unstable = "recently added to this module"]
     pub fn null() -> Unique<T> {
-        Unique(RawPtr::null())
+        Unique(null_mut())
     }
 
     /// Return an (unsafe) pointer into the memory owned by `self`.
+    #[unstable = "recently added to this module"]
     pub unsafe fn offset(self, offset: int) -> *mut T {
-        (self.0 as *const T).offset(offset) as *mut T
+        self.0.offset(offset)
     }
 }
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index c738f61e20a..3ebe191930b 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -332,7 +332,7 @@ impl<T, E> Result<T, E> {
 
     /// Convert from `Result<T, E>` to `Option<E>`
     ///
-    /// Converts `self` into an `Option<T>`, consuming `self`,
+    /// Converts `self` into an `Option<E>`, consuming `self`,
     /// and discarding the value, if any.
     ///
     /// # Example
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 26684864c4c..7d894ac697b 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -46,8 +46,10 @@ use num::Int;
 use ops::{FnMut, mod};
 use option::Option;
 use option::Option::{None, Some};
+use result::Result;
+use result::Result::{Ok, Err};
 use ptr;
-use ptr::RawPtr;
+use ptr::PtrExt;
 use mem;
 use mem::size_of;
 use kinds::{Sized, marker};
@@ -68,23 +70,23 @@ pub trait SliceExt<T> for Sized? {
     fn slice_to<'a>(&'a self, end: uint) -> &'a [T];
     fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]);
     fn iter<'a>(&'a self) -> Iter<'a, T>;
-    fn split<'a, P>(&'a self, pred: P) -> Splits<'a, T, P>
+    fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P>
                     where P: FnMut(&T) -> bool;
-    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, T, P>>
+    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P>
                      where P: FnMut(&T) -> bool;
-    fn rsplitn<'a, P>(&'a self,  n: uint, pred: P) -> SplitsN<Splits<'a, T, P>>
+    fn rsplitn<'a, P>(&'a self,  n: uint, pred: P) -> RSplitN<'a, T, P>
                       where P: FnMut(&T) -> bool;
     fn windows<'a>(&'a self, size: uint) -> Windows<'a, T>;
     fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T>;
     fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
-    fn head<'a>(&'a self) -> Option<&'a T>;
+    fn first<'a>(&'a self) -> Option<&'a T>;
     fn tail<'a>(&'a self) -> &'a [T];
     fn init<'a>(&'a self) -> &'a [T];
     fn last<'a>(&'a self) -> Option<&'a T>;
-    unsafe fn unsafe_get<'a>(&'a self, index: uint) -> &'a T;
+    unsafe fn get_unchecked<'a>(&'a self, index: uint) -> &'a T;
     fn as_ptr(&self) -> *const T;
-    fn binary_search<F>(&self, f: F) -> BinarySearchResult
-                        where F: FnMut(&T) -> Ordering;
+    fn binary_search_by<F>(&self, f: F) -> Result<uint, uint> where
+        F: FnMut(&T) -> Ordering;
     fn len(&self) -> uint;
     fn is_empty(&self) -> bool { self.len() == 0 }
     fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
@@ -93,21 +95,21 @@ pub trait SliceExt<T> for Sized? {
     fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T];
     fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T];
     fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T>;
-    fn head_mut<'a>(&'a mut self) -> Option<&'a mut T>;
+    fn first_mut<'a>(&'a mut self) -> Option<&'a mut T>;
     fn tail_mut<'a>(&'a mut self) -> &'a mut [T];
     fn init_mut<'a>(&'a mut self) -> &'a mut [T];
     fn last_mut<'a>(&'a mut self) -> Option<&'a mut T>;
-    fn split_mut<'a, P>(&'a mut self, pred: P) -> MutSplits<'a, T, P>
+    fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P>
                         where P: FnMut(&T) -> bool;
-    fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitsN<MutSplits<T, P>>
+    fn splitn_mut<P>(&mut self, n: uint, pred: P) -> SplitNMut<T, P>
                      where P: FnMut(&T) -> bool;
-    fn rsplitn_mut<P>(&mut self,  n: uint, pred: P) -> SplitsN<MutSplits<T, P>>
+    fn rsplitn_mut<P>(&mut self,  n: uint, pred: P) -> RSplitNMut<T, P>
                       where P: FnMut(&T) -> bool;
-    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> MutChunks<'a, T>;
+    fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> ChunksMut<'a, T>;
     fn swap(&mut self, a: uint, b: uint);
     fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]);
     fn reverse(&mut self);
-    unsafe fn unsafe_mut<'a>(&'a mut self, index: uint) -> &'a mut T;
+    unsafe fn get_unchecked_mut<'a>(&'a mut self, index: uint) -> &'a mut T;
     fn as_mut_ptr(&mut self) -> *mut T;
 }
 
@@ -145,11 +147,11 @@ impl<T> SliceExt<T> for [T] {
         unsafe {
             let p = self.as_ptr();
             if mem::size_of::<T>() == 0 {
-                Iter{ptr: p,
+                Iter {ptr: p,
                       end: (p as uint + self.len()) as *const T,
                       marker: marker::ContravariantLifetime::<'a>}
             } else {
-                Iter{ptr: p,
+                Iter {ptr: p,
                       end: p.offset(self.len() as int),
                       marker: marker::ContravariantLifetime::<'a>}
             }
@@ -157,8 +159,8 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn split<'a, P>(&'a self, pred: P) -> Splits<'a, T, P> where P: FnMut(&T) -> bool {
-        Splits {
+    fn split<'a, P>(&'a self, pred: P) -> Split<'a, T, P> where P: FnMut(&T) -> bool {
+        Split {
             v: self,
             pred: pred,
             finished: false
@@ -166,24 +168,28 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, T, P>> where
+    fn splitn<'a, P>(&'a self, n: uint, pred: P) -> SplitN<'a, T, P> where
         P: FnMut(&T) -> bool,
     {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: false
+        SplitN {
+            inner: GenericSplitN {
+                iter: self.split(pred),
+                count: n,
+                invert: false
+            }
         }
     }
 
     #[inline]
-    fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, T, P>> where
+    fn rsplitn<'a, P>(&'a self, n: uint, pred: P) -> RSplitN<'a, T, P> where
         P: FnMut(&T) -> bool,
     {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: true
+        RSplitN {
+            inner: GenericSplitN {
+                iter: self.split(pred),
+                count: n,
+                invert: true
+            }
         }
     }
 
@@ -205,7 +211,7 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head(&self) -> Option<&T> {
+    fn first(&self) -> Option<&T> {
         if self.len() == 0 { None } else { Some(&self[0]) }
     }
 
@@ -223,7 +229,7 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_get(&self, index: uint) -> &T {
+    unsafe fn get_unchecked(&self, index: uint) -> &T {
         transmute(self.repr().data.offset(index as int))
     }
 
@@ -233,14 +239,16 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[unstable]
-    fn binary_search<F>(&self, mut f: F) -> BinarySearchResult where F: FnMut(&T) -> Ordering {
+    fn binary_search_by<F>(&self, mut f: F) -> Result<uint, uint> where
+        F: FnMut(&T) -> Ordering
+    {
         let mut base : uint = 0;
         let mut lim : uint = self.len();
 
         while lim != 0 {
             let ix = base + (lim >> 1);
             match f(&self[ix]) {
-                Equal => return BinarySearchResult::Found(ix),
+                Equal => return Ok(ix),
                 Less => {
                     base = ix + 1;
                     lim -= 1;
@@ -249,7 +257,7 @@ impl<T> SliceExt<T> for [T] {
             }
             lim >>= 1;
         }
-        return BinarySearchResult::NotFound(base);
+        Err(base)
     }
 
     #[inline]
@@ -264,24 +272,26 @@ impl<T> SliceExt<T> for [T] {
     fn as_mut_slice(&mut self) -> &mut [T] { self }
 
     fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T] {
-        self[mut start..end]
+        ops::SliceMut::slice_or_fail_mut(self, &start, &end)
     }
 
     #[inline]
     fn slice_from_mut(&mut self, start: uint) -> &mut [T] {
-        self[mut start..]
+        ops::SliceMut::slice_from_or_fail_mut(self, &start)
     }
 
     #[inline]
     fn slice_to_mut(&mut self, end: uint) -> &mut [T] {
-        self[mut ..end]
+        ops::SliceMut::slice_to_or_fail_mut(self, &end)
     }
 
     #[inline]
     fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]) {
         unsafe {
             let self2: &mut [T] = mem::transmute_copy(&self);
-            (self[mut ..mid], self2[mut mid..])
+
+            (ops::SliceMut::slice_to_or_fail_mut(self, &mid),
+             ops::SliceMut::slice_from_or_fail_mut(self2, &mid))
         }
     }
 
@@ -290,11 +300,11 @@ impl<T> SliceExt<T> for [T] {
         unsafe {
             let p = self.as_mut_ptr();
             if mem::size_of::<T>() == 0 {
-                IterMut{ptr: p,
+                IterMut {ptr: p,
                          end: (p as uint + self.len()) as *mut T,
                          marker: marker::ContravariantLifetime::<'a>}
             } else {
-                IterMut{ptr: p,
+                IterMut {ptr: p,
                          end: p.offset(self.len() as int),
                          marker: marker::ContravariantLifetime::<'a>}
             }
@@ -309,53 +319,56 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    fn head_mut(&mut self) -> Option<&mut T> {
+    fn first_mut(&mut self) -> Option<&mut T> {
         if self.len() == 0 { None } else { Some(&mut self[0]) }
     }
 
     #[inline]
     fn tail_mut(&mut self) -> &mut [T] {
-        let len = self.len();
-        self[mut 1..len]
+        self.slice_from_mut(1)
     }
 
     #[inline]
     fn init_mut(&mut self) -> &mut [T] {
         let len = self.len();
-        self[mut 0..len - 1]
+        self.slice_to_mut(len-1)
     }
 
     #[inline]
-    fn split_mut<'a, P>(&'a mut self, pred: P) -> MutSplits<'a, T, P> where P: FnMut(&T) -> bool {
-        MutSplits { v: self, pred: pred, finished: false }
+    fn split_mut<'a, P>(&'a mut self, pred: P) -> SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
+        SplitMut { v: self, pred: pred, finished: false }
     }
 
     #[inline]
-    fn splitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitsN<MutSplits<'a, T, P>> where
+    fn splitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitNMut<'a, T, P> where
         P: FnMut(&T) -> bool
     {
-        SplitsN {
-            iter: self.split_mut(pred),
-            count: n,
-            invert: false
+        SplitNMut {
+            inner: GenericSplitN {
+                iter: self.split_mut(pred),
+                count: n,
+                invert: false
+            }
         }
     }
 
     #[inline]
-    fn rsplitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> SplitsN<MutSplits<'a, T, P>> where
+    fn rsplitn_mut<'a, P>(&'a mut self, n: uint, pred: P) -> RSplitNMut<'a, T, P> where
         P: FnMut(&T) -> bool,
     {
-        SplitsN {
-            iter: self.split_mut(pred),
-            count: n,
-            invert: true
+        RSplitNMut {
+            inner: GenericSplitN {
+                iter: self.split_mut(pred),
+                count: n,
+                invert: true
+            }
         }
    }
 
     #[inline]
-    fn chunks_mut(&mut self, chunk_size: uint) -> MutChunks<T> {
+    fn chunks_mut(&mut self, chunk_size: uint) -> ChunksMut<T> {
         assert!(chunk_size > 0);
-        MutChunks { v: self, chunk_size: chunk_size }
+        ChunksMut { v: self, chunk_size: chunk_size }
     }
 
     fn swap(&mut self, a: uint, b: uint) {
@@ -374,8 +387,8 @@ impl<T> SliceExt<T> for [T] {
         while i < ln / 2 {
             // Unsafe swap to avoid the bounds check in safe swap.
             unsafe {
-                let pa: *mut T = self.unsafe_mut(i);
-                let pb: *mut T = self.unsafe_mut(ln - i - 1);
+                let pa: *mut T = self.get_unchecked_mut(i);
+                let pb: *mut T = self.get_unchecked_mut(ln - i - 1);
                 ptr::swap(pa, pb);
             }
             i += 1;
@@ -383,7 +396,7 @@ impl<T> SliceExt<T> for [T] {
     }
 
     #[inline]
-    unsafe fn unsafe_mut(&mut self, index: uint) -> &mut T {
+    unsafe fn get_unchecked_mut(&mut self, index: uint) -> &mut T {
         transmute((self.repr().data as *mut T).offset(index as int))
     }
 
@@ -467,21 +480,26 @@ impl<T> ops::SliceMut<uint, [T]> for [T] {
 }
 
 /// Extension methods for slices containing `PartialEq` elements.
-#[unstable = "may merge with other traits"]
+#[unstable = "may merge with SliceExt"]
 pub trait PartialEqSliceExt<T: PartialEq> for Sized? {
     /// Find the first index containing a matching value.
+    #[experimental]
     fn position_elem(&self, t: &T) -> Option<uint>;
 
     /// Find the last index containing a matching value.
+    #[experimental]
     fn rposition_elem(&self, t: &T) -> Option<uint>;
 
     /// Return true if the slice contains an element with the given value.
+    #[stable]
     fn contains(&self, x: &T) -> bool;
 
     /// Returns true if `needle` is a prefix of the slice.
+    #[stable]
     fn starts_with(&self, needle: &[T]) -> bool;
 
     /// Returns true if `needle` is a suffix of the slice.
+    #[stable]
     fn ends_with(&self, needle: &[T]) -> bool;
 }
 
@@ -519,19 +537,16 @@ impl<T: PartialEq> PartialEqSliceExt<T> for [T] {
 #[unstable = "may merge with other traits"]
 #[allow(missing_docs)] // docs in libcollections
 pub trait OrdSliceExt<T: Ord> for Sized? {
-    #[unstable = "name likely to change"]
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult;
-    #[experimental]
+    fn binary_search(&self, x: &T) -> Result<uint, uint>;
     fn next_permutation(&mut self) -> bool;
-    #[experimental]
     fn prev_permutation(&mut self) -> bool;
 }
 
 #[unstable = "trait is unstable"]
 impl<T: Ord> OrdSliceExt<T> for [T] {
     #[unstable]
-    fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
-        self.binary_search(|p| p.cmp(x))
+    fn binary_search(&self, x: &T) -> Result<uint, uint> {
+        self.binary_search_by(|p| p.cmp(x))
     }
 
     #[experimental]
@@ -560,7 +575,7 @@ impl<T: Ord> OrdSliceExt<T> for [T] {
         self.swap(j, i-1);
 
         // Step 4: Reverse the (previously) weakly decreasing part
-        self[mut i..].reverse();
+        self.slice_from_mut(i).reverse();
 
         true
     }
@@ -582,7 +597,7 @@ impl<T: Ord> OrdSliceExt<T> for [T] {
         }
 
         // Step 2: Reverse the weakly increasing part
-        self[mut i..].reverse();
+        self.slice_from_mut(i).reverse();
 
         // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
         let mut j = self.len() - 1;
@@ -618,28 +633,30 @@ impl<T: Clone> CloneSliceExt<T> for [T] {
     }
 }
 
-//
+////////////////////////////////////////////////////////////////////////////////
 // Common traits
-//
+////////////////////////////////////////////////////////////////////////////////
 
 /// Data that is viewable as a slice.
-#[unstable = "may merge with other traits"]
+#[experimental = "will be replaced by slice syntax"]
 pub trait AsSlice<T> for Sized? {
     /// Work with `self` as a slice.
     fn as_slice<'a>(&'a self) -> &'a [T];
 }
 
-#[unstable = "trait is unstable"]
+#[experimental = "trait is experimental"]
 impl<T> AsSlice<T> for [T] {
     #[inline(always)]
     fn as_slice<'a>(&'a self) -> &'a [T] { self }
 }
 
+#[experimental = "trait is experimental"]
 impl<'a, T, Sized? U: AsSlice<T>> AsSlice<T> for &'a U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
 }
 
+#[experimental = "trait is experimental"]
 impl<'a, T, Sized? U: AsSlice<T>> AsSlice<T> for &'a mut U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
@@ -655,7 +672,7 @@ impl<'a, T> Default for &'a [T] {
 // Iterators
 //
 
-// The shared definition of the `Item` and `IterMut` iterators
+// The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
     (struct $name:ident -> $ptr:ty, $elem:ty) => {
         #[experimental = "needs review"]
@@ -735,9 +752,8 @@ macro_rules! make_slice {
     }}
 }
 
-
 /// Immutable slice iterator
-#[experimental = "needs review"]
+#[stable]
 pub struct Iter<'a, T: 'a> {
     ptr: *const T,
     end: *const T,
@@ -812,7 +828,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Iter<'a, T> {
 }
 
 /// Mutable slice iterator.
-#[experimental = "needs review"]
+#[stable]
 pub struct IterMut<'a, T: 'a> {
     ptr: *mut T,
     end: *mut T,
@@ -875,9 +891,9 @@ iterator!{struct IterMut -> *mut T, &'a mut T}
 #[experimental = "needs review"]
 impl<'a, T> ExactSizeIterator<&'a mut T> for IterMut<'a, T> {}
 
-/// An abstraction over the splitting iterators, so that splitn, splitn_mut etc
-/// can be implemented once.
-trait SplitsIter<E>: DoubleEndedIterator<E> {
+/// An internal abstraction over the splitting iterators, so that
+/// splitn, splitn_mut etc can be implemented once.
+trait SplitIter<E>: DoubleEndedIterator<E> {
     /// Mark the underlying iterator as complete, extracting the remaining
     /// portion of the slice.
     fn finish(&mut self) -> Option<E>;
@@ -885,8 +901,8 @@ trait SplitsIter<E>: DoubleEndedIterator<E> {
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function.
-#[experimental = "needs review"]
-pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool {
+#[stable]
+pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a [T],
     pred: P,
     finished: bool
@@ -894,9 +910,9 @@ pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool {
 
 // FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
 #[stable]
-impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool {
-    fn clone(&self) -> Splits<'a, T, P> {
-        Splits {
+impl<'a, T, P> Clone for Split<'a, T, P> where P: Clone + FnMut(&T) -> bool {
+    fn clone(&self) -> Split<'a, T, P> {
+        Split {
             v: self.v,
             pred: self.pred.clone(),
             finished: self.finished,
@@ -905,7 +921,7 @@ impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool {
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> Iterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> Iterator<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
         if self.finished { return None; }
@@ -931,7 +947,7 @@ impl<'a, T, P> Iterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
         if self.finished { return None; }
@@ -947,7 +963,7 @@ impl<'a, T, P> DoubleEndedIterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(
     }
 }
 
-impl<'a, T, P> SplitsIter<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> SplitIter<&'a [T]> for Split<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn finish(&mut self) -> Option<&'a [T]> {
         if self.finished { None } else { self.finished = true; Some(self.v) }
@@ -956,14 +972,14 @@ impl<'a, T, P> SplitsIter<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bo
 
 /// An iterator over the subslices of the vector which are separated
 /// by elements that match `pred`.
-#[experimental = "needs review"]
-pub struct MutSplits<'a, T:'a, P> where P: FnMut(&T) -> bool {
+#[stable]
+pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a mut [T],
     pred: P,
     finished: bool
 }
 
-impl<'a, T, P> SplitsIter<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> SplitIter<&'a mut [T]> for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn finish(&mut self) -> Option<&'a mut [T]> {
         if self.finished {
@@ -976,7 +992,7 @@ impl<'a, T, P> SplitsIter<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T) -> bool {
+impl<'a, T, P> Iterator<&'a mut [T]> for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
     #[inline]
     fn next(&mut self) -> Option<&'a mut [T]> {
         if self.finished { return None; }
@@ -990,7 +1006,7 @@ impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T)
             Some(idx) => {
                 let tmp = mem::replace(&mut self.v, &mut []);
                 let (head, tail) = tmp.split_at_mut(idx);
-                self.v = tail[mut 1..];
+                self.v = tail.slice_from_mut(1);
                 Some(head)
             }
         }
@@ -1009,7 +1025,7 @@ impl<'a, T, P> Iterator<&'a mut [T]> for MutSplits<'a, T, P> where P: FnMut(&T)
 }
 
 #[experimental = "needs review"]
-impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T, P> where
+impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for SplitMut<'a, T, P> where
     P: FnMut(&T) -> bool,
 {
     #[inline]
@@ -1026,23 +1042,23 @@ impl<'a, T, P> DoubleEndedIterator<&'a mut [T]> for MutSplits<'a, T, P> where
                 let tmp = mem::replace(&mut self.v, &mut []);
                 let (head, tail) = tmp.split_at_mut(idx);
                 self.v = head;
-                Some(tail[mut 1..])
+                Some(tail.slice_from_mut(1))
             }
         }
     }
 }
 
-/// An iterator over subslices separated by elements that match a predicate
-/// function, splitting at most a fixed number of times.
-#[experimental = "needs review"]
-pub struct SplitsN<I> {
+/// An private iterator over subslices separated by elements that
+/// match a predicate function, splitting at most a fixed number of
+/// times.
+struct GenericSplitN<I> {
     iter: I,
     count: uint,
     invert: bool
 }
 
 #[experimental = "needs review"]
-impl<E, I: SplitsIter<E>> Iterator<E> for SplitsN<I> {
+impl<E, I: SplitIter<E>> Iterator<E> for GenericSplitN<I> {
     #[inline]
     fn next(&mut self) -> Option<E> {
         if self.count == 0 {
@@ -1060,6 +1076,55 @@ impl<E, I: SplitsIter<E>> Iterator<E> for SplitsN<I> {
     }
 }
 
+/// An iterator over subslices separated by elements that match a predicate
+/// function, limited to a given number of splits.
+pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<Split<'a, T, P>>
+}
+
+/// An iterator over subslices separated by elements that match a
+/// predicate function, limited to a given number of splits, starting
+/// from the end of the slice.
+pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<Split<'a, T, P>>
+}
+
+/// An iterator over subslices separated by elements that match a predicate
+/// function, limited to a given number of splits.
+pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<SplitMut<'a, T, P>>
+}
+
+/// An iterator over subslices separated by elements that match a
+/// predicate function, limited to a given number of splits, starting
+/// from the end of the slice.
+pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
+    inner: GenericSplitN<SplitMut<'a, T, P>>
+}
+
+macro_rules! forward_iterator {
+    ($name:ident: $elem:ident, $iter_of:ty) => {
+        impl<'a, $elem, P> Iterator<$iter_of> for $name<'a, $elem, P> where
+            P: FnMut(&T) -> bool
+        {
+            #[inline]
+            fn next(&mut self) -> Option<$iter_of> {
+                self.inner.next()
+            }
+
+            #[inline]
+            fn size_hint(&self) -> (uint, Option<uint>) {
+                self.inner.size_hint()
+            }
+        }
+    }
+}
+
+forward_iterator! { SplitN: T, &'a [T] }
+forward_iterator! { RSplitN: T, &'a [T] }
+forward_iterator! { SplitNMut: T, &'a mut [T] }
+forward_iterator! { RSplitNMut: T, &'a mut [T] }
+
 /// An iterator over overlapping subslices of length `size`.
 #[deriving(Clone)]
 #[experimental = "needs review"]
@@ -1171,13 +1236,13 @@ impl<'a, T> RandomAccessIterator<&'a [T]> for Chunks<'a, T> {
 /// elements at a time). When the slice len is not evenly divided by the chunk
 /// size, the last slice of the iteration will be the remainder.
 #[experimental = "needs review"]
-pub struct MutChunks<'a, T:'a> {
+pub struct ChunksMut<'a, T:'a> {
     v: &'a mut [T],
     chunk_size: uint
 }
 
 #[experimental = "needs review"]
-impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
+impl<'a, T> Iterator<&'a mut [T]> for ChunksMut<'a, T> {
     #[inline]
     fn next(&mut self) -> Option<&'a mut [T]> {
         if self.v.len() == 0 {
@@ -1205,7 +1270,7 @@ impl<'a, T> Iterator<&'a mut [T]> for MutChunks<'a, T> {
 }
 
 #[experimental = "needs review"]
-impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
+impl<'a, T> DoubleEndedIterator<&'a mut [T]> for ChunksMut<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a mut [T]> {
         if self.v.len() == 0 {
@@ -1223,51 +1288,12 @@ impl<'a, T> DoubleEndedIterator<&'a mut [T]> for MutChunks<'a, T> {
 }
 
 
-
-/// The result of calling `binary_search`.
-///
-/// `Found` means the search succeeded, and the contained value is the
-/// index of the matching element. `NotFound` means the search
-/// succeeded, and the contained value is an index where a matching
-/// value could be inserted while maintaining sort order.
-#[deriving(Copy, PartialEq, Show)]
-#[experimental = "needs review"]
-pub enum BinarySearchResult {
-    /// The index of the found value.
-    Found(uint),
-    /// The index where the value should have been found.
-    NotFound(uint)
-}
-
-#[experimental = "needs review"]
-impl BinarySearchResult {
-    /// Converts a `Found` to `Some`, `NotFound` to `None`.
-    /// Similar to `Result::ok`.
-    pub fn found(&self) -> Option<uint> {
-        match *self {
-            BinarySearchResult::Found(i) => Some(i),
-            BinarySearchResult::NotFound(_) => None
-        }
-    }
-
-    /// Convert a `Found` to `None`, `NotFound` to `Some`.
-    /// Similar to `Result::err`.
-    pub fn not_found(&self) -> Option<uint> {
-        match *self {
-            BinarySearchResult::Found(_) => None,
-            BinarySearchResult::NotFound(i) => Some(i)
-        }
-    }
-}
-
-
-
 //
 // Free functions
 //
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable = "waiting for DST"]
+#[unstable]
 pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
     unsafe {
         transmute(RawSlice { data: s, len: 1 })
@@ -1275,7 +1301,7 @@ pub fn ref_slice<'a, A>(s: &'a A) -> &'a [A] {
 }
 
 /// Converts a pointer to A into a slice of length 1 (without copying).
-#[unstable = "waiting for DST"]
+#[unstable]
 pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
     unsafe {
         let ptr: *const A = transmute(s);
@@ -1309,7 +1335,7 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] {
 /// }
 /// ```
 #[inline]
-#[unstable = "just renamed from `mod raw`"]
+#[unstable = "should be renamed to from_raw_parts"]
 pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] {
     transmute(RawSlice { data: *p, len: len })
 }
@@ -1321,7 +1347,7 @@ pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] {
 /// not being able to provide a non-aliasing guarantee of the returned mutable
 /// slice.
 #[inline]
-#[unstable = "just renamed from `mod raw`"]
+#[unstable = "jshould be renamed to from_raw_parts_mut"]
 pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
     transmute(RawSlice { data: *p as *const T, len: len })
 }
@@ -1334,7 +1360,7 @@ pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
 #[deprecated]
 pub mod raw {
     use mem::transmute;
-    use ptr::RawPtr;
+    use ptr::PtrExt;
     use raw::Slice;
     use ops::FnOnce;
     use option::Option;
@@ -1436,7 +1462,7 @@ pub mod bytes {
 // Boilerplate traits
 //
 
-#[unstable = "waiting for DST"]
+#[stable]
 impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
     fn eq(&self, other: &[B]) -> bool {
         self.len() == other.len() &&
@@ -1448,7 +1474,7 @@ impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
     }
 }
 
-#[unstable = "waiting for DST"]
+#[stable]
 impl<T: Eq> Eq for [T] {}
 
 #[allow(deprecated)]
@@ -1465,14 +1491,14 @@ impl<'a,T:PartialEq, Sized? V: AsSlice<T>> Equiv<V> for &'a mut [T] {
     fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() }
 }
 
-#[unstable = "waiting for DST"]
+#[stable]
 impl<T: Ord> Ord for [T] {
     fn cmp(&self, other: &[T]) -> Ordering {
         order::cmp(self.iter(), other.iter())
     }
 }
 
-#[unstable = "waiting for DST"]
+#[stable]
 impl<T: PartialOrd> PartialOrd for [T] {
     #[inline]
     fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
@@ -1496,39 +1522,28 @@ impl<T: PartialOrd> PartialOrd for [T] {
     }
 }
 
-/// Extension methods for immutable slices containing integers.
+/// Extension methods for slices containing integers.
 #[experimental]
-pub trait ImmutableIntSlice<U, S> for Sized? {
+pub trait IntSliceExt<U, S> for Sized? {
     /// Converts the slice to an immutable slice of unsigned integers with the same width.
     fn as_unsigned<'a>(&'a self) -> &'a [U];
     /// Converts the slice to an immutable slice of signed integers with the same width.
     fn as_signed<'a>(&'a self) -> &'a [S];
-}
 
-/// Extension methods for mutable slices containing integers.
-#[experimental]
-pub trait MutableIntSlice<U, S> for Sized?: ImmutableIntSlice<U, S> {
     /// Converts the slice to a mutable slice of unsigned integers with the same width.
     fn as_unsigned_mut<'a>(&'a mut self) -> &'a mut [U];
     /// Converts the slice to a mutable slice of signed integers with the same width.
     fn as_signed_mut<'a>(&'a mut self) -> &'a mut [S];
 }
 
-macro_rules! impl_immut_int_slice {
+macro_rules! impl_int_slice {
     ($u:ty, $s:ty, $t:ty) => {
         #[experimental]
-        impl ImmutableIntSlice<$u, $s> for [$t] {
+        impl IntSliceExt<$u, $s> for [$t] {
             #[inline]
             fn as_unsigned(&self) -> &[$u] { unsafe { transmute(self) } }
             #[inline]
             fn as_signed(&self) -> &[$s] { unsafe { transmute(self) } }
-        }
-    }
-}
-macro_rules! impl_mut_int_slice {
-    ($u:ty, $s:ty, $t:ty) => {
-        #[experimental]
-        impl MutableIntSlice<$u, $s> for [$t] {
             #[inline]
             fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute(self) } }
             #[inline]
@@ -1537,17 +1552,15 @@ macro_rules! impl_mut_int_slice {
     }
 }
 
-macro_rules! impl_int_slice {
+macro_rules! impl_int_slices {
     ($u:ty, $s:ty) => {
-        impl_immut_int_slice! { $u, $s, $u }
-        impl_immut_int_slice! { $u, $s, $s }
-        impl_mut_int_slice! { $u, $s, $u }
-        impl_mut_int_slice! { $u, $s, $s }
+        impl_int_slice! { $u, $s, $u }
+        impl_int_slice! { $u, $s, $s }
     }
 }
 
-impl_int_slice! { u8,   i8 }
-impl_int_slice! { u16,  i16 }
-impl_int_slice! { u32,  i32 }
-impl_int_slice! { u64,  i64 }
-impl_int_slice! { uint, int }
+impl_int_slices! { u8,   i8  }
+impl_int_slices! { u16,  i16 }
+impl_int_slices! { u32,  i32 }
+impl_int_slices! { u64,  i64 }
+impl_int_slices! { uint, int }
diff --git a/src/libcore/str.rs b/src/libcore/str/mod.rs
index 204ffae6cbd..f4fe86a0d7e 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str/mod.rs
@@ -18,7 +18,6 @@
 
 use self::Searcher::{Naive, TwoWay, TwoWayLong};
 
-use clone::Clone;
 use cmp::{mod, Eq};
 use default::Default;
 use iter::range;
@@ -29,12 +28,76 @@ use mem;
 use num::Int;
 use ops::{Fn, FnMut};
 use option::Option::{mod, None, Some};
-use ptr::RawPtr;
+use ptr::PtrExt;
 use raw::{Repr, Slice};
 use result::Result::{mod, Ok, Err};
 use slice::{mod, SliceExt};
 use uint;
 
+macro_rules! delegate_iter {
+    (exact $te:ty in $ti:ty) => {
+        delegate_iter!{$te in $ti}
+        impl<'a> ExactSizeIterator<$te> for $ti {
+            #[inline]
+            fn rposition<P>(&mut self, predicate: P) -> Option<uint> where P: FnMut($te) -> bool{
+                self.0.rposition(predicate)
+            }
+            #[inline]
+            fn len(&self) -> uint {
+                self.0.len()
+            }
+        }
+    };
+    ($te:ty in $ti:ty) => {
+        impl<'a> Iterator<$te> for $ti {
+            #[inline]
+            fn next(&mut self) -> Option<$te> {
+                self.0.next()
+            }
+            #[inline]
+            fn size_hint(&self) -> (uint, Option<uint>) {
+                self.0.size_hint()
+            }
+        }
+        impl<'a> DoubleEndedIterator<$te> for $ti {
+            #[inline]
+            fn next_back(&mut self) -> Option<$te> {
+                self.0.next_back()
+            }
+        }
+    };
+    (pattern $te:ty in $ti:ty) => {
+        impl<'a, P: CharEq> Iterator<$te> for $ti {
+            #[inline]
+            fn next(&mut self) -> Option<$te> {
+                self.0.next()
+            }
+            #[inline]
+            fn size_hint(&self) -> (uint, Option<uint>) {
+                self.0.size_hint()
+            }
+        }
+        impl<'a, P: CharEq> DoubleEndedIterator<$te> for $ti {
+            #[inline]
+            fn next_back(&mut self) -> Option<$te> {
+                self.0.next_back()
+            }
+        }
+    };
+    (pattern forward $te:ty in $ti:ty) => {
+        impl<'a, P: CharEq> Iterator<$te> for $ti {
+            #[inline]
+            fn next(&mut self) -> Option<$te> {
+                self.0.next()
+            }
+            #[inline]
+            fn size_hint(&self) -> (uint, Option<uint>) {
+                self.0.size_hint()
+            }
+        }
+    }
+}
+
 /// A trait to abstract the idea of creating a new instance of a type from a
 /// string.
 // FIXME(#17307): there should be an `E` associated type for a `Result` return
@@ -333,29 +396,28 @@ impl<'a> DoubleEndedIterator<(uint, char)> for CharIndices<'a> {
 
 /// External iterator for a string's bytes.
 /// Use with the `std::iter` module.
+///
+/// Created with `StrExt::bytes`
 #[stable]
 #[deriving(Clone)]
-pub struct Bytes<'a> {
-    inner: Map<&'a u8, u8, slice::Iter<'a, u8>, BytesFn>,
-}
+pub struct Bytes<'a>(Map<&'a u8, u8, slice::Iter<'a, u8>, BytesDeref>);
+delegate_iter!{exact u8 in Bytes<'a>}
 
-/// A temporary new type wrapper that ensures that the `Bytes` iterator
+/// A temporary fn new type that ensures that the `Bytes` iterator
 /// is cloneable.
-#[deriving(Copy)]
-struct BytesFn(fn(&u8) -> u8);
+#[deriving(Copy, Clone)]
+struct BytesDeref;
 
-impl<'a> Fn(&'a u8) -> u8 for BytesFn {
+impl<'a> Fn(&'a u8) -> u8 for BytesDeref {
+    #[inline]
     extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
-        (self.0)(ptr)
+        *ptr
     }
 }
 
-impl Clone for BytesFn {
-    fn clone(&self) -> BytesFn { *self }
-}
-
 /// An iterator over the substrings of a string, separated by `sep`.
 #[deriving(Clone)]
+#[deprecated = "Type is now named `Split` or `SplitTerminator`"]
 pub struct CharSplits<'a, Sep> {
     /// The slice remaining to be iterated
     string: &'a str,
@@ -369,6 +431,7 @@ pub struct CharSplits<'a, Sep> {
 /// An iterator over the substrings of a string, separated by `sep`,
 /// splitting at most `count` times.
 #[deriving(Clone)]
+#[deprecated = "Type is now named `SplitN` or `RSplitN`"]
 pub struct CharSplitsN<'a, Sep> {
     iter: CharSplits<'a, Sep>,
     /// The number of splits remaining
@@ -790,12 +853,17 @@ pub struct MatchIndices<'a> {
 /// An iterator over the substrings of a string separated by a given
 /// search string
 #[deriving(Clone)]
-pub struct StrSplits<'a> {
+#[unstable = "Type might get removed"]
+pub struct SplitStr<'a> {
     it: MatchIndices<'a>,
     last_end: uint,
     finished: bool
 }
 
+/// Deprecated
+#[deprecated = "Type is now named `SplitStr`"]
+pub type StrSplits<'a> = SplitStr<'a>;
+
 impl<'a> Iterator<(uint, uint)> for MatchIndices<'a> {
     #[inline]
     fn next(&mut self) -> Option<(uint, uint)> {
@@ -810,7 +878,7 @@ impl<'a> Iterator<(uint, uint)> for MatchIndices<'a> {
     }
 }
 
-impl<'a> Iterator<&'a str> for StrSplits<'a> {
+impl<'a> Iterator<&'a str> for SplitStr<'a> {
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
         if self.finished { return None; }
@@ -829,6 +897,7 @@ impl<'a> Iterator<&'a str> for StrSplits<'a> {
     }
 }
 
+
 /*
 Section: Comparing strings
 */
@@ -958,7 +1027,7 @@ pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
 }
 
 // https://tools.ietf.org/html/rfc3629
-static UTF8_CHAR_WIDTH: [u8, ..256] = [
+static UTF8_CHAR_WIDTH: [u8; 256] = [
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -1004,7 +1073,7 @@ const TAG_CONT_U8: u8 = 0b1000_0000u8;
 /// Unsafe operations
 #[deprecated]
 pub mod raw {
-    use ptr::RawPtr;
+    use ptr::PtrExt;
     use raw::Slice;
     use slice::SliceExt;
     use str::StrExt;
@@ -1074,6 +1143,7 @@ pub mod traits {
     use ops;
     use str::{Str, StrExt, eq_slice};
 
+    #[stable]
     impl Ord for str {
         #[inline]
         fn cmp(&self, other: &str) -> Ordering {
@@ -1089,6 +1159,7 @@ pub mod traits {
         }
     }
 
+    #[stable]
     impl PartialEq for str {
         #[inline]
         fn eq(&self, other: &str) -> bool {
@@ -1098,8 +1169,10 @@ pub mod traits {
         fn ne(&self, other: &str) -> bool { !(*self).eq(other) }
     }
 
+    #[stable]
     impl Eq for str {}
 
+    #[stable]
     impl PartialOrd for str {
         #[inline]
         fn partial_cmp(&self, other: &str) -> Option<Ordering> {
@@ -1158,23 +1231,47 @@ impl<'a, Sized? S> Str for &'a S where S: Str {
     fn as_slice(&self) -> &str { Str::as_slice(*self) }
 }
 
+/// Return type of `StrExt::split`
+#[deriving(Clone)]
+#[stable]
+pub struct Split<'a, P>(CharSplits<'a, P>);
+delegate_iter!{pattern &'a str in Split<'a, P>}
+
+/// Return type of `StrExt::split_terminator`
+#[deriving(Clone)]
+#[unstable = "might get removed in favour of a constructor method on Split"]
+pub struct SplitTerminator<'a, P>(CharSplits<'a, P>);
+delegate_iter!{pattern &'a str in SplitTerminator<'a, P>}
+
+/// Return type of `StrExt::splitn`
+#[deriving(Clone)]
+#[stable]
+pub struct SplitN<'a, P>(CharSplitsN<'a, P>);
+delegate_iter!{pattern forward &'a str in SplitN<'a, P>}
+
+/// Return type of `StrExt::rsplitn`
+#[deriving(Clone)]
+#[stable]
+pub struct RSplitN<'a, P>(CharSplitsN<'a, P>);
+delegate_iter!{pattern forward &'a str in RSplitN<'a, P>}
+
 /// Methods for string slices
 #[allow(missing_docs)]
 pub trait StrExt for Sized? {
     // NB there are no docs here are they're all located on the StrExt trait in
     // libcollections, not here.
 
-    fn contains(&self, needle: &str) -> bool;
-    fn contains_char(&self, needle: char) -> bool;
+    fn contains(&self, pat: &str) -> bool;
+    fn contains_char<P: CharEq>(&self, pat: P) -> bool;
     fn chars<'a>(&'a self) -> Chars<'a>;
     fn bytes<'a>(&'a self) -> Bytes<'a>;
     fn char_indices<'a>(&'a self) -> CharIndices<'a>;
-    fn split<'a, Sep: CharEq>(&'a self, sep: Sep) -> CharSplits<'a, Sep>;
-    fn splitn<'a, Sep: CharEq>(&'a self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
-    fn split_terminator<'a, Sep: CharEq>(&'a self, sep: Sep) -> CharSplits<'a, Sep>;
-    fn rsplitn<'a, Sep: CharEq>(&'a self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
+    fn split<'a, P: CharEq>(&'a self, pat: P) -> Split<'a, P>;
+    fn splitn<'a, P: CharEq>(&'a self, count: uint, pat: P) -> SplitN<'a, P>;
+    fn split_terminator<'a, P: CharEq>(&'a self, pat: P) -> SplitTerminator<'a, P>;
+    fn rsplitn<'a, P: CharEq>(&'a self, count: uint, pat: P) -> RSplitN<'a, P>;
     fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a>;
-    fn split_str<'a>(&'a self, &'a str) -> StrSplits<'a>;
+    fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a>;
     fn lines<'a>(&'a self) -> Lines<'a>;
     fn lines_any<'a>(&'a self) -> LinesAny<'a>;
     fn char_len(&self) -> uint;
@@ -1183,20 +1280,20 @@ pub trait StrExt for Sized? {
     fn slice_to<'a>(&'a self, end: uint) -> &'a str;
     fn slice_chars<'a>(&'a self, begin: uint, end: uint) -> &'a str;
     unsafe fn slice_unchecked<'a>(&'a self, begin: uint, end: uint) -> &'a str;
-    fn starts_with(&self, needle: &str) -> bool;
-    fn ends_with(&self, needle: &str) -> bool;
-    fn trim_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
-    fn trim_left_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
-    fn trim_right_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
+    fn starts_with(&self, pat: &str) -> bool;
+    fn ends_with(&self, pat: &str) -> bool;
+    fn trim_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str;
+    fn trim_left_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str;
+    fn trim_right_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str;
     fn is_char_boundary(&self, index: uint) -> bool;
     fn char_range_at(&self, start: uint) -> CharRange;
     fn char_range_at_reverse(&self, start: uint) -> CharRange;
     fn char_at(&self, i: uint) -> char;
     fn char_at_reverse(&self, i: uint) -> char;
     fn as_bytes<'a>(&'a self) -> &'a [u8];
-    fn find<C: CharEq>(&self, search: C) -> Option<uint>;
-    fn rfind<C: CharEq>(&self, search: C) -> Option<uint>;
-    fn find_str(&self, &str) -> Option<uint>;
+    fn find<P: CharEq>(&self, pat: P) -> Option<uint>;
+    fn rfind<P: CharEq>(&self, pat: P) -> Option<uint>;
+    fn find_str(&self, pat: &str) -> Option<uint>;
     fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
     fn subslice_offset(&self, inner: &str) -> uint;
     fn as_ptr(&self) -> *const u8;
@@ -1218,8 +1315,8 @@ impl StrExt for str {
     }
 
     #[inline]
-    fn contains_char(&self, needle: char) -> bool {
-        self.find(needle).is_some()
+    fn contains_char<P: CharEq>(&self, pat: P) -> bool {
+        self.find(pat).is_some()
     }
 
     #[inline]
@@ -1229,9 +1326,7 @@ impl StrExt for str {
 
     #[inline]
     fn bytes(&self) -> Bytes {
-        fn deref(&x: &u8) -> u8 { x }
-
-        Bytes { inner: self.as_bytes().iter().map(BytesFn(deref)) }
+        Bytes(self.as_bytes().iter().map(BytesDeref))
     }
 
     #[inline]
@@ -1240,43 +1335,44 @@ impl StrExt for str {
     }
 
     #[inline]
-    fn split<Sep: CharEq>(&self, sep: Sep) -> CharSplits<Sep> {
-        CharSplits {
+    #[allow(deprecated)] // For using CharSplits
+    fn split<P: CharEq>(&self, pat: P) -> Split<P> {
+        Split(CharSplits {
             string: self,
-            only_ascii: sep.only_ascii(),
-            sep: sep,
+            only_ascii: pat.only_ascii(),
+            sep: pat,
             allow_trailing_empty: true,
             finished: false,
-        }
+        })
     }
 
     #[inline]
-    fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep)
-        -> CharSplitsN<Sep> {
-        CharSplitsN {
-            iter: self.split(sep),
+    #[allow(deprecated)] // For using CharSplitsN
+    fn splitn<P: CharEq>(&self, count: uint, pat: P) -> SplitN<P> {
+        SplitN(CharSplitsN {
+            iter: self.split(pat).0,
             count: count,
             invert: false,
-        }
+        })
     }
 
     #[inline]
-    fn split_terminator<Sep: CharEq>(&self, sep: Sep)
-        -> CharSplits<Sep> {
-        CharSplits {
+    #[allow(deprecated)] // For using CharSplits
+    fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
+        SplitTerminator(CharSplits {
             allow_trailing_empty: false,
-            ..self.split(sep)
-        }
+            ..self.split(pat).0
+        })
     }
 
     #[inline]
-    fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep)
-        -> CharSplitsN<Sep> {
-        CharSplitsN {
-            iter: self.split(sep),
+    #[allow(deprecated)] // For using CharSplitsN
+    fn rsplitn<P: CharEq>(&self, count: uint, pat: P) -> RSplitN<P> {
+        RSplitN(CharSplitsN {
+            iter: self.split(pat).0,
             count: count,
             invert: true,
-        }
+        })
     }
 
     #[inline]
@@ -1290,8 +1386,8 @@ impl StrExt for str {
     }
 
     #[inline]
-    fn split_str<'a>(&'a self, sep: &'a str) -> StrSplits<'a> {
-        StrSplits {
+    fn split_str<'a>(&'a self, sep: &'a str) -> SplitStr<'a> {
+        SplitStr {
             it: self.match_indices(sep),
             last_end: 0,
             finished: false
@@ -1300,7 +1396,7 @@ impl StrExt for str {
 
     #[inline]
     fn lines(&self) -> Lines {
-        Lines { inner: self.split_terminator('\n') }
+        Lines { inner: self.split_terminator('\n').0 }
     }
 
     fn lines_any(&self) -> LinesAny {
@@ -1393,12 +1489,12 @@ impl StrExt for str {
     }
 
     #[inline]
-    fn trim_chars<C: CharEq>(&self, mut to_trim: C) -> &str {
-        let cur = match self.find(|&mut: c: char| !to_trim.matches(c)) {
+    fn trim_matches<P: CharEq>(&self, mut pat: P) -> &str {
+        let cur = match self.find(|&mut: c: char| !pat.matches(c)) {
             None => "",
             Some(i) => unsafe { self.slice_unchecked(i, self.len()) }
         };
-        match cur.rfind(|&mut: c: char| !to_trim.matches(c)) {
+        match cur.rfind(|&mut: c: char| !pat.matches(c)) {
             None => "",
             Some(i) => {
                 let right = cur.char_range_at(i).next;
@@ -1408,16 +1504,16 @@ impl StrExt for str {
     }
 
     #[inline]
-    fn trim_left_chars<C: CharEq>(&self, mut to_trim: C) -> &str {
-        match self.find(|&mut: c: char| !to_trim.matches(c)) {
+    fn trim_left_matches<P: CharEq>(&self, mut pat: P) -> &str {
+        match self.find(|&mut: c: char| !pat.matches(c)) {
             None => "",
             Some(first) => unsafe { self.slice_unchecked(first, self.len()) }
         }
     }
 
     #[inline]
-    fn trim_right_chars<C: CharEq>(&self, mut to_trim: C) -> &str {
-        match self.rfind(|&mut: c: char| !to_trim.matches(c)) {
+    fn trim_right_matches<P: CharEq>(&self, mut pat: P) -> &str {
+        match self.rfind(|&mut: c: char| !pat.matches(c)) {
             None => "",
             Some(last) => {
                 let next = self.char_range_at(last).next;
@@ -1504,23 +1600,23 @@ impl StrExt for str {
         unsafe { mem::transmute(self) }
     }
 
-    fn find<C: CharEq>(&self, mut search: C) -> Option<uint> {
-        if search.only_ascii() {
-            self.bytes().position(|b| search.matches(b as char))
+    fn find<P: CharEq>(&self, mut pat: P) -> Option<uint> {
+        if pat.only_ascii() {
+            self.bytes().position(|b| pat.matches(b as char))
         } else {
             for (index, c) in self.char_indices() {
-                if search.matches(c) { return Some(index); }
+                if pat.matches(c) { return Some(index); }
             }
             None
         }
     }
 
-    fn rfind<C: CharEq>(&self, mut search: C) -> Option<uint> {
-        if search.only_ascii() {
-            self.bytes().rposition(|b| search.matches(b as char))
+    fn rfind<P: CharEq>(&self, mut pat: P) -> Option<uint> {
+        if pat.only_ascii() {
+            self.bytes().rposition(|b| pat.matches(b as char))
         } else {
             for (index, c) in self.char_indices().rev() {
-                if search.matches(c) { return Some(index); }
+                if pat.matches(c) { return Some(index); }
             }
             None
         }
@@ -1596,14 +1692,3 @@ impl<'a> DoubleEndedIterator<&'a str> for LinesAny<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
 }
-impl<'a> Iterator<u8> for Bytes<'a> {
-    #[inline]
-    fn next(&mut self) -> Option<u8> { self.inner.next() }
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
-}
-impl<'a> DoubleEndedIterator<u8> for Bytes<'a> {
-    #[inline]
-    fn next_back(&mut self) -> Option<u8> { self.inner.next_back() }
-}
-impl<'a> ExactSizeIterator<u8> for Bytes<'a> {}
diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs
index 270c5c59058..ad2323296d9 100644
--- a/src/libcore/tuple.rs
+++ b/src/libcore/tuple.rs
@@ -103,7 +103,7 @@ macro_rules! tuple_impls {
                 }
             }
 
-            #[unstable = "waiting for PartialEq to stabilize"]
+            #[stable]
             impl<$($T:PartialEq),+> PartialEq for ($($T,)+) {
                 #[inline]
                 fn eq(&self, other: &($($T,)+)) -> bool {
@@ -115,10 +115,10 @@ macro_rules! tuple_impls {
                 }
             }
 
-            #[unstable = "waiting for Eq to stabilize"]
+            #[stable]
             impl<$($T:Eq),+> Eq for ($($T,)+) {}
 
-            #[unstable = "waiting for PartialOrd to stabilize"]
+            #[stable]
             impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) {
                 #[inline]
                 fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
@@ -142,7 +142,7 @@ macro_rules! tuple_impls {
                 }
             }
 
-            #[unstable = "waiting for Ord to stabilize"]
+            #[stable]
             impl<$($T:Ord),+> Ord for ($($T,)+) {
                 #[inline]
                 fn cmp(&self, other: &($($T,)+)) -> Ordering {
diff --git a/src/libcoretest/any.rs b/src/libcoretest/any.rs
index 7c832e90ed9..e9e2028dc61 100644
--- a/src/libcoretest/any.rs
+++ b/src/libcoretest/any.rs
@@ -113,10 +113,10 @@ fn any_downcast_mut() {
 
 #[test]
 fn any_fixed_vec() {
-    let test = [0u, ..8];
+    let test = [0u; 8];
     let test = &test as &Any;
-    assert!(test.is::<[uint, ..8]>());
-    assert!(!test.is::<[uint, ..10]>());
+    assert!(test.is::<[uint; 8]>());
+    assert!(!test.is::<[uint; 10]>());
 }
 
 
diff --git a/src/libcoretest/atomic.rs b/src/libcoretest/atomic.rs
index ab9c7ab9f11..1fee304a976 100644
--- a/src/libcoretest/atomic.rs
+++ b/src/libcoretest/atomic.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use core::atomic::*;
+use core::atomic::Ordering::SeqCst;
 
 #[test]
 fn bool_() {
diff --git a/src/libcoretest/char.rs b/src/libcoretest/char.rs
index bed38f8c296..b931809e603 100644
--- a/src/libcoretest/char.rs
+++ b/src/libcoretest/char.rs
@@ -169,7 +169,7 @@ fn test_escape_unicode() {
 #[test]
 fn test_encode_utf8() {
     fn check(input: char, expect: &[u8]) {
-        let mut buf = [0u8, ..4];
+        let mut buf = [0u8; 4];
         let n = input.encode_utf8(buf.as_mut_slice()).unwrap_or(0);
         assert_eq!(buf[..n], expect);
     }
@@ -183,7 +183,7 @@ fn test_encode_utf8() {
 #[test]
 fn test_encode_utf16() {
     fn check(input: char, expect: &[u16]) {
-        let mut buf = [0u16, ..2];
+        let mut buf = [0u16; 2];
         let n = input.encode_utf16(buf.as_mut_slice()).unwrap_or(0);
         assert_eq!(buf[..n], expect);
     }
diff --git a/src/libcoretest/hash/sip.rs b/src/libcoretest/hash/sip.rs
index 8801c2975c8..431f7e748f6 100644
--- a/src/libcoretest/hash/sip.rs
+++ b/src/libcoretest/hash/sip.rs
@@ -33,7 +33,7 @@ impl<'a, S: Writer> Hash<S> for Bytes<'a> {
 #[test]
 #[allow(unused_must_use)]
 fn test_siphash() {
-    let vecs : [[u8, ..8], ..64] = [
+    let vecs : [[u8; 8]; 64] = [
         [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
         [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
         [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
@@ -107,7 +107,7 @@ fn test_siphash() {
     let mut state_inc = SipState::new_with_keys(k0, k1);
     let mut state_full = SipState::new_with_keys(k0, k1);
 
-    fn to_hex_str(r: &[u8, ..8]) -> String {
+    fn to_hex_str(r: &[u8; 8]) -> String {
         let mut s = String::new();
         for b in r.iter() {
             s.push_str(format!("{}", fmt::radix(*b, 16)).as_slice());
diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs
index dbbbaa5892c..d450e557383 100644
--- a/src/libcoretest/iter.rs
+++ b/src/libcoretest/iter.rs
@@ -19,7 +19,7 @@ use test::Bencher;
 
 #[test]
 fn test_lt() {
-    let empty: [int, ..0] = [];
+    let empty: [int; 0] = [];
     let xs = [1i,2,3];
     let ys = [1i,2,0];
 
@@ -781,7 +781,7 @@ fn test_peekable_is_empty() {
 
 #[test]
 fn test_min_max() {
-    let v: [int, ..0] = [];
+    let v: [int; 0] = [];
     assert_eq!(v.iter().min_max(), NoElements);
 
     let v = [1i];
diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs
index a8889ce9e34..430188c7e43 100644
--- a/src/libcoretest/ops.rs
+++ b/src/libcoretest/ops.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use test::Bencher;
-use core::ops::{Range, FullRange, RangeFrom};
+use core::ops::{Range, FullRange, RangeFrom, RangeTo};
 
 // Overhead of dtors
 
@@ -56,6 +56,12 @@ fn test_range_from() {
 }
 
 #[test]
+fn test_range_to() {
+    // Not much to test.
+    let _ = RangeTo { end: 42u };
+}
+
+#[test]
 fn test_full_range() {
     // Not much to test.
     let _ = FullRange;
diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs
index db3580e5d0c..162f75763de 100644
--- a/src/libcoretest/ptr.rs
+++ b/src/libcoretest/ptr.rs
@@ -165,8 +165,8 @@ fn test_ptr_subtraction() {
 
 #[test]
 fn test_set_memory() {
-    let mut xs = [0u8, ..20];
+    let mut xs = [0u8; 20];
     let ptr = xs.as_mut_ptr();
     unsafe { set_memory(ptr, 5u8, xs.len()); }
-    assert!(xs == [5u8, ..20]);
+    assert!(xs == [5u8; 20]);
 }
diff --git a/src/libcoretest/slice.rs b/src/libcoretest/slice.rs
index 987da903211..9ef7d603059 100644
--- a/src/libcoretest/slice.rs
+++ b/src/libcoretest/slice.rs
@@ -8,30 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::slice::BinarySearchResult::{Found, NotFound};
+use core::result::Result::{Ok, Err};
 
 #[test]
 fn binary_search_not_found() {
     let b = [1i, 2, 4, 6, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&6)) == Found(3));
+    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
     let b = [1i, 2, 4, 6, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3));
+    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
     let b = [1i, 2, 4, 6, 7, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&6)) == Found(3));
+    assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
     let b = [1i, 2, 4, 6, 7, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&5)) == NotFound(3));
+    assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
     let b = [1i, 2, 4, 6, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&8)) == Found(4));
+    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
     let b = [1i, 2, 4, 6, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(4));
+    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
     let b = [1i, 2, 4, 6, 7, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&8)) == Found(5));
+    assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
     let b = [1i, 2, 4, 5, 6, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&7)) == NotFound(5));
+    assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
     let b = [1i, 2, 4, 5, 6, 8, 9];
-    assert!(b.binary_search(|v| v.cmp(&0)) == NotFound(0));
+    assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
     let b = [1i, 2, 4, 5, 6, 8];
-    assert!(b.binary_search(|v| v.cmp(&9)) == NotFound(6));
+    assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
 }
 
 #[test]
diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs
index 8c4f74027a5..aa1550ae5b8 100644
--- a/src/libflate/lib.rs
+++ b/src/libflate/lib.rs
@@ -112,7 +112,7 @@ mod tests {
 
     #[test]
     fn test_flate_round_trip() {
-        let mut r = rand::task_rng();
+        let mut r = rand::thread_rng();
         let mut words = vec!();
         for _ in range(0u, 20) {
             let range = r.gen_range(1u, 10);
diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index 0426f269376..0db0bd413ac 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -578,7 +578,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
 
     fn f(_x: uint) -> Vec<Optval> { return Vec::new(); }
 
-    let mut vals = Vec::from_fn(n_opts, f);
+    let mut vals: Vec<_> = range(0, n_opts).map(f).collect();
     let mut free: Vec<String> = Vec::new();
     let l = args.len();
     let mut i = 0;
@@ -875,7 +875,7 @@ fn each_split_within<F>(ss: &str, lim: uint, mut it: F) -> bool where
         lim = fake_i;
     }
 
-    let machine: |&mut bool, (uint, char)| -> bool = |cont, (i, c)| {
+    let mut machine = |&mut: cont: &mut bool, (i, c): (uint, char)| -> bool {
         let whitespace = if c.is_whitespace() { Ws }       else { Cr };
         let limit      = if (i - slice_start + 1) <= lim  { UnderLim } else { OverLim };
 
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index 9574549a260..01e55fb2edd 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -740,7 +740,7 @@ mod tests {
     fn test_input(g: LabelledGraph) -> IoResult<String> {
         let mut writer = Vec::new();
         render(&g, &mut writer).unwrap();
-        (&mut writer[]).read_to_string()
+        (&mut writer.as_slice()).read_to_string()
     }
 
     // All of the tests use raw-strings as the format for the expected outputs,
@@ -852,7 +852,7 @@ r#"digraph hasse_diagram {
                  edge(1, 3, ";"),    edge(2, 3, ";"   )));
 
         render(&g, &mut writer).unwrap();
-        let r = (&mut writer[]).read_to_string();
+        let r = (&mut writer.as_slice()).read_to_string();
 
         assert_eq!(r.unwrap(),
 r#"digraph syntax_tree {
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index 7dcdc08943f..9faaedc45f3 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -425,20 +425,20 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr {
                     pub sa_family: sa_family_t,
-                    pub sa_data: [u8, ..14],
+                    pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_storage {
                     pub ss_family: sa_family_t,
                     pub __ss_align: i64,
-                    pub __ss_pad2: [u8, ..112],
+                    pub __ss_pad2: [u8; 112],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_in {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
-                    pub sin_zero: [u8, ..8],
+                    pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in_addr {
@@ -454,7 +454,7 @@ pub mod types {
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in6_addr {
-                    pub s6_addr: [u16, ..8]
+                    pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct ip_mreq {
@@ -491,7 +491,7 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_un {
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char, ..108]
+                    pub sun_path: [c_char; 108]
                 }
 
                 #[repr(C)]
@@ -609,7 +609,7 @@ pub mod types {
 
                 #[repr(C)]
                 #[deriving(Copy)] pub struct pthread_attr_t {
-                    pub __size: [u32, ..9]
+                    pub __size: [u32; 9]
                 }
             }
             #[cfg(target_arch = "arm")]
@@ -625,14 +625,14 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct stat {
                     pub st_dev: c_ulonglong,
-                    pub __pad0: [c_uchar, ..4],
+                    pub __pad0: [c_uchar; 4],
                     pub __st_ino: ino_t,
                     pub st_mode: c_uint,
                     pub st_nlink: c_uint,
                     pub st_uid: uid_t,
                     pub st_gid: gid_t,
                     pub st_rdev: c_ulonglong,
-                    pub __pad3: [c_uchar, ..4],
+                    pub __pad3: [c_uchar; 4],
                     pub st_size: c_longlong,
                     pub st_blksize: blksize_t,
                     pub st_blocks: c_ulonglong,
@@ -653,7 +653,7 @@ pub mod types {
 
                 #[repr(C)]
                 #[deriving(Copy)] pub struct pthread_attr_t {
-                    pub __size: [u32, ..9]
+                    pub __size: [u32; 9]
                 }
             }
             #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
@@ -670,14 +670,14 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct stat {
                     pub st_dev: c_ulong,
-                    pub st_pad1: [c_long, ..3],
+                    pub st_pad1: [c_long; 3],
                     pub st_ino: ino_t,
                     pub st_mode: mode_t,
                     pub st_nlink: nlink_t,
                     pub st_uid: uid_t,
                     pub st_gid: gid_t,
                     pub st_rdev: c_ulong,
-                    pub st_pad2: [c_long, ..2],
+                    pub st_pad2: [c_long; 2],
                     pub st_size: off_t,
                     pub st_pad3: c_long,
                     pub st_atime: time_t,
@@ -688,7 +688,7 @@ pub mod types {
                     pub st_ctime_nsec: c_long,
                     pub st_blksize: blksize_t,
                     pub st_blocks: blkcnt_t,
-                    pub st_pad5: [c_long, ..14],
+                    pub st_pad5: [c_long; 14],
                 }
 
                 #[repr(C)]
@@ -699,7 +699,7 @@ pub mod types {
 
                 #[repr(C)]
                 #[deriving(Copy)] pub struct pthread_attr_t {
-                    pub __size: [u32, ..9]
+                    pub __size: [u32; 9]
                 }
             }
             pub mod posix08 {}
@@ -714,7 +714,7 @@ pub mod types {
                     pub sll_hatype: c_ushort,
                     pub sll_pkttype: c_uchar,
                     pub sll_halen: c_uchar,
-                    pub sll_addr: [c_uchar, ..8]
+                    pub sll_addr: [c_uchar; 8]
                 }
             }
 
@@ -788,7 +788,7 @@ pub mod types {
                     pub st_mtime_nsec: c_long,
                     pub st_ctime: time_t,
                     pub st_ctime_nsec: c_long,
-                    pub __unused: [c_long, ..3],
+                    pub __unused: [c_long; 3],
                 }
 
                 #[repr(C)]
@@ -799,7 +799,7 @@ pub mod types {
 
                 #[repr(C)]
                 #[deriving(Copy)] pub struct pthread_attr_t {
-                    pub __size: [u64, ..7]
+                    pub __size: [u64; 7]
                 }
             }
             pub mod posix08 {
@@ -815,7 +815,7 @@ pub mod types {
                     pub sll_hatype: c_ushort,
                     pub sll_pkttype: c_uchar,
                     pub sll_halen: c_uchar,
-                    pub sll_addr: [c_uchar, ..8]
+                    pub sll_addr: [c_uchar; 8]
                 }
 
             }
@@ -878,15 +878,15 @@ pub mod types {
                 #[deriving(Copy)] pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
-                    pub sa_data: [u8, ..14],
+                    pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_storage {
                     pub ss_len: u8,
                     pub ss_family: sa_family_t,
-                    pub __ss_pad1: [u8, ..6],
+                    pub __ss_pad1: [u8; 6],
                     pub __ss_align: i64,
-                    pub __ss_pad2: [u8, ..112],
+                    pub __ss_pad2: [u8; 112],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_in {
@@ -894,7 +894,7 @@ pub mod types {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
-                    pub sin_zero: [u8, ..8],
+                    pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in_addr {
@@ -911,7 +911,7 @@ pub mod types {
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in6_addr {
-                    pub s6_addr: [u16, ..8]
+                    pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct ip_mreq {
@@ -938,7 +938,7 @@ pub mod types {
                 #[deriving(Copy)] pub struct sockaddr_un {
                     pub sun_len: u8,
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char, ..104]
+                    pub sun_path: [c_char; 104]
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct ifaddrs {
@@ -1030,7 +1030,7 @@ pub mod types {
                     pub st_lspare: int32_t,
                     pub st_birthtime: time_t,
                     pub st_birthtime_nsec: c_long,
-                    pub __unused: [uint8_t, ..2],
+                    pub __unused: [uint8_t; 2],
                 }
 
                 #[repr(C)]
@@ -1106,15 +1106,15 @@ pub mod types {
                 #[deriving(Copy)] pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
-                    pub sa_data: [u8, ..14],
+                    pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_storage {
                     pub ss_len: u8,
                     pub ss_family: sa_family_t,
-                    pub __ss_pad1: [u8, ..6],
+                    pub __ss_pad1: [u8; 6],
                     pub __ss_align: i64,
-                    pub __ss_pad2: [u8, ..112],
+                    pub __ss_pad2: [u8; 112],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_in {
@@ -1122,7 +1122,7 @@ pub mod types {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
-                    pub sin_zero: [u8, ..8],
+                    pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in_addr {
@@ -1139,7 +1139,7 @@ pub mod types {
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in6_addr {
-                    pub s6_addr: [u16, ..8]
+                    pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct ip_mreq {
@@ -1166,7 +1166,7 @@ pub mod types {
                 #[deriving(Copy)] pub struct sockaddr_un {
                     pub sun_len: u8,
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char, ..104]
+                    pub sun_path: [c_char; 104]
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct ifaddrs {
@@ -1337,21 +1337,21 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr {
                     pub sa_family: sa_family_t,
-                    pub sa_data: [u8, ..14],
+                    pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_storage {
                     pub ss_family: sa_family_t,
-                    pub __ss_pad1: [u8, ..6],
+                    pub __ss_pad1: [u8; 6],
                     pub __ss_align: i64,
-                    pub __ss_pad2: [u8, ..112],
+                    pub __ss_pad2: [u8; 112],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_in {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
-                    pub sin_zero: [u8, ..8],
+                    pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in_addr {
@@ -1367,7 +1367,7 @@ pub mod types {
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in6_addr {
-                    pub s6_addr: [u16, ..8]
+                    pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
                 #[deriving(Copy)] pub struct ip_mreq {
@@ -1393,7 +1393,7 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_un {
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char, ..108]
+                    pub sun_path: [c_char; 108]
                 }
             }
         }
@@ -1626,13 +1626,13 @@ pub mod types {
                     pub Data1: DWORD,
                     pub Data2: WORD,
                     pub Data3: WORD,
-                    pub Data4: [BYTE, ..8],
+                    pub Data4: [BYTE; 8],
                 }
 
                 #[repr(C)]
                 #[deriving(Copy)] pub struct WSAPROTOCOLCHAIN {
                     pub ChainLen: c_int,
-                    pub ChainEntries: [DWORD, ..MAX_PROTOCOL_CHAIN as uint],
+                    pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as uint],
                 }
 
                 pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
@@ -1658,7 +1658,7 @@ pub mod types {
                     pub iSecurityScheme: c_int,
                     pub dwMessageSize: DWORD,
                     pub dwProviderReserved: DWORD,
-                    pub szProtocol: [u8, ..(WSAPROTOCOL_LEN as uint) + 1u],
+                    pub szProtocol: [u8; (WSAPROTOCOL_LEN as uint) + 1u],
                 }
 
                 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
@@ -1675,8 +1675,8 @@ pub mod types {
                     pub nFileSizeLow: DWORD,
                     pub dwReserved0: DWORD,
                     pub dwReserved1: DWORD,
-                    pub cFileName: [wchar_t, ..260], // #define MAX_PATH 260
-                    pub cAlternateFileName: [wchar_t, ..14],
+                    pub cFileName: [wchar_t; 260], // #define MAX_PATH 260
+                    pub cAlternateFileName: [wchar_t; 14],
                 }
 
                 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
@@ -1741,16 +1741,16 @@ pub mod types {
                 #[deriving(Copy)] pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
-                    pub sa_data: [u8, ..14],
+                    pub sa_data: [u8; 14],
                 }
 
                 #[repr(C)]
                 #[deriving(Copy)] pub struct sockaddr_storage {
                     pub ss_len: u8,
                     pub ss_family: sa_family_t,
-                    pub __ss_pad1: [u8, ..6],
+                    pub __ss_pad1: [u8; 6],
                     pub __ss_align: i64,
-                    pub __ss_pad2: [u8, ..112],
+                    pub __ss_pad2: [u8; 112],
                 }
 
                 #[repr(C)]
@@ -1759,7 +1759,7 @@ pub mod types {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
-                    pub sin_zero: [u8, ..8],
+                    pub sin_zero: [u8; 8],
                 }
 
                 #[repr(C)]
@@ -1779,7 +1779,7 @@ pub mod types {
 
                 #[repr(C)]
                 #[deriving(Copy)] pub struct in6_addr {
-                    pub s6_addr: [u16, ..8]
+                    pub s6_addr: [u16; 8]
                 }
 
                 #[repr(C)]
@@ -1810,7 +1810,7 @@ pub mod types {
                 #[deriving(Copy)] pub struct sockaddr_un {
                     pub sun_len: u8,
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char, ..104]
+                    pub sun_path: [c_char; 104]
                 }
 
                 #[repr(C)]
@@ -1899,7 +1899,7 @@ pub mod types {
                     pub st_flags: uint32_t,
                     pub st_gen: uint32_t,
                     pub st_lspare: int32_t,
-                    pub st_qspare: [int64_t, ..2],
+                    pub st_qspare: [int64_t; 2],
                 }
 
                 #[repr(C)]
@@ -1911,7 +1911,7 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct pthread_attr_t {
                     pub __sig: c_long,
-                    pub __opaque: [c_char, ..36]
+                    pub __opaque: [c_char; 36]
                 }
             }
             pub mod posix08 {
@@ -2003,7 +2003,7 @@ pub mod types {
                     pub st_flags: uint32_t,
                     pub st_gen: uint32_t,
                     pub st_lspare: int32_t,
-                    pub st_qspare: [int64_t, ..2],
+                    pub st_qspare: [int64_t; 2],
                 }
 
                 #[repr(C)]
@@ -2015,7 +2015,7 @@ pub mod types {
                 #[repr(C)]
                 #[deriving(Copy)] pub struct pthread_attr_t {
                     pub __sig: c_long,
-                    pub __opaque: [c_char, ..56]
+                    pub __opaque: [c_char; 56]
                 }
             }
             pub mod posix08 {
diff --git a/src/liblog/directive.rs b/src/liblog/directive.rs
index 2b25a64affe..7e21f5f48f1 100644
--- a/src/liblog/directive.rs
+++ b/src/liblog/directive.rs
@@ -18,7 +18,7 @@ pub struct LogDirective {
     pub level: u32,
 }
 
-pub static LOG_LEVEL_NAMES: [&'static str, ..4] = ["ERROR", "WARN", "INFO",
+pub static LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO",
                                                "DEBUG"];
 
 /// Parse an individual log level that is either a number or a symbolic log level
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index 1d865868f18..b30938ae7f5 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -268,8 +268,6 @@ impl Drop for DefaultLogger {
     }
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// This function is called directly by the compiler when using the logging
 /// macros. This function does not take into account whether the log level
 /// specified is active or not, it will always log something if this method is
@@ -304,42 +302,6 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
     set_logger(logger);
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-/// This function is called directly by the compiler when using the logging
-/// macros. This function does not take into account whether the log level
-/// specified is active or not, it will always log something if this method is
-/// called.
-///
-/// It is not recommended to call this function directly, rather it should be
-/// invoked through the logging family of macros.
-#[doc(hidden)]
-pub fn log(level: u32, loc: &'static LogLocation, args: &fmt::Arguments) {
-    // Test the literal string from args against the current filter, if there
-    // is one.
-    match unsafe { FILTER.as_ref() } {
-        Some(filter) if !filter.is_match(args.to_string().as_slice()) => return,
-        _ => {}
-    }
-
-    // Completely remove the local logger from TLS in case anyone attempts to
-    // frob the slot while we're doing the logging. This will destroy any logger
-    // set during logging.
-    let mut logger = LOCAL_LOGGER.with(|s| {
-        s.borrow_mut().take()
-    }).unwrap_or_else(|| {
-        box DefaultLogger { handle: io::stderr() } as Box<Logger + Send>
-    });
-    logger.log(&LogRecord {
-        level: LogLevel(level),
-        args: *args,
-        file: loc.file,
-        module_path: loc.module_path,
-        line: loc.line,
-    });
-    set_logger(logger);
-}
-
 /// Getter for the global log level. This is a function so that it can be called
 /// safely
 #[doc(hidden)]
diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs
index 2e8302cc10f..233d1c049f4 100644
--- a/src/liblog/macros.rs
+++ b/src/liblog/macros.rs
@@ -12,8 +12,6 @@
 
 #![macro_escape]
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// The standard logging macro
 ///
 /// This macro will generically log over a provided level (of type u32) with a
@@ -67,61 +65,6 @@ macro_rules! log {
     })
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// The standard logging macro
-///
-/// This macro will generically log over a provided level (of type u32) with a
-/// format!-based argument list. See documentation in `std::fmt` for details on
-/// how to use the syntax.
-///
-/// # Example
-///
-/// ```
-/// #![feature(phase)]
-/// #[phase(plugin, link)] extern crate log;
-///
-/// fn main() {
-///     log!(log::WARN, "this is a warning {}", "message");
-///     log!(log::DEBUG, "this is a debug message");
-///     log!(6, "this is a custom logging level: {level}", level=6u);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=warn ./main
-/// WARN:main: this is a warning message
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=debug ./main
-/// DEBUG:main: this is a debug message
-/// WARN:main: this is a warning message
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=6 ./main
-/// DEBUG:main: this is a debug message
-/// WARN:main: this is a warning message
-/// 6:main: this is a custom logging level: 6
-/// ```
-#[macro_export]
-macro_rules! log {
-    ($lvl:expr, $($arg:tt)+) => ({
-        static LOC: ::log::LogLocation = ::log::LogLocation {
-            line: line!(),
-            file: file!(),
-            module_path: module_path!(),
-        };
-        let lvl = $lvl;
-        if log_enabled!(lvl) {
-            format_args!(|args| { ::log::log(lvl, &LOC, args) }, $($arg)+)
-        }
-    })
-}
-
 /// A convenience macro for logging at the error log level.
 ///
 /// # Example
diff --git a/src/librand/chacha.rs b/src/librand/chacha.rs
index c8d7b910424..8e6c7de305f 100644
--- a/src/librand/chacha.rs
+++ b/src/librand/chacha.rs
@@ -31,14 +31,14 @@ const CHACHA_ROUNDS: uint = 20; // Cryptographically secure from 8 upwards as of
 
 #[deriving(Copy)]
 pub struct ChaChaRng {
-    buffer:  [u32, ..STATE_WORDS], // Internal buffer of output
-    state:   [u32, ..STATE_WORDS], // Initial state
+    buffer:  [u32; STATE_WORDS], // Internal buffer of output
+    state:   [u32; STATE_WORDS], // Initial state
     index:   uint,                 // Index into state
 }
 
 static EMPTY: ChaChaRng = ChaChaRng {
-    buffer:  [0, ..STATE_WORDS],
-    state:   [0, ..STATE_WORDS],
+    buffer:  [0; STATE_WORDS],
+    state:   [0; STATE_WORDS],
     index:   STATE_WORDS
 };
 
@@ -68,7 +68,7 @@ macro_rules! double_round{
 }
 
 #[inline]
-fn core(output: &mut [u32, ..STATE_WORDS], input: &[u32, ..STATE_WORDS]) {
+fn core(output: &mut [u32; STATE_WORDS], input: &[u32; STATE_WORDS]) {
     *output = *input;
 
     for _ in range(0, CHACHA_ROUNDS / 2) {
@@ -86,7 +86,7 @@ impl ChaChaRng {
     /// fixed key of 8 zero words.
     pub fn new_unseeded() -> ChaChaRng {
         let mut rng = EMPTY;
-        rng.init(&[0, ..KEY_WORDS]);
+        rng.init(&[0; KEY_WORDS]);
         rng
     }
 
@@ -124,7 +124,7 @@ impl ChaChaRng {
     /// ```
     /// [1]: Daniel J. Bernstein. [*Extending the Salsa20
     /// nonce.*](http://cr.yp.to/papers.html#xsalsa)
-    fn init(&mut self, key: &[u32, ..KEY_WORDS]) {
+    fn init(&mut self, key: &[u32; KEY_WORDS]) {
         self.state[0] = 0x61707865;
         self.state[1] = 0x3320646E;
         self.state[2] = 0x79622D32;
@@ -174,7 +174,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
 
     fn reseed(&mut self, seed: &'a [u32]) {
         // reset state
-        self.init(&[0u32, ..KEY_WORDS]);
+        self.init(&[0u32; KEY_WORDS]);
         // set key in place
         let key = self.state.slice_mut(4, 4+KEY_WORDS);
         for (k, s) in key.iter_mut().zip(seed.iter()) {
@@ -195,7 +195,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
 
 impl Rand for ChaChaRng {
     fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
-        let mut key : [u32, ..KEY_WORDS] = [0, ..KEY_WORDS];
+        let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS];
         for word in key.iter_mut() {
             *word = other.gen();
         }
@@ -246,7 +246,7 @@ mod test {
     fn test_rng_true_values() {
         // Test vectors 1 and 2 from
         // http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
-        let seed : &[_] = &[0u32, ..8];
+        let seed : &[_] = &[0u32; 8];
         let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
 
         let v = Vec::from_fn(16, |_| ra.next_u32());
diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs
index da34b96505d..981b0eeee53 100644
--- a/src/librand/distributions/exponential.rs
+++ b/src/librand/distributions/exponential.rs
@@ -64,7 +64,7 @@ impl Rand for Exp1 {
 /// use std::rand::distributions::{Exp, IndependentSample};
 ///
 /// let exp = Exp::new(2.0);
-/// let v = exp.ind_sample(&mut rand::task_rng());
+/// let v = exp.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a Exp(2) distribution", v);
 /// ```
 #[deriving(Copy)]
diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs
index 21565224e57..378029d1f9b 100644
--- a/src/librand/distributions/gamma.rs
+++ b/src/librand/distributions/gamma.rs
@@ -44,7 +44,7 @@ use super::{IndependentSample, Sample, Exp};
 /// use std::rand::distributions::{IndependentSample, Gamma};
 ///
 /// let gamma = Gamma::new(2.0, 5.0);
-/// let v = gamma.ind_sample(&mut rand::task_rng());
+/// let v = gamma.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a Gamma(2, 5) distribution", v);
 /// ```
 ///
@@ -191,7 +191,7 @@ impl IndependentSample<f64> for GammaLargeShape {
 /// use std::rand::distributions::{ChiSquared, IndependentSample};
 ///
 /// let chi = ChiSquared::new(11.0);
-/// let v = chi.ind_sample(&mut rand::task_rng());
+/// let v = chi.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a χ²(11) distribution", v)
 /// ```
 pub struct ChiSquared {
@@ -248,7 +248,7 @@ impl IndependentSample<f64> for ChiSquared {
 /// use std::rand::distributions::{FisherF, IndependentSample};
 ///
 /// let f = FisherF::new(2.0, 32.0);
-/// let v = f.ind_sample(&mut rand::task_rng());
+/// let v = f.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from an F(2, 32) distribution", v)
 /// ```
 pub struct FisherF {
@@ -292,7 +292,7 @@ impl IndependentSample<f64> for FisherF {
 /// use std::rand::distributions::{StudentT, IndependentSample};
 ///
 /// let t = StudentT::new(11.0);
-/// let v = t.ind_sample(&mut rand::task_rng());
+/// let v = t.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a t(11) distribution", v)
 /// ```
 pub struct StudentT {
diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs
index d48c7b9aaa4..d0123d9c76c 100644
--- a/src/librand/distributions/mod.rs
+++ b/src/librand/distributions/mod.rs
@@ -96,7 +96,7 @@ pub struct Weighted<T> {
 ///                      Weighted { weight: 4, item: 'b' },
 ///                      Weighted { weight: 1, item: 'c' });
 /// let wc = WeightedChoice::new(items.as_mut_slice());
-/// let mut rng = rand::task_rng();
+/// let mut rng = rand::thread_rng();
 /// for _ in range(0u, 16) {
 ///      // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
 ///      println!("{}", wc.ind_sample(&mut rng));
diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs
index 140f34f67f5..543e236f96d 100644
--- a/src/librand/distributions/normal.rs
+++ b/src/librand/distributions/normal.rs
@@ -81,7 +81,7 @@ impl Rand for StandardNormal {
 ///
 /// // mean 2, standard deviation 3
 /// let normal = Normal::new(2.0, 3.0);
-/// let v = normal.ind_sample(&mut rand::task_rng());
+/// let v = normal.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a N(2, 9) distribution", v)
 /// ```
 #[deriving(Copy)]
@@ -129,7 +129,7 @@ impl IndependentSample<f64> for Normal {
 ///
 /// // mean 2, standard deviation 3
 /// let log_normal = LogNormal::new(2.0, 3.0);
-/// let v = log_normal.ind_sample(&mut rand::task_rng());
+/// let v = log_normal.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from an ln N(2, 9) distribution", v)
 /// ```
 #[deriving(Copy)]
diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs
index f23ad6a753b..558fa201256 100644
--- a/src/librand/distributions/range.rs
+++ b/src/librand/distributions/range.rs
@@ -39,7 +39,7 @@ use distributions::{Sample, IndependentSample};
 ///
 /// fn main() {
 ///     let between = Range::new(10u, 10000u);
-///     let mut rng = std::rand::task_rng();
+///     let mut rng = std::rand::thread_rng();
 ///     let mut sum = 0;
 ///     for _ in range(0u, 1000) {
 ///         sum += between.ind_sample(&mut rng);
diff --git a/src/librand/distributions/ziggurat_tables.rs b/src/librand/distributions/ziggurat_tables.rs
index 049ef3dbb59..a108fd70d1c 100644
--- a/src/librand/distributions/ziggurat_tables.rs
+++ b/src/librand/distributions/ziggurat_tables.rs
@@ -11,9 +11,9 @@
 // Tables for distributions which are sampled using the ziggurat
 // algorithm. Autogenerated by `ziggurat_tables.py`.
 
-pub type ZigTable = &'static [f64, .. 257];
+pub type ZigTable = &'static [f64; 257];
 pub static ZIG_NORM_R: f64 = 3.654152885361008796;
-pub static ZIG_NORM_X: [f64, .. 257] =
+pub static ZIG_NORM_X: [f64; 257] =
     [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074,
      3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434,
      2.978603279880844834, 2.934366867207854224, 2.894121053612348060, 2.857138730872132548,
@@ -79,7 +79,7 @@ pub static ZIG_NORM_X: [f64, .. 257] =
      0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746,
      0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806,
      0.000000000000000000];
-pub static ZIG_NORM_F: [f64, .. 257] =
+pub static ZIG_NORM_F: [f64; 257] =
     [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872,
      0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100,
      0.011842757857943104, 0.013497450601780807, 0.015177088307982072, 0.016880083152595839,
@@ -146,7 +146,7 @@ pub static ZIG_NORM_F: [f64, .. 257] =
      0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328,
      1.000000000000000000];
 pub static ZIG_EXP_R: f64 = 7.697117470131050077;
-pub static ZIG_EXP_X: [f64, .. 257] =
+pub static ZIG_EXP_X: [f64; 257] =
     [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696,
      6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488,
      5.323090505754398016, 5.181487281301500047, 5.054288489981304089, 4.938777085901250530,
@@ -212,7 +212,7 @@ pub static ZIG_EXP_X: [f64, .. 257] =
      0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842,
      0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570,
      0.000000000000000000];
-pub static ZIG_EXP_F: [f64, .. 257] =
+pub static ZIG_EXP_F: [f64; 257] =
     [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573,
      0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797,
      0.004877655983542396, 0.005619642207205489, 0.006381905937319183, 0.007163353183634991,
diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs
index d7ae91593a1..1ea47844075 100644
--- a/src/librand/isaac.rs
+++ b/src/librand/isaac.rs
@@ -32,8 +32,8 @@ const RAND_SIZE_UINT: uint = 1 << (RAND_SIZE_LEN as uint);
 #[deriving(Copy)]
 pub struct IsaacRng {
     cnt: u32,
-    rsl: [u32, ..RAND_SIZE_UINT],
-    mem: [u32, ..RAND_SIZE_UINT],
+    rsl: [u32; RAND_SIZE_UINT],
+    mem: [u32; RAND_SIZE_UINT],
     a: u32,
     b: u32,
     c: u32
@@ -41,8 +41,8 @@ pub struct IsaacRng {
 
 static EMPTY: IsaacRng = IsaacRng {
     cnt: 0,
-    rsl: [0, ..RAND_SIZE_UINT],
-    mem: [0, ..RAND_SIZE_UINT],
+    rsl: [0; RAND_SIZE_UINT],
+    mem: [0; RAND_SIZE_UINT],
     a: 0, b: 0, c: 0
 };
 
@@ -267,8 +267,8 @@ const RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN;
 #[deriving(Copy)]
 pub struct Isaac64Rng {
     cnt: uint,
-    rsl: [u64, .. RAND_SIZE_64],
-    mem: [u64, .. RAND_SIZE_64],
+    rsl: [u64; RAND_SIZE_64],
+    mem: [u64; RAND_SIZE_64],
     a: u64,
     b: u64,
     c: u64,
@@ -276,8 +276,8 @@ pub struct Isaac64Rng {
 
 static EMPTY_64: Isaac64Rng = Isaac64Rng {
     cnt: 0,
-    rsl: [0, .. RAND_SIZE_64],
-    mem: [0, .. RAND_SIZE_64],
+    rsl: [0; RAND_SIZE_64],
+    mem: [0; RAND_SIZE_64],
     a: 0, b: 0, c: 0,
 };
 
@@ -358,10 +358,10 @@ impl Isaac64Rng {
         let mut a = self.a;
         let mut b = self.b + self.c;
         const MIDPOINT: uint =  RAND_SIZE_64 / 2;
-        const MP_VEC: [(uint, uint), .. 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
+        const MP_VEC: [(uint, uint); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
         macro_rules! ind (
             ($x:expr) => {
-                *self.mem.unsafe_get(($x as uint >> 3) & (RAND_SIZE_64 - 1))
+                *self.mem.get_unchecked(($x as uint >> 3) & (RAND_SIZE_64 - 1))
             }
         );
 
@@ -375,13 +375,13 @@ impl Isaac64Rng {
                             let mix = if $j == 0 {!mix} else {mix};
 
                             unsafe {
-                                let x = *self.mem.unsafe_get(base + mr_offset);
-                                a = mix + *self.mem.unsafe_get(base + m2_offset);
+                                let x = *self.mem.get_unchecked(base + mr_offset);
+                                a = mix + *self.mem.get_unchecked(base + m2_offset);
                                 let y = ind!(x) + a + b;
-                                *self.mem.unsafe_mut(base + mr_offset) = y;
+                                *self.mem.get_unchecked_mut(base + mr_offset) = y;
 
                                 b = ind!(y >> RAND_SIZE_64_LEN) + x;
-                                *self.rsl.unsafe_mut(base + mr_offset) = b;
+                                *self.rsl.get_unchecked_mut(base + mr_offset) = b;
                             }
                         }}
                     );
@@ -392,13 +392,13 @@ impl Isaac64Rng {
                             let mix = if $j == 0 {!mix} else {mix};
 
                             unsafe {
-                                let x = *self.mem.unsafe_get(base + mr_offset);
-                                a = mix + *self.mem.unsafe_get(base + m2_offset);
+                                let x = *self.mem.get_unchecked(base + mr_offset);
+                                a = mix + *self.mem.get_unchecked(base + m2_offset);
                                 let y = ind!(x) + a + b;
-                                *self.mem.unsafe_mut(base + mr_offset) = y;
+                                *self.mem.get_unchecked_mut(base + mr_offset) = y;
 
                                 b = ind!(y >> RAND_SIZE_64_LEN) + x;
-                                *self.rsl.unsafe_mut(base + mr_offset) = b;
+                                *self.rsl.get_unchecked_mut(base + mr_offset) = b;
                             }
                         }}
                     );
diff --git a/src/librand/lib.rs b/src/librand/lib.rs
index 514ff81da51..568d2459118 100644
--- a/src/librand/lib.rs
+++ b/src/librand/lib.rs
@@ -138,10 +138,10 @@ pub trait Rng {
     /// # Example
     ///
     /// ```rust
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
-    /// let mut v = [0u8, .. 13579];
-    /// task_rng().fill_bytes(&mut v);
+    /// let mut v = [0u8; 13579];
+    /// thread_rng().fill_bytes(&mut v);
     /// println!("{}", v.as_slice());
     /// ```
     fn fill_bytes(&mut self, dest: &mut [u8]) {
@@ -173,9 +173,9 @@ pub trait Rng {
     /// # Example
     ///
     /// ```rust
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
-    /// let mut rng = task_rng();
+    /// let mut rng = thread_rng();
     /// let x: uint = rng.gen();
     /// println!("{}", x);
     /// println!("{}", rng.gen::<(f64, bool)>());
@@ -191,9 +191,9 @@ pub trait Rng {
     /// # Example
     ///
     /// ```
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
-    /// let mut rng = task_rng();
+    /// let mut rng = thread_rng();
     /// let x = rng.gen_iter::<uint>().take(10).collect::<Vec<uint>>();
     /// println!("{}", x);
     /// println!("{}", rng.gen_iter::<(f64, bool)>().take(5)
@@ -218,9 +218,9 @@ pub trait Rng {
     /// # Example
     ///
     /// ```rust
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
-    /// let mut rng = task_rng();
+    /// let mut rng = thread_rng();
     /// let n: uint = rng.gen_range(0u, 10);
     /// println!("{}", n);
     /// let m: f64 = rng.gen_range(-40.0f64, 1.3e5f64);
@@ -236,9 +236,9 @@ pub trait Rng {
     /// # Example
     ///
     /// ```rust
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
-    /// let mut rng = task_rng();
+    /// let mut rng = thread_rng();
     /// println!("{}", rng.gen_weighted_bool(3));
     /// ```
     fn gen_weighted_bool(&mut self, n: uint) -> bool {
@@ -250,9 +250,9 @@ pub trait Rng {
     /// # Example
     ///
     /// ```rust
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
-    /// let s: String = task_rng().gen_ascii_chars().take(10).collect();
+    /// let s: String = thread_rng().gen_ascii_chars().take(10).collect();
     /// println!("{}", s);
     /// ```
     fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
@@ -266,12 +266,13 @@ pub trait Rng {
     /// # Example
     ///
     /// ```
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
     /// let choices = [1i, 2, 4, 8, 16, 32];
-    /// let mut rng = task_rng();
+    /// let mut rng = thread_rng();
     /// println!("{}", rng.choose(&choices));
-    /// assert_eq!(rng.choose(choices[..0]), None);
+    /// # // replace with slicing syntax when it's stable!
+    /// assert_eq!(rng.choose(choices.slice_to(0)), None);
     /// ```
     fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
         if values.is_empty() {
@@ -286,9 +287,9 @@ pub trait Rng {
     /// # Example
     ///
     /// ```rust
-    /// use std::rand::{task_rng, Rng};
+    /// use std::rand::{thread_rng, Rng};
     ///
-    /// let mut rng = task_rng();
+    /// let mut rng = thread_rng();
     /// let mut y = [1i, 2, 3];
     /// rng.shuffle(&mut y);
     /// println!("{}", y.as_slice());
@@ -428,9 +429,9 @@ impl Rng for XorShiftRng {
     }
 }
 
-impl SeedableRng<[u32, .. 4]> for XorShiftRng {
+impl SeedableRng<[u32; 4]> for XorShiftRng {
     /// Reseed an XorShiftRng. This will panic if `seed` is entirely 0.
-    fn reseed(&mut self, seed: [u32, .. 4]) {
+    fn reseed(&mut self, seed: [u32; 4]) {
         assert!(!seed.iter().all(|&x| x == 0),
                 "XorShiftRng.reseed called with an all zero seed.");
 
@@ -441,7 +442,7 @@ impl SeedableRng<[u32, .. 4]> for XorShiftRng {
     }
 
     /// Create a new XorShiftRng. This will panic if `seed` is entirely 0.
-    fn from_seed(seed: [u32, .. 4]) -> XorShiftRng {
+    fn from_seed(seed: [u32; 4]) -> XorShiftRng {
         assert!(!seed.iter().all(|&x| x == 0),
                 "XorShiftRng::from_seed called with an all zero seed.");
 
@@ -520,8 +521,8 @@ mod test {
         }
     }
 
-    pub fn rng() -> MyRng<rand::TaskRng> {
-        MyRng { inner: rand::task_rng() }
+    pub fn rng() -> MyRng<rand::ThreadRng> {
+        MyRng { inner: rand::thread_rng() }
     }
 
     pub fn weak_rng() -> MyRng<rand::XorShiftRng> {
diff --git a/src/librand/rand_impls.rs b/src/librand/rand_impls.rs
index 937723aa5f5..c331807c1b9 100644
--- a/src/librand/rand_impls.rs
+++ b/src/librand/rand_impls.rs
@@ -215,7 +215,7 @@ impl<T:Rand> Rand for Option<T> {
 #[cfg(test)]
 mod tests {
     use std::prelude::v1::*;
-    use std::rand::{Rng, task_rng, Open01, Closed01};
+    use std::rand::{Rng, thread_rng, Open01, Closed01};
 
     struct ConstantRng(u64);
     impl Rng for ConstantRng {
@@ -240,7 +240,7 @@ mod tests {
     fn rand_open() {
         // this is unlikely to catch an incorrect implementation that
         // generates exactly 0 or 1, but it keeps it sane.
-        let mut rng = task_rng();
+        let mut rng = thread_rng();
         for _ in range(0u, 1_000) {
             // strict inequalities
             let Open01(f) = rng.gen::<Open01<f64>>();
@@ -253,7 +253,7 @@ mod tests {
 
     #[test]
     fn rand_closed() {
-        let mut rng = task_rng();
+        let mut rng = thread_rng();
         for _ in range(0u, 1_000) {
             // strict inequalities
             let Closed01(f) = rng.gen::<Closed01<f64>>();
diff --git a/src/librbml/io.rs b/src/librbml/io.rs
index b46b977d701..fd0c54e8ed3 100644
--- a/src/librbml/io.rs
+++ b/src/librbml/io.rs
@@ -11,6 +11,7 @@
 use std::io::{IoError, IoResult, SeekStyle};
 use std::io;
 use std::slice;
+use std::iter::repeat;
 
 static BUF_CAPACITY: uint = 128;
 
@@ -87,7 +88,7 @@ impl Writer for SeekableMemWriter {
             // currently are
             let difference = self.pos as i64 - self.buf.len() as i64;
             if difference > 0 {
-                self.buf.grow(difference as uint, 0);
+                self.buf.extend(repeat(0).take(difference as uint));
             }
 
             // Figure out what bytes will be used to overwrite what's currently
@@ -102,7 +103,7 @@ impl Writer for SeekableMemWriter {
 
             // Do the necessary writes
             if left.len() > 0 {
-                slice::bytes::copy_memory(self.buf[mut self.pos..], left);
+                slice::bytes::copy_memory(self.buf.slice_from_mut(self.pos), left);
             }
             if right.len() > 0 {
                 self.buf.push_all(right);
diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs
index 19e79b1eb7b..5bfe7e15a93 100644
--- a/src/librbml/lib.rs
+++ b/src/librbml/lib.rs
@@ -200,7 +200,7 @@ pub mod reader {
         // the most significant bit is set, the second most significant bit is set etc. we can
         // replace up to three "and+branch" with a single table lookup which gives us a measured
         // speedup of around 2x on x86_64.
-        static SHIFT_MASK_TABLE: [(uint, u32), ..16] = [
+        static SHIFT_MASK_TABLE: [(uint, u32); 16] = [
             (0, 0x0), (0, 0x0fffffff),
             (8, 0x1fffff), (8, 0x1fffff),
             (16, 0x3fff), (16, 0x3fff), (16, 0x3fff), (16, 0x3fff),
diff --git a/src/libregex/compile.rs b/src/libregex/compile.rs
index c361a25bf52..1476e6ab8a7 100644
--- a/src/libregex/compile.rs
+++ b/src/libregex/compile.rs
@@ -14,6 +14,7 @@
 pub use self::Inst::*;
 
 use std::cmp;
+use std::iter::repeat;
 use parse;
 use parse::{
     Flags, FLAG_EMPTY,
@@ -157,7 +158,7 @@ impl<'r> Compiler<'r> {
             Capture(cap, name, x) => {
                 let len = self.names.len();
                 if cap >= len {
-                    self.names.grow(10 + cap - len, None)
+                    self.names.extend(repeat(None).take(10 + cap - len))
                 }
                 self.names[cap] = name;
 
diff --git a/src/libregex/parse.rs b/src/libregex/parse.rs
index 105687b89fd..692a065299c 100644
--- a/src/libregex/parse.rs
+++ b/src/libregex/parse.rs
@@ -18,7 +18,6 @@ use std::cmp;
 use std::fmt;
 use std::iter;
 use std::num;
-use std::slice::BinarySearchResult;
 
 /// Static data containing Unicode ranges for general categories and scripts.
 use unicode::regex::{UNICODE_CLASSES, PERLD, PERLS, PERLW};
@@ -519,8 +518,8 @@ impl<'a> Parser<'a> {
             };
         self.chari = closer;
         let greed = try!(self.get_next_greedy());
-        let inner = String::from_chars(
-            self.chars[start+1..closer]);
+        let inner = self.chars[start+1..closer].iter().cloned()
+                                               .collect::<String>();
 
         // Parse the min and max values from the regex.
         let (mut min, mut max): (uint, Option<uint>);
@@ -954,7 +953,7 @@ impl<'a> Parser<'a> {
     }
 
     fn slice(&self, start: uint, end: uint) -> String {
-        String::from_chars(self.chars[start..end])
+        self.chars[start..end].iter().cloned().collect()
     }
 }
 
@@ -1028,9 +1027,9 @@ fn is_valid_cap(c: char) -> bool {
 }
 
 fn find_class(classes: NamedClasses, name: &str) -> Option<Vec<(char, char)>> {
-    match classes.binary_search(|&(s, _)| s.cmp(name)) {
-        BinarySearchResult::Found(i) => Some(classes[i].1.to_vec()),
-        BinarySearchResult::NotFound(_) => None,
+    match classes.binary_search_by(|&(s, _)| s.cmp(name)) {
+        Ok(i) => Some(classes[i].1.to_vec()),
+        Err(_) => None,
     }
 }
 
diff --git a/src/libregex/re.rs b/src/libregex/re.rs
index 1b6dcb3a8e2..3171966a596 100644
--- a/src/libregex/re.rs
+++ b/src/libregex/re.rs
@@ -540,6 +540,7 @@ impl Regex {
 
 }
 
+#[deriving(Clone)]
 pub enum NamesIter<'a> {
     NamesIterNative(::std::slice::Iter<'a, Option<&'static str>>),
     NamesIterDynamic(::std::slice::Iter<'a, Option<String>>)
@@ -596,6 +597,7 @@ impl<F> Replacer for F where F: FnMut(&Captures) -> String {
 ///
 /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime
 /// of the string being split.
+#[deriving(Clone)]
 pub struct RegexSplits<'r, 't> {
     finder: FindMatches<'r, 't>,
     last: uint,
@@ -629,6 +631,7 @@ impl<'r, 't> Iterator<&'t str> for RegexSplits<'r, 't> {
 ///
 /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime
 /// of the string being split.
+#[deriving(Clone)]
 pub struct RegexSplitsN<'r, 't> {
     splits: RegexSplits<'r, 't>,
     cur: uint,
@@ -792,6 +795,7 @@ impl<'t> Captures<'t> {
 /// expression.
 ///
 /// `'t` is the lifetime of the matched text.
+#[deriving(Clone)]
 pub struct SubCaptures<'t> {
     idx: uint,
     caps: &'t Captures<'t>,
@@ -814,6 +818,7 @@ impl<'t> Iterator<&'t str> for SubCaptures<'t> {
 /// Positions are byte indices in terms of the original string matched.
 ///
 /// `'t` is the lifetime of the matched text.
+#[deriving(Clone)]
 pub struct SubCapturesPos<'t> {
     idx: uint,
     caps: &'t Captures<'t>,
@@ -837,6 +842,7 @@ impl<'t> Iterator<Option<(uint, uint)>> for SubCapturesPos<'t> {
 ///
 /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime
 /// of the matched string.
+#[deriving(Clone)]
 pub struct FindCaptures<'r, 't> {
     re: &'r Regex,
     search: &'t str,
@@ -879,6 +885,7 @@ impl<'r, 't> Iterator<Captures<'t>> for FindCaptures<'r, 't> {
 ///
 /// `'r` is the lifetime of the compiled expression and `'t` is the lifetime
 /// of the matched string.
+#[deriving(Clone)]
 pub struct FindMatches<'r, 't> {
     re: &'r Regex,
     search: &'t str,
diff --git a/src/libregex/test/bench.rs b/src/libregex/test/bench.rs
index 0c204f759e6..17521ff7ea5 100644
--- a/src/libregex/test/bench.rs
+++ b/src/libregex/test/bench.rs
@@ -9,8 +9,9 @@
 // except according to those terms.
 #![allow(non_snake_case)]
 
-use std::rand::{Rng, task_rng};
+use std::rand::{Rng, thread_rng};
 use stdtest::Bencher;
+use std::iter::repeat;
 
 use regex::{Regex, NoExpand};
 
@@ -22,30 +23,30 @@ fn bench_assert_match(b: &mut Bencher, re: Regex, text: &str) {
 fn no_exponential(b: &mut Bencher) {
     let n = 100;
     let re = Regex::new(format!("{}{}",
-                                "a?".repeat(n),
-                                "a".repeat(n)).as_slice()).unwrap();
-    let text = "a".repeat(n);
+                                repeat("a?").take(n).collect::<String>(),
+                                repeat("a").take(n).collect::<String>()).as_slice()).unwrap();
+    let text = repeat("a").take(n).collect::<String>();
     bench_assert_match(b, re, text.as_slice());
 }
 
 #[bench]
 fn literal(b: &mut Bencher) {
     let re = regex!("y");
-    let text = format!("{}y", "x".repeat(50));
+    let text = format!("{}y", repeat("x").take(50).collect::<String>());
     bench_assert_match(b, re, text.as_slice());
 }
 
 #[bench]
 fn not_literal(b: &mut Bencher) {
     let re = regex!(".y");
-    let text = format!("{}y", "x".repeat(50));
+    let text = format!("{}y", repeat("x").take(50).collect::<String>());
     bench_assert_match(b, re, text.as_slice());
 }
 
 #[bench]
 fn match_class(b: &mut Bencher) {
     let re = regex!("[abcdw]");
-    let text = format!("{}w", "xxxx".repeat(20));
+    let text = format!("{}w", repeat("xxxx").take(20).collect::<String>());
     bench_assert_match(b, re, text.as_slice());
 }
 
@@ -53,7 +54,7 @@ fn match_class(b: &mut Bencher) {
 fn match_class_in_range(b: &mut Bencher) {
     // 'b' is between 'a' and 'c', so the class range checking doesn't help.
     let re = regex!("[ac]");
-    let text = format!("{}c", "bbbb".repeat(20));
+    let text = format!("{}c", repeat("bbbb").take(20).collect::<String>());
     bench_assert_match(b, re, text.as_slice());
 }
 
@@ -77,7 +78,7 @@ fn anchored_literal_short_non_match(b: &mut Bencher) {
 #[bench]
 fn anchored_literal_long_non_match(b: &mut Bencher) {
     let re = regex!("^zbc(d|e)");
-    let text = "abcdefghijklmnopqrstuvwxyz".repeat(15);
+    let text = repeat("abcdefghijklmnopqrstuvwxyz").take(15).collect::<String>();
     b.iter(|| re.is_match(text.as_slice()));
 }
 
@@ -91,7 +92,7 @@ fn anchored_literal_short_match(b: &mut Bencher) {
 #[bench]
 fn anchored_literal_long_match(b: &mut Bencher) {
     let re = regex!("^.bc(d|e)");
-    let text = "abcdefghijklmnopqrstuvwxyz".repeat(15);
+    let text = repeat("abcdefghijklmnopqrstuvwxyz").take(15).collect::<String>();
     b.iter(|| re.is_match(text.as_slice()));
 }
 
@@ -154,7 +155,7 @@ fn medium() -> Regex { regex!("[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
 fn hard() -> Regex { regex!("[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
 
 fn gen_text(n: uint) -> String {
-    let mut rng = task_rng();
+    let mut rng = thread_rng();
     let mut bytes = rng.gen_ascii_chars().map(|n| n as u8).take(n)
                        .collect::<Vec<u8>>();
     for (i, b) in bytes.iter_mut().enumerate() {
diff --git a/src/libregex/vm.rs b/src/libregex/vm.rs
index 0cdafb73b6e..603ca57d15d 100644
--- a/src/libregex/vm.rs
+++ b/src/libregex/vm.rs
@@ -39,6 +39,7 @@ pub use self::StepState::*;
 use std::cmp;
 use std::cmp::Ordering::{mod, Less, Equal, Greater};
 use std::mem;
+use std::iter::repeat;
 use std::slice::SliceExt;
 use compile::{
     Program,
@@ -122,7 +123,7 @@ impl<'r, 't> Nfa<'r, 't> {
         let mut clist = &mut Threads::new(self.which, ninsts, ncaps);
         let mut nlist = &mut Threads::new(self.which, ninsts, ncaps);
 
-        let mut groups = Vec::from_elem(ncaps * 2, None);
+        let mut groups: Vec<_> = repeat(None).take(ncaps * 2).collect();
 
         // Determine if the expression starts with a '^' so we can avoid
         // simulating .*?
@@ -228,8 +229,7 @@ impl<'r, 't> Nfa<'r, 't> {
                     let negate = flags & FLAG_NEGATED > 0;
                     let casei = flags & FLAG_NOCASE > 0;
                     let found = ranges.as_slice();
-                    let found = found.binary_search(|&rc| class_cmp(casei, c, rc))
-                        .found().is_some();
+                    let found = found.binary_search_by(|&rc| class_cmp(casei, c, rc)).is_ok();
                     if found ^ negate {
                         self.add(nlist, pc+1, caps);
                     }
@@ -458,10 +458,10 @@ impl Threads {
     fn new(which: MatchKind, num_insts: uint, ncaps: uint) -> Threads {
         Threads {
             which: which,
-            queue: Vec::from_fn(num_insts, |_| {
-                Thread { pc: 0, groups: Vec::from_elem(ncaps * 2, None) }
-            }),
-            sparse: Vec::from_elem(num_insts, 0u),
+            queue: range(0, num_insts).map(|_| {
+                Thread { pc: 0, groups: repeat(None).take(ncaps * 2).collect() }
+            }).collect(),
+            sparse: repeat(0u).take(num_insts).collect(),
             size: 0,
         }
     }
@@ -519,7 +519,7 @@ pub fn is_word(c: Option<char>) -> bool {
     // Try the common ASCII case before invoking binary search.
     match c {
         '_' | '0' ... '9' | 'a' ... 'z' | 'A' ... 'Z' => true,
-        _ => PERLW.binary_search(|&(start, end)| {
+        _ => PERLW.binary_search_by(|&(start, end)| {
             if c >= start && c <= end {
                 Equal
             } else if start > c {
@@ -527,7 +527,7 @@ pub fn is_word(c: Option<char>) -> bool {
             } else {
                 Less
             }
-        }).found().is_some()
+        }).is_ok()
     }
 }
 
diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs
index bf1095d21b2..0baa5e6c24f 100644
--- a/src/libregex_macros/lib.rs
+++ b/src/libregex_macros/lib.rs
@@ -169,7 +169,7 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
         chars: CharReader::new(input),
     }.run(start, end);
 
-    type Captures = [Option<uint>, ..$num_cap_locs];
+    type Captures = [Option<uint>; $num_cap_locs];
 
     struct Nfa<'t> {
         which: MatchKind,
@@ -250,8 +250,8 @@ fn exec<'t>(which: ::regex::native::MatchKind, input: &'t str,
 
     struct Threads {
         which: MatchKind,
-        queue: [Thread, ..$num_insts],
-        sparse: [uint, ..$num_insts],
+        queue: [Thread; $num_insts],
+        sparse: [uint; $num_insts],
         size: uint,
     }
 
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 602de8cd90d..5e74b90dba3 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -655,6 +655,7 @@ impl LintPass for UnusedAttributes {
             "static_assert",
             "thread_local",
             "no_debug",
+            "omit_gdb_pretty_printer_section",
             "unsafe_no_drop_flag",
 
             // used in resolve
@@ -818,7 +819,7 @@ impl NonCamelCaseTypes {
         fn is_camel_case(ident: ast::Ident) -> bool {
             let ident = token::get_ident(ident);
             if ident.get().is_empty() { return true; }
-            let ident = ident.get().trim_chars('_');
+            let ident = ident.get().trim_matches('_');
 
             // start with a non-lowercase letter rather than non-uppercase
             // ones (some scripts don't have a concept of upper/lowercase)
@@ -941,8 +942,8 @@ impl NonSnakeCase {
         fn is_snake_case(ident: ast::Ident) -> bool {
             let ident = token::get_ident(ident);
             if ident.get().is_empty() { return true; }
-            let ident = ident.get().trim_left_chars('\'');
-            let ident = ident.trim_chars('_');
+            let ident = ident.get().trim_left_matches('\'');
+            let ident = ident.trim_matches('_');
 
             let mut allow_underscore = true;
             ident.chars().all(|c| {
@@ -1682,33 +1683,7 @@ impl Stability {
     }
 
     fn is_internal(&self, cx: &Context, span: Span) -> bool {
-        // first, check if the given expression was generated by a macro or not
-        // we need to go back the expn_info tree to check only the arguments
-        // of the initial macro call, not the nested ones.
-        let mut expnid = span.expn_id;
-        let mut is_internal = false;
-        while cx.tcx.sess.codemap().with_expn_info(expnid, |expninfo| {
-            match expninfo {
-                Some(ref info) => {
-                    // save the parent expn_id for next loop iteration
-                    expnid = info.call_site.expn_id;
-                    if info.callee.span.is_none() {
-                        // it's a compiler built-in, we *really* don't want to mess with it
-                        // so we skip it, unless it was called by a regular macro, in which case
-                        // we will handle the caller macro next turn
-                        is_internal = true;
-                        true // continue looping
-                    } else {
-                        // was this expression from the current macro arguments ?
-                        is_internal = !( span.lo > info.call_site.lo &&
-                                         span.hi < info.call_site.hi );
-                        true // continue looping
-                    }
-                },
-                _ => false // stop looping
-            }
-        }) { /* empty while loop body */ }
-        return is_internal;
+        cx.tcx.sess.codemap().span_is_internal(span)
     }
 }
 
@@ -1783,9 +1758,9 @@ impl LintPass for Stability {
         if self.is_internal(cx, item.span) { return }
 
         match item.node {
-            ast::ItemTrait(_, _, _, ref supertraits, _) => {
+            ast::ItemTrait(_, _, ref supertraits, _) => {
                 for t in supertraits.iter() {
-                    if let ast::TraitTyParamBound(ref t) = *t {
+                    if let ast::TraitTyParamBound(ref t, _) = *t {
                         let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref);
                         self.lint(cx, id, t.trait_ref.path.span);
                     }
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 03e436e98df..2a58da8cb3b 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -256,3 +256,6 @@ pub const tag_predicate_space: uint = 0xa9;
 pub const tag_predicate_data: uint = 0xb0;
 
 pub const tag_unsafety: uint = 0xb1;
+
+pub const tag_associated_type_names: uint = 0xb2;
+pub const tag_associated_type_name: uint = 0xb3;
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 98b57511957..5dac2bafaec 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -14,6 +14,7 @@
 
 use back::svh::Svh;
 use session::{config, Session};
+use session::search_paths::PathKind;
 use metadata::cstore;
 use metadata::cstore::{CStore, CrateSource};
 use metadata::decoder;
@@ -134,7 +135,8 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
                                              info.ident[],
                                              info.name[],
                                              None,
-                                             i.span);
+                                             i.span,
+                                             PathKind::Crate);
             e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
         }
         None => ()
@@ -175,7 +177,7 @@ fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
 }
 
 pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
-    let err = |s: &str| {
+    let err = |&: s: &str| {
         match (sp, sess) {
             (_, None) => panic!("{}", s),
             (Some(sp), Some(sess)) => sess.span_err(sp, s),
@@ -388,12 +390,13 @@ fn register_crate<'a>(e: &mut Env,
     (cnum, cmeta, source)
 }
 
-fn resolve_crate<'a>(e: &mut Env,
+fn resolve_crate(e: &mut Env,
                  root: &Option<CratePaths>,
                  ident: &str,
                  name: &str,
                  hash: Option<&Svh>,
-                 span: Span)
+                 span: Span,
+                 kind: PathKind)
                      -> (ast::CrateNum, Rc<cstore::crate_metadata>,
                          cstore::CrateSource) {
     match existing_match(e, name, hash) {
@@ -404,7 +407,7 @@ fn resolve_crate<'a>(e: &mut Env,
                 ident: ident,
                 crate_name: name,
                 hash: hash.map(|a| &*a),
-                filesearch: e.sess.target_filesearch(),
+                filesearch: e.sess.target_filesearch(kind),
                 triple: e.sess.opts.target_triple[],
                 root: root,
                 rejected_via_hash: vec!(),
@@ -434,7 +437,8 @@ fn resolve_crate_deps(e: &mut Env,
                                                dep.name[],
                                                dep.name[],
                                                Some(&dep.hash),
-                                               span);
+                                               span,
+                                               PathKind::Dependency);
         (dep.cnum, local_cnum)
     }).collect()
 }
@@ -453,7 +457,8 @@ impl<'a> PluginMetadataReader<'a> {
         }
     }
 
-    pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata {
+    pub fn read_plugin_metadata(&mut self,
+                                krate: &ast::ViewItem) -> PluginMetadata {
         let info = extract_crate_info(&self.env, krate).unwrap();
         let target_triple = self.env.sess.opts.target_triple[];
         let is_cross = target_triple != config::host_triple();
@@ -464,7 +469,7 @@ impl<'a> PluginMetadataReader<'a> {
             ident: info.ident[],
             crate_name: info.name[],
             hash: None,
-            filesearch: self.env.sess.host_filesearch(),
+            filesearch: self.env.sess.host_filesearch(PathKind::Crate),
             triple: config::host_triple(),
             root: &None,
             rejected_via_hash: vec!(),
@@ -477,7 +482,7 @@ impl<'a> PluginMetadataReader<'a> {
                 // try loading from target crates (only valid if there are
                 // no syntax extensions)
                 load_ctxt.triple = target_triple;
-                load_ctxt.filesearch = self.env.sess.target_filesearch();
+                load_ctxt.filesearch = self.env.sess.target_filesearch(PathKind::Crate);
                 let lib = load_ctxt.load_library_crate();
                 if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() {
                     let message = format!("crate `{}` contains a plugin_registrar fn but \
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 51cebbfb52c..2b11b8517b0 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -62,7 +62,7 @@ pub fn each_child_of_item<F>(cstore: &cstore::CStore,
     F: FnMut(decoder::DefLike, ast::Name, ast::Visibility),
 {
     let crate_data = cstore.get_crate_data(def_id.krate);
-    let get_crate_data: decoder::GetCrateDataCb = |cnum| {
+    let get_crate_data = |&mut: cnum| {
         cstore.get_crate_data(cnum)
     };
     decoder::each_child_of_item(cstore.intr.clone(),
@@ -79,7 +79,7 @@ pub fn each_top_level_item_of_crate<F>(cstore: &cstore::CStore,
     F: FnMut(decoder::DefLike, ast::Name, ast::Visibility),
 {
     let crate_data = cstore.get_crate_data(cnum);
-    let get_crate_data: decoder::GetCrateDataCb = |cnum| {
+    let get_crate_data = |&mut: cnum| {
         cstore.get_crate_data(cnum)
     };
     decoder::each_top_level_item_of_crate(cstore.intr.clone(),
@@ -226,7 +226,7 @@ pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: ast::DefId) -> HashM
 
 pub fn get_type<'tcx>(tcx: &ty::ctxt<'tcx>,
                       def: ast::DefId)
-                      -> ty::Polytype<'tcx> {
+                      -> ty::TypeScheme<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_type(&*cdata, def.node, tcx)
@@ -239,7 +239,7 @@ pub fn get_trait_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId) -> ty::TraitDe
 }
 
 pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
-                            def: ast::DefId) -> ty::Polytype<'tcx> {
+                            def: ast::DefId) -> ty::TypeScheme<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(class_id.krate);
     let all_items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
@@ -257,7 +257,7 @@ pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: ast::DefId,
                     def)).to_string()
         });
     let ty = decoder::item_type(def, the_field, tcx, &*cdata);
-    ty::Polytype {
+    ty::TypeScheme {
         generics: ty::Generics::empty(),
         ty: ty,
     }
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 567c3f5e752..70325294743 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -174,14 +174,15 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
 }
 
 fn item_sort(item: rbml::Doc) -> char {
-    // NB(pcwalton): The default of 'r' here is relied upon in
-    // `is_associated_type` below.
-    let mut ret = 'r';
+    let mut ret = None;
     reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
-        ret = doc.as_str_slice().as_bytes()[0] as char;
+        ret = Some(doc.as_str_slice().as_bytes()[0] as char);
         false
     });
-    ret
+    match ret {
+        Some(r) => r,
+        None => panic!("No item_sort found")
+    }
 }
 
 fn item_symbol(item: rbml::Doc) -> String {
@@ -247,13 +248,13 @@ pub fn item_type<'tcx>(_item_id: ast::DefId, item: rbml::Doc,
 }
 
 fn doc_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
-                       -> ty::TraitRef<'tcx> {
+                       -> Rc<ty::TraitRef<'tcx>> {
     parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx,
                          |_, did| translate_def_id(cdata, did))
 }
 
 fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
-                        -> ty::TraitRef<'tcx> {
+                        -> Rc<ty::TraitRef<'tcx>> {
     let tp = reader::get_doc(doc, tag_item_trait_ref);
     doc_trait_ref(tp, tcx, cdata)
 }
@@ -371,6 +372,17 @@ fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety {
     }
 }
 
+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();
+    reader::tagged_docs(names_doc, tag_associated_type_name, |name_doc| {
+        let name = token::intern(name_doc.as_str_slice());
+        names.push(name);
+        true
+    });
+    names
+}
+
 pub fn get_trait_def<'tcx>(cdata: Cmd,
                            item_id: ast::NodeId,
                            tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx>
@@ -379,17 +391,19 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
     let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
     let bounds = trait_def_bounds(item_doc, tcx, cdata);
     let unsafety = parse_unsafety(item_doc);
+    let associated_type_names = parse_associated_type_names(item_doc);
 
     ty::TraitDef {
         unsafety: unsafety,
         generics: generics,
         bounds: bounds,
-        trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))
+        trait_ref: item_trait_ref(item_doc, tcx, cdata),
+        associated_type_names: associated_type_names,
     }
 }
 
 pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
-    -> ty::Polytype<'tcx> {
+    -> ty::TypeScheme<'tcx> {
 
     let item = lookup_item(id, cdata.data());
 
@@ -398,7 +412,7 @@ pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
 
     let generics = doc_generics(item, tcx, cdata, tag_item_generics);
 
-    ty::Polytype {
+    ty::TypeScheme {
         generics: generics,
         ty: t
     }
@@ -430,7 +444,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
 {
     let item_doc = lookup_item(id, cdata.data());
     reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
-        Rc::new(doc_trait_ref(tp, tcx, cdata))
+        doc_trait_ref(tp, tcx, cdata)
     })
 }
 
@@ -475,14 +489,13 @@ pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where
     })
 }
 
-pub type GetCrateDataCb<'a> = |ast::CrateNum|: 'a -> Rc<crate_metadata>;
-
-fn each_child_of_item_or_crate<F>(intr: Rc<IdentInterner>,
-                                  cdata: Cmd,
-                                  item_doc: rbml::Doc,
-                                  get_crate_data: GetCrateDataCb,
-                                  mut callback: F) where
+fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
+                                     cdata: Cmd,
+                                     item_doc: rbml::Doc,
+                                     mut get_crate_data: G,
+                                     mut callback: F) where
     F: FnMut(DefLike, ast::Name, ast::Visibility),
+    G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
 {
     // Iterate over all children.
     let _ = reader::tagged_docs(item_doc, tag_mod_child, |child_info_doc| {
@@ -596,12 +609,13 @@ fn each_child_of_item_or_crate<F>(intr: Rc<IdentInterner>,
 }
 
 /// Iterates over each child of the given item.
-pub fn each_child_of_item<F>(intr: Rc<IdentInterner>,
-                             cdata: Cmd,
-                             id: ast::NodeId,
-                             get_crate_data: GetCrateDataCb,
-                             callback: F) where
+pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>,
+                               cdata: Cmd,
+                               id: ast::NodeId,
+                               get_crate_data: G,
+                               callback: F) where
     F: FnMut(DefLike, ast::Name, ast::Visibility),
+    G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
 {
     // Find the item.
     let root_doc = rbml::Doc::new(cdata.data());
@@ -619,11 +633,12 @@ pub fn each_child_of_item<F>(intr: Rc<IdentInterner>,
 }
 
 /// Iterates over all the top-level crate items.
-pub fn each_top_level_item_of_crate<F>(intr: Rc<IdentInterner>,
-                                       cdata: Cmd,
-                                       get_crate_data: GetCrateDataCb,
-                                       callback: F) where
+pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>,
+                                          cdata: Cmd,
+                                          get_crate_data: G,
+                                          callback: F) where
     F: FnMut(DefLike, ast::Name, ast::Visibility),
+    G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
 {
     let root_doc = rbml::Doc::new(cdata.data());
     let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
@@ -926,7 +941,7 @@ pub fn get_supertraits<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
         // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place.
         let trait_ref = doc_trait_ref(trait_doc, tcx, cdata);
         if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() {
-            results.push(Rc::new(trait_ref));
+            results.push(trait_ref);
         }
         true
     });
@@ -1355,7 +1370,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd)
         if spec.len() == 0 { continue }
         let cnum = spec.split(':').nth(0).unwrap();
         let link = spec.split(':').nth(1).unwrap();
-        let cnum = cnum.parse().unwrap();
+        let cnum: ast::CrateNum = cnum.parse().unwrap();
         let cnum = match cdata.cnum_map.get(&cnum) {
             Some(&n) => n,
             None => panic!("didn't find a crate in the cnum_map")
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 6782b3a7481..8378c620c1d 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -142,7 +142,7 @@ fn encode_item_variances(rbml_w: &mut Encoder,
 
 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
                                     ecx: &EncodeContext<'a, 'tcx>,
-                                    pty: &ty::Polytype<'tcx>) {
+                                    pty: &ty::TypeScheme<'tcx>) {
     encode_generics(rbml_w, ecx, &pty.generics, tag_item_generics);
     encode_type(ecx, rbml_w, pty.ty);
 }
@@ -898,7 +898,10 @@ fn encode_info_for_associated_type(ecx: &EncodeContext,
     encode_visibility(rbml_w, associated_type.vis);
     encode_family(rbml_w, 'y');
     encode_parent_item(rbml_w, local_def(parent_id));
-    encode_item_sort(rbml_w, 'r');
+    encode_item_sort(rbml_w, 't');
+
+    let type_scheme = ty::lookup_item_type(ecx.tcx, associated_type.def_id);
+    encode_bounds_and_type(rbml_w, ecx, &type_scheme);
 
     let stab = stability::lookup(ecx.tcx, associated_type.def_id);
     encode_stability(rbml_w, stab);
@@ -1308,7 +1311,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
         }
       }
-      ast::ItemTrait(_, _, _, _, ref ms) => {
+      ast::ItemTrait(_, _, _, ref ms) => {
         add_to_index(item, rbml_w, index);
         rbml_w.start_tag(tag_items_data_item);
         encode_def_id(rbml_w, def_id);
@@ -1316,6 +1319,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_item_variances(rbml_w, ecx, item.id);
         let trait_def = ty::lookup_trait_def(tcx, def_id);
         encode_unsafety(rbml_w, trait_def.unsafety);
+        encode_associated_type_names(rbml_w, trait_def.associated_type_names.as_slice());
         encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
         encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
         encode_name(rbml_w, item.ident.name);
@@ -1397,10 +1401,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
                         ty::StaticExplicitSelfCategory;
                 }
                 ty::TypeTraitItem(associated_type) => {
+                    encode_name(rbml_w, associated_type.name);
+                    encode_def_id(rbml_w, associated_type.def_id);
+
                     let elem = ast_map::PathName(associated_type.name);
                     encode_path(rbml_w,
                                 path.clone().chain(Some(elem).into_iter()));
 
+                    encode_item_sort(rbml_w, 't');
                     encode_family(rbml_w, 'y');
 
                     is_nonstatic_method = false;
@@ -1410,7 +1418,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             encode_parent_sort(rbml_w, 't');
 
             let trait_item = &ms[i];
-            let encode_trait_item = |rbml_w: &mut Encoder| {
+            let encode_trait_item = |&: rbml_w: &mut Encoder| {
                 // If this is a static method, we've already
                 // encoded this.
                 if is_nonstatic_method {
@@ -1592,7 +1600,7 @@ fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn:
     F: FnMut(&mut SeekableMemWriter, &T),
     T: Hash,
 {
-    let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
+    let mut buckets: Vec<Vec<entry<T>>> = range(0, 256u16).map(|_| Vec::new()).collect();
     for elt in index.into_iter() {
         let h = hash::hash(&elt.val) as uint;
         buckets[h % 256].push(elt);
@@ -1689,6 +1697,14 @@ fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
     rbml_w.wr_tagged_u8(tag_unsafety, byte);
 }
 
+fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[ast::Name]) {
+    rbml_w.start_tag(tag_associated_type_names);
+    for &name in names.iter() {
+        rbml_w.wr_tagged_str(tag_associated_type_name, token::get_name(name).get());
+    }
+    rbml_w.end_tag();
+}
+
 fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
     fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
         // Pull the cnums and name,vers,hash out of cstore
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 0b859abc531..82071931fe3 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -12,13 +12,13 @@
 
 pub use self::FileMatch::*;
 
-use std::cell::RefCell;
 use std::collections::HashSet;
 use std::io::fs::PathExtensions;
 use std::io::fs;
 use std::os;
 
 use util::fs as myfs;
+use session::search_paths::{SearchPaths, PathKind};
 
 #[deriving(Copy)]
 pub enum FileMatch {
@@ -30,14 +30,11 @@ pub enum FileMatch {
 // FIXME (#2658): I'm not happy how this module turned out. Should
 // probably just be folded into cstore.
 
-/// Functions with type `pick` take a parent directory as well as
-/// a file found in that directory.
-pub type pick<'a> = |path: &Path|: 'a -> FileMatch;
-
 pub struct FileSearch<'a> {
     pub sysroot: &'a Path,
-    pub addl_lib_search_paths: &'a RefCell<Vec<Path>>,
+    pub search_paths: &'a SearchPaths,
     pub triple: &'a str,
+    pub kind: PathKind,
 }
 
 impl<'a> FileSearch<'a> {
@@ -47,9 +44,7 @@ impl<'a> FileSearch<'a> {
         let mut visited_dirs = HashSet::new();
         let mut found = false;
 
-        debug!("filesearch: searching additional lib search paths [{}]",
-               self.addl_lib_search_paths.borrow().len());
-        for path in self.addl_lib_search_paths.borrow().iter() {
+        for path in self.search_paths.iter(self.kind) {
             match f(path) {
                 FileMatches => found = true,
                 FileDoesntMatch => ()
@@ -96,7 +91,7 @@ impl<'a> FileSearch<'a> {
         make_target_lib_path(self.sysroot, self.triple)
     }
 
-    pub fn search(&self, pick: pick) {
+    pub fn search<F>(&self, mut pick: F) where F: FnMut(&Path) -> FileMatch {
         self.for_each_lib_search_path(|lib_search_path| {
             debug!("searching {}", lib_search_path.display());
             match fs::readdir(lib_search_path) {
@@ -133,12 +128,14 @@ impl<'a> FileSearch<'a> {
 
     pub fn new(sysroot: &'a Path,
                triple: &'a str,
-               addl_lib_search_paths: &'a RefCell<Vec<Path>>) -> FileSearch<'a> {
+               search_paths: &'a SearchPaths,
+               kind: PathKind) -> FileSearch<'a> {
         debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
         FileSearch {
             sysroot: sysroot,
-            addl_lib_search_paths: addl_lib_search_paths,
+            search_paths: search_paths,
             triple: triple,
+            kind: kind,
         }
     }
 
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index e0a69f58d37..2d3ff95ffa6 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -179,7 +179,7 @@ pub fn parse_bare_fn_ty_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: u
 
 pub fn parse_trait_ref_data<'tcx>(data: &[u8], crate_num: ast::CrateNum, pos: uint,
                                   tcx: &ty::ctxt<'tcx>, conv: conv_did)
-                                  -> ty::TraitRef<'tcx> {
+                                  -> Rc<ty::TraitRef<'tcx>> {
     debug!("parse_trait_ref_data {}", data_log_string(data, pos));
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_trait_ref(&mut st, conv)
@@ -199,9 +199,9 @@ pub fn parse_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
     parse_bounds(&mut st, conv)
 }
 
-pub fn parse_existential_bounds_data(data: &[u8], crate_num: ast::CrateNum,
-                                     pos: uint, tcx: &ty::ctxt, conv: conv_did)
-                                     -> ty::ExistentialBounds {
+pub fn parse_existential_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
+                                           pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did)
+                                           -> ty::ExistentialBounds<'tcx> {
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_existential_bounds(&mut st, conv)
 }
@@ -376,89 +376,90 @@ fn parse_str(st: &mut PState, term: char) -> String {
 }
 
 fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
-                             -> ty::TraitRef<'tcx> {
+                             -> Rc<ty::TraitRef<'tcx>> {
     let def = parse_def(st, NominalType, |x,y| conv(x,y));
-    let substs = parse_substs(st, |x,y| conv(x,y));
-    ty::TraitRef {def_id: def, substs: st.tcx.mk_substs(substs)}
+    let substs = st.tcx.mk_substs(parse_substs(st, |x,y| conv(x,y)));
+    Rc::new(ty::TraitRef {def_id: def, substs: substs})
 }
 
 fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
+    let tcx = st.tcx;
     match next(st) {
-      'b' => return ty::mk_bool(),
-      'i' => return ty::mk_int(),
-      'u' => return ty::mk_uint(),
+      'b' => return tcx.types.bool,
+      'i' => return tcx.types.int,
+      'u' => return tcx.types.uint,
       'M' => {
         match next(st) {
-          'b' => return ty::mk_mach_uint(ast::TyU8),
-          'w' => return ty::mk_mach_uint(ast::TyU16),
-          'l' => return ty::mk_mach_uint(ast::TyU32),
-          'd' => return ty::mk_mach_uint(ast::TyU64),
-          'B' => return ty::mk_mach_int(ast::TyI8),
-          'W' => return ty::mk_mach_int(ast::TyI16),
-          'L' => return ty::mk_mach_int(ast::TyI32),
-          'D' => return ty::mk_mach_int(ast::TyI64),
-          'f' => return ty::mk_mach_float(ast::TyF32),
-          'F' => return ty::mk_mach_float(ast::TyF64),
+          'b' => return tcx.types.u8,
+          'w' => return tcx.types.u16,
+          'l' => return tcx.types.u32,
+          'd' => return tcx.types.u64,
+          'B' => return tcx.types.i8,
+          'W' => return tcx.types.i16,
+          'L' => return tcx.types.i32,
+          'D' => return tcx.types.i64,
+          'f' => return tcx.types.f32,
+          'F' => return tcx.types.f64,
           _ => panic!("parse_ty: bad numeric type")
         }
       }
-      'c' => return ty::mk_char(),
+      'c' => return tcx.types.char,
       't' => {
         assert_eq!(next(st), '[');
         let def = parse_def(st, NominalType, |x,y| conv(x,y));
         let substs = parse_substs(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
-        return ty::mk_enum(st.tcx, def, st.tcx.mk_substs(substs));
+        return ty::mk_enum(tcx, def, st.tcx.mk_substs(substs));
       }
       'x' => {
         assert_eq!(next(st), '[');
         let trait_ref = ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)));
         let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
-        return ty::mk_trait(st.tcx, trait_ref, bounds);
+        return ty::mk_trait(tcx, trait_ref, bounds);
       }
       'p' => {
-        let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
-        debug!("parsed ty_param: did={}", did);
+        assert_eq!(next(st), '[');
         let index = parse_u32(st);
         assert_eq!(next(st), '|');
         let space = parse_param_space(st);
         assert_eq!(next(st), '|');
-        return ty::mk_param(st.tcx, space, index, did);
+        let name = token::intern(parse_str(st, ']')[]);
+        return ty::mk_param(tcx, space, index, name);
       }
-      '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
-      '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
+      '~' => return ty::mk_uniq(tcx, parse_ty(st, |x,y| conv(x,y))),
+      '*' => return ty::mk_ptr(tcx, parse_mt(st, |x,y| conv(x,y))),
       '&' => {
         let r = parse_region(st, |x,y| conv(x,y));
         let mt = parse_mt(st, |x,y| conv(x,y));
-        return ty::mk_rptr(st.tcx, st.tcx.mk_region(r), mt);
+        return ty::mk_rptr(tcx, tcx.mk_region(r), mt);
       }
       'V' => {
         let t = parse_ty(st, |x,y| conv(x,y));
         let sz = parse_size(st);
-        return ty::mk_vec(st.tcx, t, sz);
+        return ty::mk_vec(tcx, t, sz);
       }
       'v' => {
-        return ty::mk_str(st.tcx);
+        return ty::mk_str(tcx);
       }
       'T' => {
         assert_eq!(next(st), '[');
         let mut params = Vec::new();
         while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
         st.pos = st.pos + 1u;
-        return ty::mk_tup(st.tcx, params);
+        return ty::mk_tup(tcx, params);
       }
       'f' => {
-        return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
+        return ty::mk_closure(tcx, parse_closure_ty(st, |x,y| conv(x,y)));
       }
       'F' => {
           let def_id = parse_def(st, NominalType, |x,y| conv(x,y));
-          return ty::mk_bare_fn(st.tcx, Some(def_id),
-                                st.tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
+          return ty::mk_bare_fn(tcx, Some(def_id),
+                                tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
       }
       'G' => {
-          return ty::mk_bare_fn(st.tcx, None,
-                                st.tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
+          return ty::mk_bare_fn(tcx, None,
+                                tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
       }
       '#' => {
         let pos = parse_hex(st);
@@ -469,7 +470,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
                                          pos: pos,
                                          len: len };
 
-        match st.tcx.rcache.borrow().get(&key).cloned() {
+        match tcx.rcache.borrow().get(&key).cloned() {
           Some(tt) => return tt,
           None => {}
         }
@@ -478,7 +479,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
             .. *st
         };
         let tt = parse_ty(&mut ps, |x,y| conv(x,y));
-        st.tcx.rcache.borrow_mut().insert(key, tt);
+        tcx.rcache.borrow_mut().insert(key, tt);
         return tt;
       }
       '\"' => {
@@ -502,8 +503,14 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
           return ty::mk_unboxed_closure(st.tcx, did,
                   st.tcx.mk_region(region), st.tcx.mk_substs(substs));
       }
+      'P' => {
+          assert_eq!(next(st), '[');
+          let trait_ref = parse_trait_ref(st, |x,y| conv(x,y));
+          let name = token::intern(parse_str(st, ']').as_slice());
+          return ty::mk_projection(tcx, trait_ref, name);
+      }
       'e' => {
-          return ty::mk_err();
+          return tcx.types.err;
       }
       c => { panic!("unexpected char in type string: {}", c);}
     }
@@ -681,17 +688,32 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>,
                                 -> ty::Predicate<'tcx>
 {
     match next(st) {
-        't' => Rc::new(ty::Binder(parse_trait_ref(st, conv))).as_predicate(),
+        't' => ty::Binder(parse_trait_ref(st, conv)).as_predicate(),
         'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)),
                                               parse_ty(st, |x,y| conv(x,y)))).as_predicate(),
         'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)),
                                                 parse_region(st, |x,y| conv(x,y)))).as_predicate(),
         'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)),
                                                 parse_region(st, |x,y| conv(x,y)))).as_predicate(),
+        'p' => ty::Binder(parse_projection_predicate(st, conv)).as_predicate(),
         c => panic!("Encountered invalid character in metadata: {}", c)
     }
 }
 
+fn parse_projection_predicate<'a,'tcx>(
+    st: &mut PState<'a, 'tcx>,
+    conv: conv_did)
+     -> ty::ProjectionPredicate<'tcx>
+{
+    ty::ProjectionPredicate {
+        projection_ty: ty::ProjectionTy {
+            trait_ref: parse_trait_ref(st, |x,y| conv(x,y)),
+            item_name: token::str_to_ident(parse_str(st, '|').as_slice()).name,
+        },
+        ty: parse_ty(st, |x,y| conv(x,y)),
+    }
+}
+
 pub fn parse_type_param_def_data<'tcx>(data: &[u8], start: uint,
                                        crate_num: ast::CrateNum, tcx: &ty::ctxt<'tcx>,
                                        conv: conv_did) -> ty::TypeParameterDef<'tcx>
@@ -708,10 +730,6 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
     assert_eq!(next(st), '|');
     let index = parse_u32(st);
     assert_eq!(next(st), '|');
-    let associated_with = parse_opt(st, |st| {
-        parse_def(st, NominalType, |x,y| conv(x,y))
-    });
-    assert_eq!(next(st), '|');
     let bounds = parse_bounds(st, |x,y| conv(x,y));
     let default = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)));
 
@@ -720,16 +738,23 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
         def_id: def_id,
         space: space,
         index: index,
-        associated_with: associated_with,
         bounds: bounds,
         default: default
     }
 }
 
-fn parse_existential_bounds(st: &mut PState, conv: conv_did) -> ty::ExistentialBounds {
-    let r = parse_region(st, |x,y| conv(x,y));
-    let bb = parse_builtin_bounds(st, conv);
-    return ty::ExistentialBounds { region_bound: r, builtin_bounds: bb };
+fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>,
+                                     conv: conv_did)
+                                     -> ty::ExistentialBounds<'tcx>
+{
+    let ty::ParamBounds { trait_bounds, mut region_bounds, builtin_bounds, projection_bounds } =
+         parse_bounds(st, conv);
+    assert_eq!(region_bounds.len(), 1);
+    assert_eq!(trait_bounds.len(), 0);
+    let region_bound = region_bounds.pop().unwrap();
+    return ty::ExistentialBounds { region_bound: region_bound,
+                                   builtin_bounds: builtin_bounds,
+                                   projection_bounds: projection_bounds };
 }
 
 fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds {
@@ -766,7 +791,8 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
     let mut param_bounds = ty::ParamBounds {
         region_bounds: Vec::new(),
         builtin_bounds: builtin_bounds,
-        trait_bounds: Vec::new()
+        trait_bounds: Vec::new(),
+        projection_bounds: Vec::new(),
     };
     loop {
         match next(st) {
@@ -776,7 +802,11 @@ fn parse_bounds<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
             }
             'I' => {
                 param_bounds.trait_bounds.push(
-                    Rc::new(ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)))));
+                    ty::Binder(parse_trait_ref(st, |x,y| conv(x,y))));
+            }
+            'P' => {
+                param_bounds.projection_bounds.push(
+                    ty::Binder(parse_projection_predicate(st, |x,y| conv(x,y))));
             }
             '.' => {
                 return param_bounds;
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 3e9eaf7eea2..30746f51a8f 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -91,7 +91,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
         ty::ty_trait(box ty::TyTrait { ref principal,
                                        ref bounds }) => {
             mywrite!(w, "x[");
-            enc_trait_ref(w, cx, &principal.0);
+            enc_trait_ref(w, cx, &*principal.0);
             enc_existential_bounds(w, cx, bounds);
             mywrite!(w, "]");
         }
@@ -135,8 +135,8 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
         ty::ty_infer(_) => {
             cx.diag.handler().bug("cannot encode inference variable types");
         }
-        ty::ty_param(ParamTy {space, idx: id, def_id: did}) => {
-            mywrite!(w, "p{}|{}|{}|", (cx.ds)(did), id, space.to_uint())
+        ty::ty_param(ParamTy {space, idx, name}) => {
+            mywrite!(w, "p[{}|{}|{}]", idx, space.to_uint(), token::get_name(name))
         }
         ty::ty_struct(def, substs) => {
             mywrite!(w, "a[{}|", (cx.ds)(def));
@@ -149,6 +149,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
             enc_substs(w, cx, substs);
             mywrite!(w, "]");
         }
+        ty::ty_projection(ref data) => {
+            mywrite!(w, "P[");
+            enc_trait_ref(w, cx, &*data.trait_ref);
+            mywrite!(w, "{}]", token::get_name(data.item_name));
+        }
         ty::ty_err => {
             mywrite!(w, "e");
         }
@@ -387,9 +392,14 @@ pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::Builti
     mywrite!(w, ".");
 }
 
-pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ExistentialBounds) {
-    enc_region(w, cx, bs.region_bound);
-    enc_builtin_bounds(w, cx, &bs.builtin_bounds);
+pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter,
+                                       cx: &ctxt<'a,'tcx>,
+                                       bs: &ty::ExistentialBounds<'tcx>) {
+    let param_bounds = ty::ParamBounds { trait_bounds: vec!(),
+                                         region_bounds: vec!(bs.region_bound),
+                                         builtin_bounds: bs.builtin_bounds,
+                                         projection_bounds: bs.projection_bounds.clone() };
+    enc_bounds(w, cx, &param_bounds);
 }
 
 pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
@@ -403,7 +413,12 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
 
     for tp in bs.trait_bounds.iter() {
         mywrite!(w, "I");
-        enc_trait_ref(w, cx, &tp.0);
+        enc_trait_ref(w, cx, &*tp.0);
+    }
+
+    for tp in bs.projection_bounds.iter() {
+        mywrite!(w, "P");
+        enc_projection_predicate(w, cx, &tp.0);
     }
 
     mywrite!(w, ".");
@@ -414,8 +429,6 @@ pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tc
     mywrite!(w, "{}:{}|{}|{}|",
              token::get_name(v.name), (cx.ds)(v.def_id),
              v.space.to_uint(), v.index);
-    enc_opt(w, v.associated_with, |w, did| mywrite!(w, "{}", (cx.ds)(did)));
-    mywrite!(w, "|");
     enc_bounds(w, cx, &v.bounds);
     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
 }
@@ -427,7 +440,7 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
     match *p {
         ty::Predicate::Trait(ref trait_ref) => {
             mywrite!(w, "t");
-            enc_trait_ref(w, cx, &trait_ref.0);
+            enc_trait_ref(w, cx, &*trait_ref.0.trait_ref);
         }
         ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
             mywrite!(w, "e");
@@ -444,5 +457,17 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
             enc_ty(w, cx, a);
             enc_region(w, cx, b);
         }
+        ty::Predicate::Projection(ty::Binder(ref data)) => {
+            mywrite!(w, "p");
+            enc_projection_predicate(w, cx, data)
+        }
     }
 }
+
+fn enc_projection_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
+                                      cx: &ctxt<'a, 'tcx>,
+                                      data: &ty::ProjectionPredicate<'tcx>) {
+    enc_trait_ref(w, cx, &*data.projection_ty.trait_ref);
+    mywrite!(w, "{}|", token::get_name(data.projection_ty.item_name));
+    enc_ty(w, cx, data.ty);
+}
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index 060e2f67faf..b1b4fd831a0 100644
--- a/src/librustc/middle/astconv_util.rs
+++ b/src/librustc/middle/astconv_util.rs
@@ -57,23 +57,23 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
                     match nty {
                         ast::TyBool => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_bool())
+                            Some(tcx.types.bool)
                         }
                         ast::TyChar => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_char())
+                            Some(tcx.types.char)
                         }
                         ast::TyInt(it) => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_int(it))
+                            Some(ty::mk_mach_int(tcx, it))
                         }
                         ast::TyUint(uit) => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_uint(uit))
+                            Some(ty::mk_mach_uint(tcx, uit))
                         }
                         ast::TyFloat(ft) => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_float(ft))
+                            Some(ty::mk_mach_float(tcx, ft))
                         }
                         ast::TyStr => {
                             Some(ty::mk_str(tcx))
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index e8627dfa64b..6efc80ed8d3 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -448,7 +448,7 @@ impl tr for def::Def {
           def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) =>
               def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident),
           def::DefPrimTy(p) => def::DefPrimTy(p),
-          def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v),
+          def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
           def::DefUse(did) => def::DefUse(did.tr(dcx)),
           def::DefUpvar(nid1, nid2, nid3) => {
             def::DefUpvar(dcx.tr_id(nid1),
@@ -707,9 +707,8 @@ impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
     {
         let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
         let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
-        let assocs = self.read_to_vec(|this| Ok(f(this))).unwrap();
         let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
-        VecPerParamSpace::new(types, selfs, assocs, fns)
+        VecPerParamSpace::new(types, selfs, fns)
     }
 
     fn read_vtable_res_with_key(&mut self,
@@ -838,11 +837,12 @@ trait rbml_writer_helpers<'tcx> {
                           predicate: &ty::Predicate<'tcx>);
     fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                           ty: &ty::TraitRef<'tcx>);
-    fn emit_polytype<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
-                         pty: ty::Polytype<'tcx>);
+    fn emit_type_scheme<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
+                            type_scheme: ty::TypeScheme<'tcx>);
     fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                        substs: &subst::Substs<'tcx>);
-    fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds);
+    fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
+                                   bounds: &ty::ExistentialBounds<'tcx>);
     fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
     fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                                 adj: &ty::AutoAdjustment<'tcx>);
@@ -951,38 +951,39 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
         });
     }
 
-    fn emit_polytype<'b>(&mut self,
-                         ecx: &e::EncodeContext<'b, 'tcx>,
-                         pty: ty::Polytype<'tcx>) {
+    fn emit_type_scheme<'b>(&mut self,
+                            ecx: &e::EncodeContext<'b, 'tcx>,
+                            type_scheme: ty::TypeScheme<'tcx>) {
         use serialize::Encoder;
 
-        self.emit_struct("Polytype", 2, |this| {
+        self.emit_struct("TypeScheme", 2, |this| {
             this.emit_struct_field("generics", 0, |this| {
                 this.emit_struct("Generics", 2, |this| {
                     this.emit_struct_field("types", 0, |this| {
                         Ok(encode_vec_per_param_space(
-                            this, &pty.generics.types,
+                            this, &type_scheme.generics.types,
                             |this, def| this.emit_type_param_def(ecx, def)))
                     });
                     this.emit_struct_field("regions", 1, |this| {
                         Ok(encode_vec_per_param_space(
-                            this, &pty.generics.regions,
+                            this, &type_scheme.generics.regions,
                             |this, def| def.encode(this).unwrap()))
                     });
                     this.emit_struct_field("predicates", 2, |this| {
                         Ok(encode_vec_per_param_space(
-                            this, &pty.generics.predicates,
+                            this, &type_scheme.generics.predicates,
                             |this, def| this.emit_predicate(ecx, def)))
                     })
                 })
             });
             this.emit_struct_field("ty", 1, |this| {
-                Ok(this.emit_ty(ecx, pty.ty))
+                Ok(this.emit_ty(ecx, type_scheme.ty))
             })
         });
     }
 
-    fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds) {
+    fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
+                                   bounds: &ty::ExistentialBounds<'tcx>) {
         self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer,
                                                                     &ecx.ty_str_ctxt(),
                                                                     bounds)));
@@ -1120,7 +1121,7 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
                     this.emit_enum_variant("UnsizeVtable", 2, 4, |this| {
                         this.emit_enum_variant_arg(0, |this| {
                             try!(this.emit_struct_field("principal", 0, |this| {
-                                Ok(this.emit_trait_ref(ecx, &principal.0))
+                                Ok(this.emit_trait_ref(ecx, &*principal.0))
                             }));
                             this.emit_struct_field("bounds", 1, |this| {
                                 Ok(this.emit_existential_bounds(ecx, b))
@@ -1252,11 +1253,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
     }
 
     let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
-    for &pty in tcx.tcache.borrow().get(&lid).iter() {
+    for &type_scheme in tcx.tcache.borrow().get(&lid).iter() {
         rbml_w.tag(c::tag_table_tcache, |rbml_w| {
             rbml_w.id(id);
             rbml_w.tag(c::tag_table_val, |rbml_w| {
-                rbml_w.emit_polytype(ecx, pty.clone());
+                rbml_w.emit_type_scheme(ecx, type_scheme.clone());
             })
         })
     }
@@ -1284,7 +1285,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         rbml_w.tag(c::tag_table_object_cast_map, |rbml_w| {
             rbml_w.id(id);
             rbml_w.tag(c::tag_table_val, |rbml_w| {
-                rbml_w.emit_trait_ref(ecx, &trait_ref.0);
+                rbml_w.emit_trait_ref(ecx, &*trait_ref.0);
             })
         })
     }
@@ -1364,15 +1365,15 @@ trait rbml_decoder_decoder_helpers<'tcx> {
     fn read_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                               -> Rc<ty::TraitRef<'tcx>>;
     fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                   -> Rc<ty::PolyTraitRef<'tcx>>;
+                                   -> ty::PolyTraitRef<'tcx>;
     fn read_type_param_def<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                    -> ty::TypeParameterDef<'tcx>;
     fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                               -> ty::Predicate<'tcx>;
-    fn read_polytype<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                             -> ty::Polytype<'tcx>;
+    fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
+                                -> ty::TypeScheme<'tcx>;
     fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                       -> ty::ExistentialBounds;
+                                       -> ty::ExistentialBounds<'tcx>;
     fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                            -> subst::Substs<'tcx>;
     fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1546,7 +1547,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
 
     fn read_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                               -> Rc<ty::TraitRef<'tcx>> {
-        Rc::new(self.read_opaque(|this, doc| {
+        self.read_opaque(|this, doc| {
             let ty = tydecode::parse_trait_ref_data(
                 doc.data,
                 dcx.cdata.cnum,
@@ -1554,12 +1555,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                 dcx.tcx,
                 |s, a| this.convert_def_id(dcx, s, a));
             Ok(ty)
-        }).unwrap())
+        }).unwrap()
     }
 
     fn read_poly_trait_ref<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                   -> Rc<ty::PolyTraitRef<'tcx>> {
-        Rc::new(ty::Binder(self.read_opaque(|this, doc| {
+                                   -> ty::PolyTraitRef<'tcx> {
+        ty::Binder(self.read_opaque(|this, doc| {
             let ty = tydecode::parse_trait_ref_data(
                 doc.data,
                 dcx.cdata.cnum,
@@ -1567,7 +1568,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                 dcx.tcx,
                 |s, a| this.convert_def_id(dcx, s, a));
             Ok(ty)
-        }).unwrap()))
+        }).unwrap())
     }
 
     fn read_type_param_def<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
@@ -1591,10 +1592,10 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_polytype<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                             -> ty::Polytype<'tcx> {
-        self.read_struct("Polytype", 2, |this| {
-            Ok(ty::Polytype {
+    fn read_type_scheme<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
+                                -> ty::TypeScheme<'tcx> {
+        self.read_struct("TypeScheme", 2, |this| {
+            Ok(ty::TypeScheme {
                 generics: this.read_struct_field("generics", 0, |this| {
                     this.read_struct("Generics", 2, |this| {
                         Ok(ty::Generics {
@@ -1626,7 +1627,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     }
 
     fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                       -> ty::ExistentialBounds
+                                       -> ty::ExistentialBounds<'tcx>
     {
         self.read_opaque(|this, doc| {
             Ok(tydecode::parse_existential_bounds_data(doc.data,
@@ -1786,7 +1787,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                                 Ok(this.read_poly_trait_ref(dcx))
                             }));
                             Ok(ty::TyTrait {
-                                principal: (*principal).clone(),
+                                principal: principal,
                                 bounds: try!(this.read_struct_field("bounds", 1, |this| {
                                     Ok(this.read_existential_bounds(dcx))
                                 })),
@@ -1939,9 +1940,9 @@ fn decode_side_tables(dcx: &DecodeContext,
                            .insert(id, capture_mode);
                     }
                     c::tag_table_tcache => {
-                        let pty = val_dsr.read_polytype(dcx);
+                        let type_scheme = val_dsr.read_type_scheme(dcx);
                         let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
-                        dcx.tcx.tcache.borrow_mut().insert(lid, pty);
+                        dcx.tcx.tcache.borrow_mut().insert(lid, type_scheme);
                     }
                     c::tag_table_param_defs => {
                         let bounds = val_dsr.read_type_param_def(dcx);
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index f50790f7e9b..92aa70548c8 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -432,15 +432,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.call(expr, pred, &**l, Some(&**r).into_iter())
             }
 
-            ast::ExprSlice(ref base, ref start, ref end, _) => {
-                self.call(expr,
-                          pred,
-                          &**base,
-                          start.iter().chain(end.iter()).map(|x| &**x))
-            }
-
             ast::ExprRange(ref start, ref end) => {
-                let fields = Some(&**start).into_iter()
+                let fields = start.as_ref().map(|e| &**e).into_iter()
                     .chain(end.as_ref().map(|e| &**e).into_iter());
                 self.straightline(expr, pred, fields)
             }
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index e08dd64d4d4..6277656e03a 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -185,7 +185,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
         ast::ExprBlock(ref block) => {
             // Check all statements in the block
             for stmt in block.stmts.iter() {
-                let block_span_err = |span|
+                let block_span_err = |&: span|
                     span_err!(v.tcx.sess, span, E0016,
                               "blocks in constants are limited to items and \
                                tail expressions");
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 234f830bc66..d16224ec5b8 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -24,7 +24,7 @@ use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
 use std::fmt;
-use std::iter::{range_inclusive, AdditiveIterator, FromIterator};
+use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat};
 use std::num::Float;
 use std::slice;
 use syntax::ast::{mod, DUMMY_NODE_ID, NodeId, Pat};
@@ -75,7 +75,7 @@ impl<'a> fmt::Show for Matrix<'a> {
         }).collect();
 
         let total_width = column_widths.iter().map(|n| *n).sum() + column_count * 3 + 1;
-        let br = String::from_char(total_width, '+');
+        let br = repeat('+').take(total_width).collect::<String>();
         try!(write!(f, "{}\n", br));
         for row in pretty_printed_matrix.into_iter() {
             try!(write!(f, "+"));
@@ -610,9 +610,9 @@ fn is_useful(cx: &MatchCheckCtxt,
                             let arity = constructor_arity(cx, &c, left_ty);
                             let mut result = {
                                 let pat_slice = pats[];
-                                let subpats = Vec::from_fn(arity, |i| {
+                                let subpats: Vec<_> = range(0, arity).map(|i| {
                                     pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
-                                });
+                                }).collect();
                                 vec![construct_witness(cx, &c, subpats, left_ty)]
                             };
                             result.extend(pats.into_iter().skip(arity));
@@ -634,7 +634,7 @@ fn is_useful(cx: &MatchCheckCtxt,
                 match is_useful(cx, &matrix, v.tail(), witness) {
                     UsefulWithWitness(pats) => {
                         let arity = constructor_arity(cx, &constructor, left_ty);
-                        let wild_pats = Vec::from_elem(arity, DUMMY_WILD_PAT);
+                        let wild_pats: Vec<_> = repeat(DUMMY_WILD_PAT).take(arity).collect();
                         let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
                         let mut new_pats = vec![enum_pat];
                         new_pats.extend(pats.into_iter());
@@ -787,7 +787,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
     } = raw_pat(r[col]);
     let head: Option<Vec<&Pat>> = match *node {
         ast::PatWild(_) =>
-            Some(Vec::from_elem(arity, DUMMY_WILD_PAT)),
+            Some(repeat(DUMMY_WILD_PAT).take(arity).collect()),
 
         ast::PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned();
@@ -800,7 +800,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
                 } else {
                     None
                 },
-                _ => Some(Vec::from_elem(arity, DUMMY_WILD_PAT))
+                _ => Some(repeat(DUMMY_WILD_PAT).take(arity).collect())
             }
         }
 
@@ -814,7 +814,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
                 DefVariant(..) | DefStruct(..) => {
                     Some(match args {
                         &Some(ref args) => args.iter().map(|p| &**p).collect(),
-                        &None => Vec::from_elem(arity, DUMMY_WILD_PAT)
+                        &None => repeat(DUMMY_WILD_PAT).take(arity).collect(),
                     })
                 }
                 _ => None
@@ -893,13 +893,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
                 // Fixed-length vectors.
                 Single => {
                     let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect();
-                    pats.grow_fn(arity - before.len() - after.len(), |_| DUMMY_WILD_PAT);
+                    pats.extend(repeat(DUMMY_WILD_PAT).take(arity - before.len() - after.len()));
                     pats.extend(after.iter().map(|p| &**p));
                     Some(pats)
                 },
                 Slice(length) if before.len() + after.len() <= length && slice.is_some() => {
                     let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect();
-                    pats.grow_fn(arity - before.len() - after.len(), |_| DUMMY_WILD_PAT);
+                    pats.extend(repeat(DUMMY_WILD_PAT).take(arity - before.len() - after.len()));
                     pats.extend(after.iter().map(|p| &**p));
                     Some(pats)
                 },
@@ -1011,7 +1011,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
         })
     }
 
-    let check_move: |&Pat, Option<&Pat>| = |p, sub| {
+    let check_move = |&: p: &Pat, sub: Option<&Pat>| {
         // check legality of moving out of the enum
 
         // x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -1064,7 +1064,7 @@ fn check_for_mutation_in_guard<'a, 'tcx>(cx: &'a MatchCheckCtxt<'a, 'tcx>,
     };
     let mut visitor = ExprUseVisitor::new(&mut checker,
                                           checker.cx.tcx,
-                                          cx.param_env.clone());
+                                          &cx.param_env);
     visitor.walk_expr(guard);
 }
 
diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs
index a14307b90ee..3b4ea5234f4 100644
--- a/src/librustc/middle/check_rvalues.rs
+++ b/src/librustc/middle/check_rvalues.rs
@@ -28,7 +28,7 @@ pub fn check_crate(tcx: &ty::ctxt,
 }
 
 struct RvalueContext<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>
+    tcx: &'a ty::ctxt<'tcx>,
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> {
@@ -40,21 +40,27 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for RvalueContext<'a, 'tcx> {
                 fn_id: ast::NodeId) {
         {
             let param_env = ParameterEnvironment::for_item(self.tcx, fn_id);
-            let mut euv = euv::ExprUseVisitor::new(self, self.tcx, param_env);
+            let mut delegate = RvalueContextDelegate { tcx: self.tcx, param_env: &param_env };
+            let mut euv = euv::ExprUseVisitor::new(&mut delegate, self.tcx, &param_env);
             euv.walk_fn(fd, b);
         }
         visit::walk_fn(self, fk, fd, b, s)
     }
 }
 
-impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContext<'a, 'tcx> {
+struct RvalueContextDelegate<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    param_env: &'a ty::ParameterEnvironment<'tcx>,
+}
+
+impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
     fn consume(&mut self,
                _: ast::NodeId,
                span: Span,
                cmt: mc::cmt<'tcx>,
                _: euv::ConsumeMode) {
         debug!("consume; cmt: {}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty));
-        if !ty::type_is_sized(self.tcx, cmt.ty) {
+        if !ty::type_is_sized(self.tcx, cmt.ty, self.param_env) {
             span_err!(self.tcx.sess, span, E0161,
                 "cannot move a value of type {0}: the size of {0} cannot be statically determined",
                 ty_to_string(self.tcx, cmt.ty));
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 14f927f5b1e..fb20df020ac 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -31,7 +31,6 @@ use middle::infer;
 use middle::traits;
 use middle::mem_categorization as mc;
 use middle::expr_use_visitor as euv;
-use util::common::ErrorReported;
 use util::nodemap::NodeSet;
 
 use syntax::ast;
@@ -72,7 +71,7 @@ pub fn check_crate(tcx: &ty::ctxt) {
     };
     {
         let param_env = ty::empty_parameter_environment();
-        let visitor = euv::ExprUseVisitor::new(&mut checker, tcx, param_env);
+        let visitor = euv::ExprUseVisitor::new(&mut checker, tcx, &param_env);
         visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate());
     }
     visit::walk_crate(&mut CheckStaticVisitor {
@@ -120,19 +119,14 @@ impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
         let ty = ty::node_id_to_type(self.tcx, e.id);
         let infcx = infer::new_infer_ctxt(self.tcx);
         let mut fulfill_cx = traits::FulfillmentContext::new();
-        match traits::poly_trait_ref_for_builtin_bound(self.tcx, ty::BoundSync, ty) {
-            Ok(trait_ref) => {
-                let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
-                fulfill_cx.register_trait_ref(self.tcx, trait_ref, cause);
-                let env = ty::empty_parameter_environment();
-                match fulfill_cx.select_all_or_error(&infcx, &env, self.tcx) {
-                    Ok(()) => { },
-                    Err(ref errors) => {
-                      traits::report_fulfillment_errors(&infcx, errors);
-                    }
-                }
+        let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
+        fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
+        let env = ty::empty_parameter_environment();
+        match fulfill_cx.select_all_or_error(&infcx, &env, self.tcx) {
+            Ok(()) => { },
+            Err(ref errors) => {
+                traits::report_fulfillment_errors(&infcx, errors);
             }
-            Err(ErrorReported) => { }
         }
     }
 }
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index a2d417ca345..6cf6065de19 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -21,6 +21,7 @@ use middle::cfg::CFGIndex;
 use middle::ty;
 use std::io;
 use std::uint;
+use std::iter::repeat;
 use syntax::ast;
 use syntax::ast_util::IdRange;
 use syntax::visit;
@@ -203,9 +204,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
 
         let entry = if oper.initial_value() { uint::MAX } else {0};
 
-        let gens = Vec::from_elem(num_nodes * words_per_id, 0);
-        let kills = Vec::from_elem(num_nodes * words_per_id, 0);
-        let on_entry = Vec::from_elem(num_nodes * words_per_id, entry);
+        let gens: Vec<_> = repeat(0).take(num_nodes * words_per_id).collect();
+        let kills: Vec<_> = repeat(0).take(num_nodes * words_per_id).collect();
+        let on_entry: Vec<_> = repeat(entry).take(num_nodes * words_per_id).collect();
 
         let nodeid_to_index = build_nodeid_to_index(decl, cfg);
 
@@ -446,7 +447,7 @@ impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
                 changed: true
             };
 
-            let mut temp = Vec::from_elem(words_per_id, 0u);
+            let mut temp: Vec<_> = repeat(0u).take(words_per_id).collect();
             while propcx.changed {
                 propcx.changed = false;
                 propcx.reset(temp.as_mut_slice());
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index 023182df336..ff1ee394966 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -36,10 +36,11 @@ pub enum Def {
     // A partially resolved path to an associated type `T::U` where `T` is a concrete
     // type (indicated by the DefId) which implements a trait which has an associated
     // type `U` (indicated by the Ident).
+    // FIXME(#20301) -- should use Name
     DefAssociatedPath(TyParamProvenance, ast::Ident),
     DefTrait(ast::DefId),
     DefPrimTy(ast::PrimTy),
-    DefTyParam(ParamSpace, ast::DefId, u32),
+    DefTyParam(ParamSpace, u32, ast::DefId, ast::Name),
     DefUse(ast::DefId),
     DefUpvar(ast::NodeId,  // id of closed over local
              ast::NodeId,  // expr node that creates the closure
@@ -130,7 +131,7 @@ impl Def {
             DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) |
             DefForeignMod(id) | DefStatic(id, _) |
             DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) |
-            DefTyParam(_, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
+            DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
             DefMethod(id, _, _) | DefConst(id) |
             DefAssociatedPath(TyParamProvenance::FromSelf(id), _) |
             DefAssociatedPath(TyParamProvenance::FromParam(id), _) => {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 1dfd602794f..d36c85342ce 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -295,11 +295,11 @@ impl OverloadedCallType {
 // supplies types from the tree. After type checking is complete, you
 // can just use the tcx as the typer.
 
-pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> {
+pub struct ExprUseVisitor<'d,'t,'tcx:'t,TYPER:'t> {
     typer: &'t TYPER,
     mc: mc::MemCategorizationContext<'t,TYPER>,
     delegate: &'d mut (Delegate<'tcx>+'d),
-    param_env: ParameterEnvironment<'tcx>,
+    param_env: &'t ParameterEnvironment<'tcx>,
 }
 
 /// Whether the elements of an overloaded operation are passed by value or by reference
@@ -311,7 +311,7 @@ enum PassArgs {
 impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     pub fn new(delegate: &'d mut Delegate<'tcx>,
                typer: &'t TYPER,
-               param_env: ParameterEnvironment<'tcx>)
+               param_env: &'t ParameterEnvironment<'tcx>)
                -> ExprUseVisitor<'d,'t,'tcx,TYPER> {
         ExprUseVisitor {
             typer: typer,
@@ -355,7 +355,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         cmt: mc::cmt<'tcx>) {
         let mode = copy_or_move(self.tcx(),
                                 cmt.ty,
-                                &self.param_env,
+                                self.param_env,
                                 DirectRefMove);
         self.delegate.consume(consume_id, consume_span, cmt, mode);
     }
@@ -431,26 +431,33 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             }
 
             ast::ExprIndex(ref lhs, ref rhs) => {       // lhs[rhs]
-                if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], PassArgs::ByRef) {
-                    self.select_from_expr(&**lhs);
-                    self.consume_expr(&**rhs);
+                match rhs.node {
+                    ast::ExprRange(ref start, ref end) => {
+                        // Hacked slicing syntax (KILLME).
+                        let args = match (start, end) {
+                            (&Some(ref e1), &Some(ref e2)) => vec![&**e1, &**e2],
+                            (&Some(ref e), &None) => vec![&**e],
+                            (&None, &Some(ref e)) => vec![&**e],
+                            (&None, &None) => Vec::new()
+                        };
+                        let overloaded =
+                            self.walk_overloaded_operator(expr, &**lhs, args, PassArgs::ByRef);
+                        assert!(overloaded);
+                    }
+                    _ => {
+                        if !self.walk_overloaded_operator(expr,
+                                                          &**lhs,
+                                                          vec![&**rhs],
+                                                          PassArgs::ByRef) {
+                            self.select_from_expr(&**lhs);
+                            self.consume_expr(&**rhs);
+                        }
+                    }
                 }
             }
 
-            ast::ExprSlice(ref base, ref start, ref end, _) => {    // base[start..end]
-                let args = match (start, end) {
-                    (&Some(ref e1), &Some(ref e2)) => vec![&**e1, &**e2],
-                    (&Some(ref e), &None) => vec![&**e],
-                    (&None, &Some(ref e)) => vec![&**e],
-                    (&None, &None) => Vec::new()
-                };
-                let overloaded =
-                    self.walk_overloaded_operator(expr, &**base, args, PassArgs::ByRef);
-                assert!(overloaded);
-            }
-
             ast::ExprRange(ref start, ref end) => {
-                self.consume_expr(&**start);
+                start.as_ref().map(|e| self.consume_expr(&**e));
                 end.as_ref().map(|e| self.consume_expr(&**e));
             }
 
@@ -991,7 +998,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                     ast::PatIdent(ast::BindByValue(_), _, _) => {
                         match copy_or_move(tcx,
                                            cmt_pat.ty,
-                                           &self.param_env,
+                                           self.param_env,
                                            PatBindingMove) {
                             Copy => mode.lub(CopyingMatch),
                             Move(_) => mode.lub(MovingMatch),
@@ -1021,8 +1028,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
         let typer = self.typer;
         let def_map = &self.typer.tcx().def_map;
         let delegate = &mut self.delegate;
-        let param_env = &mut self.param_env;
-
+        let param_env = self.param_env;
         mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
             if pat_util::pat_is_binding(def_map, pat) {
                 let tcx = typer.tcx();
@@ -1079,7 +1085,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         // Note: We declare here that the borrow
                         // occurs upon entering the `[...]`
                         // pattern. This implies that something like
-                        // `[a, ..b]` where `a` is a move is illegal,
+                        // `[a; b]` where `a` is a move is illegal,
                         // because the borrow is already in effect.
                         // In fact such a move would be safe-ish, but
                         // it effectively *requires* that we use the
@@ -1223,7 +1229,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             // inferred by regionbk
             let upvar_id = ty::UpvarId { var_id: id_var,
                                          closure_expr_id: closure_expr.id };
-            let upvar_borrow = self.typer.upvar_borrow(upvar_id);
+            let upvar_borrow = self.typer.upvar_borrow(upvar_id).unwrap();
 
             self.delegate.borrow(closure_expr.id,
                                  closure_expr.span,
@@ -1242,7 +1248,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                                                 closure_expr.span,
                                                 freevar.def);
             let mode = copy_or_move(self.tcx(), cmt_var.ty,
-                                    &self.param_env, CaptureMove);
+                                    self.param_env, CaptureMove);
             self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
         }
     }
diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs
index 62cf47da687..dcbd94b8482 100644
--- a/src/librustc/middle/fast_reject.rs
+++ b/src/librustc/middle/fast_reject.rs
@@ -58,7 +58,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
         ty::ty_vec(..) => Some(VecSimplifiedType),
         ty::ty_ptr(_) => Some(PtrSimplifiedType),
         ty::ty_trait(ref trait_info) => {
-            Some(TraitSimplifiedType(trait_info.principal.def_id()))
+            Some(TraitSimplifiedType(trait_info.principal_def_id()))
         }
         ty::ty_struct(def_id, _) => {
             Some(StructSimplifiedType(def_id))
@@ -86,6 +86,9 @@ pub fn simplify_type(tcx: &ty::ctxt,
         ty::ty_bare_fn(_, ref f) => {
             Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
         }
+        ty::ty_projection(_) => {
+            None
+        }
         ty::ty_param(_) => {
             if can_simplify_params {
                 Some(ParameterSimplifiedType)
diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs
index 06e6ef30f74..da00d737b47 100644
--- a/src/librustc/middle/graph.rs
+++ b/src/librustc/middle/graph.rs
@@ -42,12 +42,12 @@ pub struct Graph<N,E> {
 }
 
 pub struct Node<N> {
-    first_edge: [EdgeIndex, ..2], // see module comment
+    first_edge: [EdgeIndex; 2], // see module comment
     pub data: N,
 }
 
 pub struct Edge<E> {
-    next_edge: [EdgeIndex, ..2], // see module comment
+    next_edge: [EdgeIndex; 2], // see module comment
     source: NodeIndex,
     target: NodeIndex,
     pub data: E,
diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs
index 13017da508d..11ca202971e 100644
--- a/src/librustc/middle/infer/coercion.rs
+++ b/src/librustc/middle/infer/coercion.rs
@@ -351,11 +351,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 (&ty::ty_trait(..), &ty::ty_trait(..)) => {
                     None
                 }
-                (_, &ty::ty_trait(box ty::TyTrait { ref principal, bounds })) => {
+                (_, &ty::ty_trait(box ty::TyTrait { ref principal, ref bounds })) => {
                     // FIXME what is the purpose of `ty`?
-                    let ty = ty::mk_trait(tcx, principal.clone(), bounds);
-                    Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: (*principal).clone(),
-                                                             bounds: bounds },
+                    let ty = ty::mk_trait(tcx, principal.clone(), bounds.clone());
+                    Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: principal.clone(),
+                                                             bounds: bounds.clone() },
                                                ty_a)))
                 }
                 (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
@@ -458,10 +458,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         match a.sty {
             ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty {
-                ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
+                ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
                     debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl);
-                    // FIXME what is purpose of this type `tr`?
-                    let tr = ty::mk_trait(tcx, principal.clone(), bounds);
+                    let tr = ty::mk_trait(tcx, principal.clone(), bounds.clone());
                     try!(self.subtype(mk_ty(tr), b));
                     Ok(Some(AdjustDerefRef(AutoDerefRef {
                         autoderefs: 1,
diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs
index 04ae0a5a604..e0bcdfc6d8d 100644
--- a/src/librustc/middle/infer/combine.rs
+++ b/src/librustc/middle/infer/combine.rs
@@ -51,6 +51,7 @@ use middle::ty_fold;
 use middle::ty_fold::{TypeFoldable};
 use util::ppaux::Repr;
 
+use std::rc::Rc;
 use syntax::ast::{Onceness, Unsafety};
 use syntax::ast;
 use syntax::abi;
@@ -221,7 +222,7 @@ pub trait Combine<'tcx> {
         };
         let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
         let onceness = try!(self.oncenesses(a.onceness, b.onceness));
-        let bounds = try!(self.existential_bounds(a.bounds, b.bounds));
+        let bounds = try!(self.existential_bounds(&a.bounds, &b.bounds));
         let sig = try!(self.binders(&a.sig, &b.sig));
         let abi = try!(self.abi(a.abi, b.abi));
         Ok(ty::ClosureTy {
@@ -288,15 +289,61 @@ pub trait Combine<'tcx> {
 
     fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<'tcx, Onceness>;
 
+    fn projection_tys(&self,
+                      a: &ty::ProjectionTy<'tcx>,
+                      b: &ty::ProjectionTy<'tcx>)
+                      -> cres<'tcx, ty::ProjectionTy<'tcx>>
+    {
+        if a.item_name != b.item_name {
+            Err(ty::terr_projection_name_mismatched(
+                expected_found(self, a.item_name, b.item_name)))
+        } else {
+            let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref));
+            Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name })
+        }
+    }
+
+    fn projection_predicates(&self,
+                             a: &ty::ProjectionPredicate<'tcx>,
+                             b: &ty::ProjectionPredicate<'tcx>)
+                             -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
+    {
+        let projection_ty = try!(self.projection_tys(&a.projection_ty, &b.projection_ty));
+        let ty = try!(self.tys(a.ty, b.ty));
+        Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty })
+    }
+
+    fn projection_bounds(&self,
+                         a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
+                         b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
+                         -> cres<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
+    {
+        // To be compatible, `a` and `b` must be for precisely the
+        // same set of traits and item names. We always require that
+        // projection bounds lists are sorted by trait-def-id and item-name,
+        // so we can just iterate through the lists pairwise, so long as they are the
+        // same length.
+        if a.len() != b.len() {
+            Err(ty::terr_projection_bounds_length(expected_found(self, a.len(), b.len())))
+        } else {
+            a.iter()
+                .zip(b.iter())
+                .map(|(a, b)| self.binders(a, b))
+                .collect()
+        }
+    }
+
     fn existential_bounds(&self,
-                          a: ty::ExistentialBounds,
-                          b: ty::ExistentialBounds)
-                          -> cres<'tcx, ty::ExistentialBounds>
+                          a: &ty::ExistentialBounds<'tcx>,
+                          b: &ty::ExistentialBounds<'tcx>)
+                          -> cres<'tcx, ty::ExistentialBounds<'tcx>>
     {
         let r = try!(self.contraregions(a.region_bound, b.region_bound));
         let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds));
+        let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds));
         Ok(ty::ExistentialBounds { region_bound: r,
-                                   builtin_bounds: nb })
+                                   builtin_bounds: nb,
+                                   projection_bounds: pb })
     }
 
     fn builtin_bounds(&self,
@@ -358,6 +405,18 @@ pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> {
     fn combine<C:Combine<'tcx>>(combiner: &C, a: &Self, b: &Self) -> cres<'tcx, Self>;
 }
 
+impl<'tcx,T> Combineable<'tcx> for Rc<T>
+    where T : Combineable<'tcx>
+{
+    fn combine<C:Combine<'tcx>>(combiner: &C,
+                                a: &Rc<T>,
+                                b: &Rc<T>)
+                                -> cres<'tcx, Rc<T>>
+    {
+        Ok(Rc::new(try!(Combineable::combine(combiner, &**a, &**b))))
+    }
+}
+
 impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
     fn combine<C:Combine<'tcx>>(combiner: &C,
                                 a: &ty::TraitRef<'tcx>,
@@ -368,6 +427,16 @@ impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
     }
 }
 
+impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> {
+    fn combine<C:Combine<'tcx>>(combiner: &C,
+                                a: &ty::ProjectionPredicate<'tcx>,
+                                b: &ty::ProjectionPredicate<'tcx>)
+                                -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
+    {
+        combiner.projection_predicates(a, b)
+    }
+}
+
 impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> {
     fn combine<C:Combine<'tcx>>(combiner: &C,
                                 a: &ty::FnSig<'tcx>,
@@ -397,8 +466,8 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
 pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
                                          a: Ty<'tcx>,
                                          b: Ty<'tcx>)
-                                         -> cres<'tcx, Ty<'tcx>> {
-
+                                         -> cres<'tcx, Ty<'tcx>>
+{
     let tcx = this.infcx().tcx;
     let a_sty = &a.sty;
     let b_sty = &b.sty;
@@ -415,7 +484,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
       }
 
       (&ty::ty_err, _) | (_, &ty::ty_err) => {
-          Ok(ty::mk_err())
+          Ok(tcx.types.err)
       }
 
         // Relate integral variables to other types
@@ -483,7 +552,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
        &ty::ty_trait(ref b_)) => {
           debug!("Trying to match traits {} and {}", a, b);
           let principal = try!(this.binders(&a_.principal, &b_.principal));
-          let bounds = try!(this.existential_bounds(a_.bounds, b_.bounds));
+          let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
           Ok(ty::mk_trait(tcx, principal, bounds))
       }
 
@@ -581,6 +650,11 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
         })
       }
 
+      (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
+          let projection_ty = try!(this.projection_tys(a_data, b_data));
+          Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
+      }
+
       _ => Err(ty::terr_sorts(expected_found(this, a, b)))
     };
 
@@ -592,8 +666,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
     {
         try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
         match val {
-            IntType(v) => Ok(ty::mk_mach_int(v)),
-            UintType(v) => Ok(ty::mk_mach_uint(v))
+            IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)),
+            UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v))
         }
     }
 
@@ -604,7 +678,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
         val: ast::FloatTy) -> cres<'tcx, Ty<'tcx>>
     {
         try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
-        Ok(ty::mk_mach_float(val))
+        Ok(ty::mk_mach_float(this.tcx(), val))
     }
 }
 
@@ -763,7 +837,7 @@ impl<'cx, 'tcx> ty_fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
             ty::ty_infer(ty::TyVar(vid)) => {
                 if vid == self.for_vid {
                     self.cycle_detected = true;
-                    ty::mk_err()
+                    self.tcx().types.err
                 } else {
                     match self.infcx.type_variables.borrow().probe(vid) {
                         Some(u) => self.fold_ty(u),
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index 2f62858071f..6f1c7af5b86 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -1043,7 +1043,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                 ident: ty_param.ident,
                 id: ty_param.id,
                 bounds: bounds,
-                unbound: ty_param.unbound.clone(),
                 default: ty_param.default.clone(),
                 span: ty_param.span,
             }
@@ -1063,7 +1062,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                     // be passing down a map.
                     ast::RegionTyParamBound(lt)
                 }
-                &ast::TraitTyParamBound(ref poly_tr) => {
+                &ast::TraitTyParamBound(ref poly_tr, modifier) => {
                     let tr = &poly_tr.trait_ref;
                     let last_seg = tr.path.segments.last().unwrap();
                     let mut insert = Vec::new();
@@ -1087,7 +1086,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                             path: new_path,
                             ref_id: tr.ref_id,
                         }
-                    })
+                    }, modifier)
                 }
             }
         })
@@ -1188,7 +1187,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
         let mut new_ty = P(ty.clone());
         let mut ty_queue = vec!(ty);
         while !ty_queue.is_empty() {
-            let cur_ty = ty_queue.remove(0).unwrap();
+            let cur_ty = ty_queue.remove(0);
             match cur_ty.node {
                 ast::TyRptr(lt_opt, ref mut_ty) => {
                     let rebuild = match lt_opt {
@@ -1438,6 +1437,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
                 format!(" for {}in generic type",
                         bound_region_to_string(self.tcx, "lifetime parameter ", true, br))
             }
+            infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => {
+                format!(" for {}in trait containing associated type `{}`",
+                        bound_region_to_string(self.tcx, "lifetime parameter ", true, br),
+                        token::get_name(type_name))
+            }
             infer::EarlyBoundRegion(_, name) => {
                 format!(" for lifetime parameter `{}`",
                         token::get_name(name).get())
@@ -1662,13 +1666,16 @@ impl<'tcx> Resolvable<'tcx> for Rc<ty::TraitRef<'tcx>> {
     }
 }
 
-impl<'tcx> Resolvable<'tcx> for Rc<ty::PolyTraitRef<'tcx>> {
-    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
-                   -> Rc<ty::PolyTraitRef<'tcx>> {
-        Rc::new(infcx.resolve_type_vars_if_possible(&**self))
+impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
+    fn resolve<'a>(&self,
+                   infcx: &InferCtxt<'a, 'tcx>)
+                   -> ty::PolyTraitRef<'tcx>
+    {
+        infcx.resolve_type_vars_if_possible(self)
     }
+
     fn contains_error(&self) -> bool {
-        ty::trait_ref_contains_error(&self.0)
+        ty::trait_ref_contains_error(&*self.0)
     }
 }
 
diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs
index d8455b8db71..33174409f89 100644
--- a/src/librustc/middle/infer/freshen.rs
+++ b/src/librustc/middle/infer/freshen.rs
@@ -157,6 +157,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
             ty::ty_struct(..) |
             ty::ty_unboxed_closure(..) |
             ty::ty_tup(..) |
+            ty::ty_projection(..) |
             ty::ty_param(..) => {
                 ty_fold::super_fold_ty(self, t)
             }
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index 07823779216..d9b7e04bc79 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -23,7 +23,7 @@ pub use self::freshen::TypeFreshener;
 
 use middle::subst;
 use middle::subst::Substs;
-use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
+use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
 use middle::ty::replace_late_bound_regions;
 use middle::ty::{mod, Ty};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
@@ -139,7 +139,7 @@ pub enum TypeOrigin {
 pub enum ValuePairs<'tcx> {
     Types(ty::expected_found<Ty<'tcx>>),
     TraitRefs(ty::expected_found<Rc<ty::TraitRef<'tcx>>>),
-    PolyTraitRefs(ty::expected_found<Rc<ty::PolyTraitRef<'tcx>>>),
+    PolyTraitRefs(ty::expected_found<ty::PolyTraitRef<'tcx>>),
 }
 
 /// The trace designates the path through inference that we took to
@@ -231,6 +231,9 @@ pub enum LateBoundRegionConversionTime {
 
     /// when two higher-ranked types are compared
     HigherRankedType,
+
+    /// when projecting an associated type
+    AssocTypeProjection(ast::Name),
 }
 
 /// Reasons to create a region inference variable
@@ -324,7 +327,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
         Ok(t) => t,
         Err(ref err) => {
             cx.report_and_explain_type_error(trace, err);
-            ty::mk_err()
+            cx.tcx.types.err
         }
     }
 }
@@ -407,8 +410,8 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
 pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                                    a_is_expected: bool,
                                    origin: TypeOrigin,
-                                   a: Rc<ty::PolyTraitRef<'tcx>>,
-                                   b: Rc<ty::PolyTraitRef<'tcx>>)
+                                   a: ty::PolyTraitRef<'tcx>,
+                                   b: ty::PolyTraitRef<'tcx>)
                                    -> ures<'tcx>
 {
     debug!("mk_sub_trait_refs({} <: {})",
@@ -522,6 +525,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         freshen::TypeFreshener::new(self)
     }
 
+    pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
+        use middle::ty::UnconstrainedNumeric::{Neither, UnconstrainedInt, UnconstrainedFloat};
+        match ty.sty {
+            ty::ty_infer(ty::IntVar(vid)) => {
+                match self.int_unification_table.borrow_mut().get(self.tcx, vid).value {
+                    None => UnconstrainedInt,
+                    _ => Neither,
+                }
+            },
+            ty::ty_infer(ty::FloatVar(vid)) => {
+                match self.float_unification_table.borrow_mut().get(self.tcx, vid).value {
+                    None => return UnconstrainedFloat,
+                    _ => Neither,
+                }
+            },
+            _ => Neither,
+        }
+    }
+
     pub fn combine_fields<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
                               -> CombineFields<'b, 'tcx> {
         CombineFields {infcx: self,
@@ -703,8 +725,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn sub_poly_trait_refs(&self,
                                a_is_expected: bool,
                                origin: TypeOrigin,
-                               a: Rc<ty::PolyTraitRef<'tcx>>,
-                               b: Rc<ty::PolyTraitRef<'tcx>>)
+                               a: ty::PolyTraitRef<'tcx>,
+                               b: ty::PolyTraitRef<'tcx>)
                                -> ures<'tcx>
     {
         debug!("sub_poly_trait_refs({} <: {})",
@@ -715,7 +737,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 origin: origin,
                 values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
             };
-            self.sub(a_is_expected, trace).binders(&*a, &*b).to_ures()
+            self.sub(a_is_expected, trace).binders(&a, &b).to_ures()
         })
     }
 
@@ -750,7 +772,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                          -> T
         where T : TypeFoldable<'tcx> + Repr<'tcx>
     {
-        /*! See `higher_ranked::leak_check` */
+        /*! See `higher_ranked::plug_leaks` */
 
         higher_ranked::plug_leaks(self, skol_map, snapshot, value)
     }
@@ -796,7 +818,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     pub fn next_ty_vars(&self, n: uint) -> Vec<Ty<'tcx>> {
-        Vec::from_fn(n, |_i| self.next_ty_var())
+        range(0, n).map(|_i| self.next_ty_var()).collect()
     }
 
     pub fn next_int_var_id(&self) -> IntVid {
@@ -861,10 +883,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
         let regions = self.region_vars_for_defs(span, region_param_defs);
 
-        let assoc_type_parameter_count = generics.types.len(subst::AssocSpace);
-        let assoc_type_parameters = self.next_ty_vars(assoc_type_parameter_count);
-
-        subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty)
+        subst::Substs::new_trait(type_parameters, regions, self_ty)
     }
 
     pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
@@ -1058,12 +1077,12 @@ impl<'tcx> TypeTrace<'tcx> {
         self.origin.span()
     }
 
-    pub fn dummy() -> TypeTrace<'tcx> {
+    pub fn dummy(tcx: &ty::ctxt<'tcx>) -> TypeTrace<'tcx> {
         TypeTrace {
             origin: Misc(codemap::DUMMY_SP),
             values: Types(ty::expected_found {
-                expected: ty::mk_err(),
-                found: ty::mk_err(),
+                expected: tcx.types.err,
+                found: tcx.types.err,
             })
         }
     }
diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs
index 0ca1a593ce7..8455ee3955b 100644
--- a/src/librustc/middle/infer/region_inference/graphviz.rs
+++ b/src/librustc/middle/infer/region_inference/graphviz.rs
@@ -136,7 +136,7 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
         let mut i = 0;
         let mut node_ids = FnvHashMap::new();
         {
-            let add_node = |node| {
+            let mut add_node = |&mut : node| {
                 if let Vacant(e) = node_ids.entry(node) {
                     e.set(i);
                     i += 1;
diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs
index 99c6f732c36..6ac1c5470cc 100644
--- a/src/librustc/middle/infer/region_inference/mod.rs
+++ b/src/librustc/middle/infer/region_inference/mod.rs
@@ -34,6 +34,7 @@ use util::ppaux::Repr;
 
 use std::cell::{Cell, RefCell};
 use std::cmp::Ordering::{mod, Less, Greater, Equal};
+use std::iter::repeat;
 use std::u32;
 use syntax::ast;
 
@@ -976,7 +977,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
     }
 
     fn construct_var_data(&self) -> Vec<VarData> {
-        Vec::from_fn(self.num_vars() as uint, |_| {
+        range(0, self.num_vars() as uint).map(|_| {
             VarData {
                 // All nodes are initially classified as contracting; during
                 // the expansion phase, we will shift the classification for
@@ -985,7 +986,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                 classification: Contracting,
                 value: NoValue,
             }
-        })
+        }).collect()
     }
 
     fn dump_constraints(&self) {
@@ -1248,7 +1249,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // idea is to report errors that derive from independent
         // regions of the graph, but not those that derive from
         // overlapping locations.
-        let mut dup_vec = Vec::from_elem(self.num_vars() as uint, u32::MAX);
+        let mut dup_vec: Vec<_> = repeat(u32::MAX).take(self.num_vars() as uint).collect();
 
         let mut opt_graph = None;
 
@@ -1309,7 +1310,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             }
         }
 
-        Vec::from_fn(self.num_vars() as uint, |idx| var_data[idx].value)
+        range(0, self.num_vars() as uint).map(|idx| var_data[idx].value).collect()
     }
 
     fn construct_graph(&self) -> RegionGraph {
diff --git a/src/librustc/middle/infer/resolve.rs b/src/librustc/middle/infer/resolve.rs
index 12400de31ed..ca2ae25e6c6 100644
--- a/src/librustc/middle/infer/resolve.rs
+++ b/src/librustc/middle/infer/resolve.rs
@@ -83,15 +83,15 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
             match t.sty {
                 ty::ty_infer(ty::TyVar(vid)) => {
                     self.err = Some(unresolved_ty(vid));
-                    ty::mk_err()
+                    self.tcx().types.err
                 }
                 ty::ty_infer(ty::IntVar(vid)) => {
                     self.err = Some(unresolved_int_ty(vid));
-                    ty::mk_err()
+                    self.tcx().types.err
                 }
                 ty::ty_infer(ty::FloatVar(vid)) => {
                     self.err = Some(unresolved_float_ty(vid));
-                    ty::mk_err()
+                    self.tcx().types.err
                 }
                 ty::ty_infer(_) => {
                     self.infcx.tcx.sess.bug(
diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs
index 2b8adfb7c1e..4bd3308728c 100644
--- a/src/librustc/middle/infer/sub.rs
+++ b/src/librustc/middle/infer/sub.rs
@@ -146,7 +146,7 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
             }
 
             (&ty::ty_err, _) | (_, &ty::ty_err) => {
-                Ok(ty::mk_err())
+                Ok(self.tcx().types.err)
             }
 
             _ => {
diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs
index dcf70263c0a..3127ef5d8a5 100644
--- a/src/librustc/middle/infer/unify.rs
+++ b/src/librustc/middle/infer/unify.rs
@@ -225,7 +225,7 @@ impl<K,V> sv::SnapshotVecDelegate<VarValue<K,V>,()> for Delegate {
 /// Indicates a type that does not have any kind of subtyping
 /// relationship.
 pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Repr<'tcx> {
-    fn to_type(&self) -> Ty<'tcx>;
+    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
     fn to_type_err(expected_found<Self>) -> ty::type_err<'tcx>;
 }
 
@@ -337,7 +337,7 @@ impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option<V>>>
         let node_a = table.borrow_mut().get(tcx, a_id);
         match node_a.value {
             None => None,
-            Some(ref a_t) => Some(a_t.to_type())
+            Some(ref a_t) => Some(a_t.to_type(tcx))
         }
     }
 }
@@ -363,10 +363,10 @@ impl<'tcx> UnifyKey<'tcx, Option<IntVarValue>> for ty::IntVid {
 }
 
 impl<'tcx> SimplyUnifiable<'tcx> for IntVarValue {
-    fn to_type(&self) -> Ty<'tcx> {
+    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         match *self {
-            ty::IntType(i) => ty::mk_mach_int(i),
-            ty::UintType(i) => ty::mk_mach_uint(i),
+            ty::IntType(i) => ty::mk_mach_int(tcx, i),
+            ty::UintType(i) => ty::mk_mach_uint(tcx, i),
         }
     }
 
@@ -399,8 +399,8 @@ impl<'tcx> UnifyValue<'tcx> for Option<ast::FloatTy> {
 }
 
 impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy {
-    fn to_type(&self) -> Ty<'tcx> {
-        ty::mk_mach_float(*self)
+    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
+        ty::mk_mach_float(tcx, *self)
     }
 
     fn to_type_err(err: expected_found<ast::FloatTy>) -> ty::type_err<'tcx> {
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index ba18c02f52d..df06b3b7789 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -10,9 +10,10 @@
 
 use metadata::csearch;
 use middle::def::DefFn;
-use middle::subst::Subst;
+use middle::subst::{Subst, Substs, EnumeratedItems};
 use middle::ty::{TransmuteRestriction, ctxt, ty_bare_fn};
 use middle::ty::{mod, Ty};
+use util::ppaux::Repr;
 
 use syntax::abi::RustIntrinsic;
 use syntax::ast::DefId;
@@ -23,52 +24,31 @@ use syntax::parse::token;
 use syntax::visit::Visitor;
 use syntax::visit;
 
-fn type_size_is_affected_by_type_parameters<'tcx>(tcx: &ty::ctxt<'tcx>, typ: Ty<'tcx>)
-                                                  -> bool {
-    let mut result = false;
-    ty::maybe_walk_ty(typ, |typ| {
-        match typ.sty {
-            ty::ty_uniq(_) | ty::ty_ptr(_) | ty::ty_rptr(..) |
-            ty::ty_bare_fn(..) | ty::ty_closure(..) => {
-                false
-            }
-            ty::ty_param(_) => {
-                result = true;
-                // No need to continue; we now know the result.
-                false
-            }
-            ty::ty_enum(did, substs) => {
-                for enum_variant in (*ty::enum_variants(tcx, did)).iter() {
-                    for argument_type in enum_variant.args.iter() {
-                        let argument_type = argument_type.subst(tcx, substs);
-                        result = result ||
-                            type_size_is_affected_by_type_parameters(
-                                tcx,
-                                argument_type);
-                    }
-                }
-
-                // Don't traverse substitutions.
-                false
-            }
-            ty::ty_struct(did, substs) => {
-                for field in ty::struct_fields(tcx, did, substs).iter() {
-                    result = result ||
-                        type_size_is_affected_by_type_parameters(tcx,
-                                                                 field.mt.ty);
-                }
-
-                // Don't traverse substitutions.
-                false
-            }
-            _ => true,
-        }
-    });
-    result
+pub fn check_crate(tcx: &ctxt) {
+    let mut visitor = IntrinsicCheckingVisitor {
+        tcx: tcx,
+        param_envs: Vec::new(),
+        dummy_sized_ty: tcx.types.int,
+        dummy_unsized_ty: ty::mk_vec(tcx, tcx.types.int, None),
+    };
+    visit::walk_crate(&mut visitor, tcx.map.krate());
 }
 
 struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> {
     tcx: &'a ctxt<'tcx>,
+
+    // As we traverse the AST, we keep a stack of the parameter
+    // environments for each function we encounter. When we find a
+    // call to `transmute`, we can check it in the context of the top
+    // of the stack (which ought not to be empty).
+    param_envs: Vec<ty::ParameterEnvironment<'tcx>>,
+
+    // Dummy sized/unsized types that use to substitute for type
+    // parameters in order to estimate how big a type will be for any
+    // possible instantiation of the type parameters in scope.  See
+    // `check_transmute` for more details.
+    dummy_sized_ty: Ty<'tcx>,
+    dummy_unsized_ty: Ty<'tcx>,
 }
 
 impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
@@ -97,26 +77,175 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
     }
 
     fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>, id: ast::NodeId) {
-        if type_size_is_affected_by_type_parameters(self.tcx, from) {
+        // Find the parameter environment for the most recent function that
+        // we entered.
+
+        let param_env = match self.param_envs.last() {
+            Some(p) => p,
+            None => {
+                self.tcx.sess.span_bug(
+                    span,
+                    "transmute encountered outside of any fn");
+            }
+        };
+
+        // Simple case: no type parameters involved.
+        if
+            !ty::type_has_params(from) && !ty::type_has_self(from) &&
+            !ty::type_has_params(to) && !ty::type_has_self(to)
+        {
+            let restriction = TransmuteRestriction {
+                span: span,
+                original_from: from,
+                original_to: to,
+                substituted_from: from,
+                substituted_to: to,
+                id: id,
+            };
+            self.push_transmute_restriction(restriction);
+            return;
+        }
+
+        // The rules around type parameters are a bit subtle. We are
+        // checking these rules before monomorphization, so there may
+        // be unsubstituted type parameters present in the
+        // types. Obviously we cannot create LLVM types for those.
+        // However, if a type parameter appears only indirectly (i.e.,
+        // through a pointer), it does not necessarily affect the
+        // size, so that should be allowed. The only catch is that we
+        // DO want to be careful around unsized type parameters, since
+        // fat pointers have a different size than a thin pointer, and
+        // hence `&T` and `&U` have different sizes if `T : Sized` but
+        // `U : Sized` does not hold.
+        //
+        // However, it's not as simple as checking whether `T :
+        // Sized`, because even if `T : Sized` does not hold, that
+        // just means that `T` *may* not be sized.  After all, even a
+        // type parameter `Sized? T` could be bound to a sized
+        // type. (Issue #20116)
+        //
+        // To handle this, we first check for "interior" type
+        // parameters, which are always illegal. If there are none of
+        // those, then we know that the only way that all type
+        // parameters `T` are referenced indirectly, e.g. via a
+        // pointer type like `&T`. In that case, we only care whether
+        // `T` is sized or not, because that influences whether `&T`
+        // is a thin or fat pointer.
+        //
+        // One could imagine establishing a sophisticated constraint
+        // system to ensure that the transmute is legal, but instead
+        // we do something brutally dumb. We just substitute dummy
+        // sized or unsized types for every type parameter in scope,
+        // exhaustively checking all possible combinations. Here are some examples:
+        //
+        // ```
+        // fn foo<T,U>() {
+        //     // T=int, U=int
+        // }
+        //
+        // fn bar<Sized? T,U>() {
+        //     // T=int, U=int
+        //     // T=[int], U=int
+        // }
+        //
+        // fn baz<Sized? T, Sized?U>() {
+        //     // T=int, U=int
+        //     // T=[int], U=int
+        //     // T=int, U=[int]
+        //     // T=[int], U=[int]
+        // }
+        // ```
+        //
+        // In all cases, we keep the original unsubstituted types
+        // around for error reporting.
+
+        let from_tc = ty::type_contents(self.tcx, from);
+        let to_tc = ty::type_contents(self.tcx, to);
+        if from_tc.interior_param() || to_tc.interior_param() {
             span_err!(self.tcx.sess, span, E0139,
-                      "cannot transmute from a type that contains type parameters");
+                      "cannot transmute to or from a type that contains \
+                       type parameters in its interior");
+            return;
         }
-        if type_size_is_affected_by_type_parameters(self.tcx, to) {
-            span_err!(self.tcx.sess, span, E0140,
-                      "cannot transmute to a type that contains type parameters");
+
+        let mut substs = param_env.free_substs.clone();
+        self.with_each_combination(
+            param_env,
+            param_env.free_substs.types.iter_enumerated(),
+            &mut substs,
+            &mut |substs| {
+                let restriction = TransmuteRestriction {
+                    span: span,
+                    original_from: from,
+                    original_to: to,
+                    substituted_from: from.subst(self.tcx, substs),
+                    substituted_to: to.subst(self.tcx, substs),
+                    id: id,
+                };
+                self.push_transmute_restriction(restriction);
+            });
+    }
+
+    fn with_each_combination(&self,
+                             param_env: &ty::ParameterEnvironment<'tcx>,
+                             mut types_in_scope: EnumeratedItems<Ty<'tcx>>,
+                             substs: &mut Substs<'tcx>,
+                             callback: &mut FnMut(&Substs<'tcx>))
+    {
+        // This parameter invokes `callback` many times with different
+        // substitutions that replace all the parameters in scope with
+        // either `int` or `[int]`, depending on whether the type
+        // parameter is known to be sized. See big comment above for
+        // an explanation of why this is a reasonable thing to do.
+
+        match types_in_scope.next() {
+            None => {
+                debug!("with_each_combination(substs={})",
+                       substs.repr(self.tcx));
+
+                callback.call_mut((substs,));
+            }
+
+            Some((space, index, &param_ty)) => {
+                debug!("with_each_combination: space={}, index={}, param_ty={}",
+                       space, index, param_ty.repr(self.tcx));
+
+                if !ty::type_is_sized(self.tcx, param_ty, param_env) {
+                    debug!("with_each_combination: param_ty is not known to be sized");
+
+                    substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty;
+                    self.with_each_combination(param_env, types_in_scope.clone(), substs, callback);
+                }
+
+                substs.types.get_mut_slice(space)[index] = self.dummy_sized_ty;
+                self.with_each_combination(param_env, types_in_scope, substs, callback);
+            }
         }
+    }
 
-        let restriction = TransmuteRestriction {
-            span: span,
-            from: from,
-            to: to,
-            id: id,
-        };
+    fn push_transmute_restriction(&self, restriction: TransmuteRestriction<'tcx>) {
+        debug!("Pushing transmute restriction: {}", restriction.repr(self.tcx));
         self.tcx.transmute_restrictions.borrow_mut().push(restriction);
     }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
+    fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
+                b: &'v ast::Block, s: Span, id: ast::NodeId) {
+        match fk {
+            visit::FkItemFn(..) | visit::FkMethod(..) => {
+                let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
+                self.param_envs.push(param_env);
+                visit::walk_fn(self, fk, fd, b, s);
+                self.param_envs.pop();
+            }
+            visit::FkFnBlock(..) => {
+                visit::walk_fn(self, fk, fd, b, s);
+            }
+        }
+
+    }
+
     fn visit_expr(&mut self, expr: &ast::Expr) {
         if let ast::ExprPath(..) = expr.node {
             match ty::resolve_expr(self.tcx, expr) {
@@ -144,7 +273,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: &ctxt) {
-    visit::walk_crate(&mut IntrinsicCheckingVisitor { tcx: tcx },
-                      tcx.map.krate());
+impl<'tcx> Repr<'tcx> for TransmuteRestriction<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        format!("TransmuteRestriction(id={}, original=({},{}), substituted=({},{}))",
+                self.id,
+                self.original_from.repr(tcx),
+                self.original_to.repr(tcx),
+                self.substituted_from.repr(tcx),
+                self.substituted_to.repr(tcx))
+    }
 }
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 6d2db056894..78fabcd588a 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -270,6 +270,7 @@ lets_do_this! {
     SliceMutTraitLangItem,           "slice_mut",               slice_mut_trait;
     RangeStructLangItem,             "range",                   range_struct;
     RangeFromStructLangItem,         "range_from",              range_from_struct;
+    RangeToStructLangItem,           "range_to",                range_to_struct;
     FullRangeStructLangItem,         "full_range",              full_range_struct;
 
     UnsafeTypeLangItem,              "unsafe",                  unsafe_type;
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index f59a67e2e80..0c3438abb2b 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -111,12 +111,15 @@ use self::VarKind::*;
 
 use middle::def::*;
 use middle::mem_categorization::Typer;
-use middle::{pat_util, ty};
+use middle::pat_util;
+use middle::ty;
+use middle::ty::UnboxedClosureTyper;
 use lint;
 use util::nodemap::NodeMap;
 
 use std::{fmt, io, uint};
 use std::rc::Rc;
+use std::iter::repeat;
 use syntax::ast::{mod, NodeId, Expr};
 use syntax::codemap::{BytePos, original_sp, Span};
 use syntax::parse::token::{mod, special_idents};
@@ -514,7 +517,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
       ast::ExprBlock(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) |
       ast::ExprMac(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
       ast::ExprParen(..) | ast::ExprInlineAsm(..) | ast::ExprBox(..) |
-      ast::ExprSlice(..) | ast::ExprRange(..) => {
+      ast::ExprRange(..) => {
           visit::walk_expr(ir, expr);
       }
     }
@@ -575,8 +578,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         Liveness {
             ir: ir,
             s: specials,
-            successors: Vec::from_elem(num_live_nodes, invalid_node()),
-            users: Vec::from_elem(num_live_nodes * num_vars, invalid_users()),
+            successors: repeat(invalid_node()).take(num_live_nodes).collect(),
+            users: repeat(invalid_users()).take(num_live_nodes * num_vars).collect(),
             loop_scope: Vec::new(),
             break_ln: NodeMap::new(),
             cont_ln: NodeMap::new(),
@@ -1068,7 +1071,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 // the same bindings, and we also consider the first pattern to be
                 // the "authoritative" set of ids
                 let arm_succ =
-                    self.define_bindings_in_arm_pats(arm.pats.head().map(|p| &**p),
+                    self.define_bindings_in_arm_pats(arm.pats.first().map(|p| &**p),
                                                      guard_succ);
                 self.merge_from_succ(ln, arm_succ, first_merge);
                 first_merge = false;
@@ -1191,15 +1194,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**l, r_succ)
           }
 
-          ast::ExprSlice(ref e1, ref e2, ref e3, _) => {
-            let succ = e3.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
-            let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
-            self.propagate_through_expr(&**e1, succ)
-          }
-
           ast::ExprRange(ref e1, ref e2) => {
             let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
-            self.propagate_through_expr(&**e1, succ)
+            e1.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ))
           }
 
           ast::ExprBox(None, ref e) |
@@ -1442,7 +1439,7 @@ fn check_arm(this: &mut Liveness, arm: &ast::Arm) {
     // only consider the first pattern; any later patterns must have
     // the same bindings, and we also consider the first pattern to be
     // the "authoritative" set of ids
-    this.arm_pats_bindings(arm.pats.head().map(|p| &**p), |this, ln, var, sp, id| {
+    this.arm_pats_bindings(arm.pats.first().map(|p| &**p), |this, ln, var, sp, id| {
         this.warn_about_unused(sp, id, ln, var);
     });
     visit::walk_arm(this, arm);
@@ -1495,7 +1492,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::ExprSlice(..) | ast::ExprRange(..) => {
+      ast::ExprRange(..) => {
         visit::walk_expr(this, expr);
       }
       ast::ExprIfLet(..) => {
@@ -1520,16 +1517,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn fn_ret(&self, id: NodeId) -> ty::FnOutput<'tcx> {
         let fn_ty = ty::node_id_to_type(self.ir.tcx, id);
         match fn_ty.sty {
-            ty::ty_unboxed_closure(closure_def_id, _, _) =>
-                self.ir.tcx.unboxed_closures()
-                    .borrow()
-                    .get(&closure_def_id)
-                    .unwrap()
-                    .closure_type
-                    .sig
-                    .0
-                    .output,
-            _ => ty::ty_fn_ret(fn_ty)
+            ty::ty_unboxed_closure(closure_def_id, _, substs) =>
+                self.ir.tcx.unboxed_closure_type(closure_def_id, substs).sig.0.output,
+            _ =>
+                ty::ty_fn_ret(fn_ty),
         }
     }
 
@@ -1548,7 +1539,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 } else {
                     let ends_with_stmt = match body.expr {
                         None if body.stmts.len() > 0 =>
-                            match body.stmts.last().unwrap().node {
+                            match body.stmts.first().unwrap().node {
                                 ast::StmtSemi(ref e, _) => {
                                     ty::expr_ty(self.ir.tcx, &**e) == t_ret
                                 },
@@ -1559,7 +1550,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                     self.ir.tcx.sess.span_err(
                         sp, "not all control paths return a value");
                     if ends_with_stmt {
-                        let last_stmt = body.stmts.last().unwrap();
+                        let last_stmt = body.stmts.first().unwrap();
                         let original_span = original_sp(self.ir.tcx.sess.codemap(),
                                                         last_stmt.span, sp);
                         let span_semicolon = Span {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 87841c7675b..70942a950e3 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -74,7 +74,7 @@ pub use self::categorization::*;
 use middle::def;
 use middle::region;
 use middle::ty::{mod, Ty};
-use util::nodemap::{DefIdMap, NodeMap};
+use util::nodemap::{NodeMap};
 use util::ppaux::{ty_to_string, Repr};
 
 use syntax::ast::{MutImmutable, MutMutable};
@@ -280,7 +280,7 @@ impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
 /// In the borrow checker, in contrast, type checking is complete and we
 /// know that no errors have occurred, so we simply consult the tcx and we
 /// can be sure that only `Ok` results will occur.
-pub trait Typer<'tcx> {
+pub trait Typer<'tcx> : ty::UnboxedClosureTyper<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
     fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx>;
     fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx>;
@@ -290,11 +290,9 @@ pub trait Typer<'tcx> {
     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>;
     fn is_method_call(&self, id: ast::NodeId) -> bool;
     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>;
-    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
+    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow>;
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
                     -> ast::CaptureClause;
-    fn unboxed_closures<'a>(&'a self)
-                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>;
 }
 
 impl MutabilityCategory {
@@ -500,21 +498,28 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             self.cat_tup_field(expr, base_cmt, idx.node, expr_ty)
           }
 
-          ast::ExprIndex(ref base, _) => {
-            let method_call = ty::MethodCall::expr(expr.id());
-            match self.typer.node_method_ty(method_call) {
-                Some(method_ty) => {
-                    // If this is an index implemented by a method call, then it will
-                    // include an implicit deref of the result.
-                    let ret_ty = ty::ty_fn_ret(method_ty).unwrap();
-                    self.cat_deref(expr,
-                                   self.cat_rvalue_node(expr.id(),
-                                                        expr.span(),
-                                                        ret_ty), 1, true)
+          ast::ExprIndex(ref base, ref idx) => {
+            match idx.node {
+                ast::ExprRange(..) => {
+                    // Slicing syntax special case (KILLME).
+                    self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
                 }
-                None => {
-                    let base_cmt = self.cat_expr(&**base);
-                    self.cat_index(expr, base_cmt)
+                _ => {
+                    let method_call = ty::MethodCall::expr(expr.id());
+                    match self.typer.node_method_ty(method_call) {
+                        Some(method_ty) => {
+                            // If this is an index implemented by a method call, then it will
+                            // include an implicit deref of the result.
+                            let ret_ty = ty::ty_fn_ret(method_ty).unwrap();
+                            self.cat_deref(expr,
+                                           self.cat_rvalue_node(expr.id(),
+                                                                expr.span(),
+                                                                ret_ty), 1, true)
+                        }
+                        None => {
+                            self.cat_index(expr, self.cat_expr(&**base))
+                        }
+                    }
                 }
             }
           }
@@ -531,7 +536,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           ast::ExprAddrOf(..) | ast::ExprCall(..) |
           ast::ExprAssign(..) | ast::ExprAssignOp(..) |
           ast::ExprClosure(..) | ast::ExprRet(..) |
-          ast::ExprUnary(..) | ast::ExprSlice(..) | ast::ExprRange(..) |
+          ast::ExprUnary(..) | ast::ExprRange(..) |
           ast::ExprMethodCall(..) | ast::ExprCast(..) |
           ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
           ast::ExprBinary(..) | ast::ExprWhile(..) |
@@ -615,8 +620,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                       self.cat_upvar(id, span, var_id, fn_node_id, kind, mode, false)
                   }
                   ty::ty_unboxed_closure(closure_id, _, _) => {
-                      let unboxed_closures = self.typer.unboxed_closures().borrow();
-                      let kind = (*unboxed_closures)[closure_id].kind;
+                      let kind = self.typer.unboxed_closure_kind(closure_id);
                       let mode = self.typer.capture_mode(fn_node_id);
                       self.cat_upvar(id, span, var_id, fn_node_id, kind, mode, true)
                   }
@@ -748,7 +752,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                         // instead of bothering to construct a proper
                         // one.
                         base.mutbl = McImmutable;
-                        base.ty = ty::mk_err();
+                        base.ty = self.tcx().types.err;
                         Rc::new(cmt_ {
                             id: id,
                             span: span,
@@ -774,7 +778,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                         is_unboxed: is_unboxed
                     }),
                     mutbl: McImmutable,
-                    ty: ty::mk_err(),
+                    ty: self.tcx().types.err,
                     note: NoteNone
                 };
 
@@ -785,7 +789,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                             span: span,
                             cat: cat_deref(Rc::new(base), 0, env_ptr),
                             mutbl: env_mutbl,
-                            ty: ty::mk_err(),
+                            ty: self.tcx().types.err,
                             note: NoteClosureEnv(upvar_id)
                         };
                     }
@@ -793,7 +797,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 }
 
                 // Look up upvar borrow so we can get its region
-                let upvar_borrow = self.typer.upvar_borrow(upvar_id);
+                let upvar_borrow = self.typer.upvar_borrow(upvar_id).unwrap();
                 let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region);
 
                 Rc::new(cmt_ {
@@ -980,7 +984,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 ty::ty_fn_args(method_ty)[0]
             }
             None => {
-                match ty::array_element_ty(base_cmt.ty) {
+                match ty::array_element_ty(self.tcx(), base_cmt.ty) {
                     Some(ty) => ty,
                     None => {
                         self.tcx().sess.span_bug(
@@ -1115,11 +1119,15 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         })
     }
 
-    // FIXME(#19596) unbox `op`
-    pub fn cat_pattern(&self,
-                       cmt: cmt<'tcx>,
-                       pat: &ast::Pat,
-                       op: |&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat|)
+    pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, mut op: F) where
+        F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
+    {
+        self.cat_pattern_(cmt, pat, &mut op)
+    }
+
+    // FIXME(#19596) This is a workaround, but there should be a better way to do this
+    fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F) where
+        F: FnMut(&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat),
     {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
@@ -1170,7 +1178,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                pat.id, pprust::pat_to_string(pat),
                cmt.repr(self.tcx()));
 
-        op(self, cmt.clone(), pat);
+        (*op)(self, cmt.clone(), pat);
 
         let def_map = self.tcx().def_map.borrow();
         let opt_def = def_map.get(&pat.id);
@@ -1207,7 +1215,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                                 pat, cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
 
-                        self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z));
+                        self.cat_pattern_(subcmt, &**subpat, op);
                     }
                 }
                 Some(&def::DefStruct(..)) => {
@@ -1217,13 +1225,12 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                             self.cat_imm_interior(
                                 pat, cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
-                        self.cat_pattern(cmt_field, &**subpat,
-                                         |x,y,z| op(x,y,z));
+                        self.cat_pattern_(cmt_field, &**subpat, op);
                     }
                 }
                 Some(&def::DefConst(..)) => {
                     for subpat in subpats.iter() {
-                        self.cat_pattern(cmt.clone(), &**subpat, |x,y,z| op(x,y,z));
+                        self.cat_pattern_(cmt.clone(), &**subpat, op);
                     }
                 }
                 _ => {
@@ -1235,7 +1242,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           }
 
           ast::PatIdent(_, _, Some(ref subpat)) => {
-              self.cat_pattern(cmt, &**subpat, op);
+              self.cat_pattern_(cmt, &**subpat, op);
           }
 
           ast::PatIdent(_, _, None) => {
@@ -1247,7 +1254,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             for fp in field_pats.iter() {
                 let field_ty = self.pat_ty(&*fp.node.pat); // see (*2)
                 let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.ident.name, field_ty);
-                self.cat_pattern(cmt_field, &*fp.node.pat, |x,y,z| op(x,y,z));
+                self.cat_pattern_(cmt_field, &*fp.node.pat, op);
             }
           }
 
@@ -1259,29 +1266,28 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                     self.cat_imm_interior(
                         pat, cmt.clone(), subpat_ty,
                         InteriorField(PositionalField(i)));
-                self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z));
+                self.cat_pattern_(subcmt, &**subpat, op);
             }
           }
 
           ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
             // @p1, ~p1, ref p1
             let subcmt = self.cat_deref(pat, cmt, 0, false);
-            self.cat_pattern(subcmt, &**subpat, op);
+            self.cat_pattern_(subcmt, &**subpat, op);
           }
 
           ast::PatVec(ref before, ref slice, ref after) => {
               let elt_cmt = self.cat_index(pat, self.deref_vec(pat, cmt));
               for before_pat in before.iter() {
-                  self.cat_pattern(elt_cmt.clone(), &**before_pat,
-                                   |x,y,z| op(x,y,z));
+                  self.cat_pattern_(elt_cmt.clone(), &**before_pat, op);
               }
               for slice_pat in slice.iter() {
                   let slice_ty = self.pat_ty(&**slice_pat);
                   let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
-                  self.cat_pattern(slice_cmt, &**slice_pat, |x,y,z| op(x,y,z));
+                  self.cat_pattern_(slice_cmt, &**slice_pat, op);
               }
               for after_pat in after.iter() {
-                  self.cat_pattern(elt_cmt.clone(), &**after_pat, |x,y,z| op(x,y,z));
+                  self.cat_pattern_(elt_cmt.clone(), &**after_pat, op);
               }
           }
 
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 6f63ae166fe..cfa0d419aa3 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -122,7 +122,7 @@ impl<'v> Visitor<'v> for ParentVisitor {
             // 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 => {
+            ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
                 for m in methods.iter() {
                     match *m {
                         ast::ProvidedMethod(ref m) => {
@@ -328,7 +328,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
 
             // Default methods on traits are all public so long as the trait
             // is public
-            ast::ItemTrait(_, _, _, _, ref methods) if public_first => {
+            ast::ItemTrait(_, _, _, ref methods) if public_first => {
                 for method in methods.iter() {
                     match *method {
                         ast::ProvidedMethod(ref m) => {
@@ -749,12 +749,9 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
     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 = |&: tyname: &str| {
             let ck_public = |def: ast::DefId| {
-                let name = token::get_ident(path.segments
-                                                .last()
-                                                .unwrap()
-                                                .identifier);
+                let name = token::get_ident(path.segments.last().unwrap().identifier);
                 let origdid = orig_def.def_id();
                 self.ensure_public(span,
                                    def,
@@ -924,7 +921,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                 }
             }
             ast::ExprPath(..) => {
-                let guard = |did: ast::DefId| {
+                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 && (
@@ -1129,7 +1126,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
     /// 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| {
+        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 {
@@ -1178,7 +1175,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                 }
             }
 
-            ast::ItemTrait(_, _, _, _, ref methods) => {
+            ast::ItemTrait(_, _, _, ref methods) => {
                 for m in methods.iter() {
                     match *m {
                         ast::ProvidedMethod(ref m) => {
@@ -1209,7 +1206,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                 tcx.sess.span_err(sp, "visibility has no effect inside functions");
             }
         }
-        let check_struct = |def: &ast::StructDef| {
+        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),
@@ -1242,7 +1239,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
 
             ast::ItemStruct(ref def, _) => check_struct(&**def),
 
-            ast::ItemTrait(_, _, _, _, ref methods) => {
+            ast::ItemTrait(_, _, _, ref methods) => {
                 for m in methods.iter() {
                     match *m {
                         ast::RequiredMethod(..) => {}
@@ -1306,7 +1303,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
 
     fn check_ty_param_bound(&self,
                             ty_param_bound: &ast::TyParamBound) {
-        if let ast::TraitTyParamBound(ref trait_ref) = *ty_param_bound {
+        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;
@@ -1349,7 +1346,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
             // namespace (the contents have their own privacies).
             ast::ItemForeignMod(_) => {}
 
-            ast::ItemTrait(_, _, _, ref bounds, _) => {
+            ast::ItemTrait(_, _, ref bounds, _) => {
                 if !self.trait_is_public(item.id) {
                     return
                 }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 8df78281cc2..be89b32cdaa 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -485,9 +485,10 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
 
     let prev_cx = visitor.cx;
     visitor.cx.parent = Some(expr.id);
+
     {
         let region_maps = &mut visitor.region_maps;
-        let terminating = |id| {
+        let terminating = |&: id| {
             let scope = CodeExtent::from_node_id(id);
             region_maps.mark_as_terminating_scope(scope)
         };
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 22dea3be1d4..e9504a92f7b 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -105,7 +105,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                 ast::ItemTy(_, ref generics) |
                 ast::ItemEnum(_, ref generics) |
                 ast::ItemStruct(_, ref generics) |
-                ast::ItemTrait(_, ref generics, _, _, _) |
+                ast::ItemTrait(_, ref generics, _, _) |
                 ast::ItemImpl(_, ref generics, _, _, _) => {
                     // These kinds of items have only early bound lifetime parameters.
                     let lifetimes = &generics.lifetimes;
@@ -232,7 +232,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
         }
     }
 
-    fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) {
+    fn visit_poly_trait_ref(&mut self, trait_ref:
+                            &ast::PolyTraitRef,
+                            _modifier: &ast::TraitBoundModifier) {
         debug!("visit_poly_trait_ref trait_ref={}", trait_ref);
 
         self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |old_scope, this| {
@@ -294,7 +296,7 @@ impl<'a> LifetimeContext<'a> {
         debug!("visit_early_late: referenced_idents={}",
                referenced_idents);
 
-        let (early, late) = generics.lifetimes.clone().partition(
+        let (early, late): (Vec<_>, _) = generics.lifetimes.iter().cloned().partition(
             |l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
 
         self.with(EarlyScope(early_space, &early, self.scope), move |old_scope, this| {
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index abacad7d37c..3c5459ff3bc 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -55,18 +55,17 @@ impl<'tcx> Substs<'tcx> {
                     r: Vec<ty::Region>)
                     -> Substs<'tcx>
     {
-        Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new(), Vec::new()),
-                    VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
+        Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
+                    VecPerParamSpace::new(r, Vec::new(), Vec::new()))
     }
 
     pub fn new_trait(t: Vec<Ty<'tcx>>,
                      r: Vec<ty::Region>,
-                     a: Vec<Ty<'tcx>>,
                      s: Ty<'tcx>)
                     -> Substs<'tcx>
     {
-        Substs::new(VecPerParamSpace::new(t, vec!(s), a, Vec::new()),
-                    VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
+        Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
+                    VecPerParamSpace::new(r, Vec::new(), Vec::new()))
     }
 
     pub fn erased(t: VecPerParamSpace<Ty<'tcx>>) -> Substs<'tcx>
@@ -123,13 +122,6 @@ impl<'tcx> Substs<'tcx> {
         s
     }
 
-    pub fn with_assoc_tys(&self, assoc_tys: Vec<Ty<'tcx>>) -> Substs<'tcx> {
-        assert!(self.types.is_empty_in(AssocSpace));
-        let mut s = (*self).clone();
-        s.types.replace(AssocSpace, assoc_tys);
-        s
-    }
-
     pub fn erase_regions(self) -> Substs<'tcx> {
         let Substs { types, regions: _ } = self;
         Substs { types: types, regions: ErasedRegions }
@@ -192,21 +184,19 @@ impl RegionSubsts {
 pub enum ParamSpace {
     TypeSpace,  // Type parameters attached to a type definition, trait, or impl
     SelfSpace,  // Self parameter on a trait
-    AssocSpace, // Assoc types defined in a trait/impl
     FnSpace,    // Type parameters attached to a method or fn
 }
 
 impl ParamSpace {
-    pub fn all() -> [ParamSpace, ..4] {
-        [TypeSpace, SelfSpace, AssocSpace, FnSpace]
+    pub fn all() -> [ParamSpace; 3] {
+        [TypeSpace, SelfSpace, FnSpace]
     }
 
     pub fn to_uint(self) -> uint {
         match self {
             TypeSpace => 0,
             SelfSpace => 1,
-            AssocSpace => 2,
-            FnSpace => 3,
+            FnSpace => 2,
         }
     }
 
@@ -214,8 +204,7 @@ impl ParamSpace {
         match u {
             0 => TypeSpace,
             1 => SelfSpace,
-            2 => AssocSpace,
-            3 => FnSpace,
+            2 => FnSpace,
             _ => panic!("Invalid ParamSpace: {}", u)
         }
     }
@@ -235,11 +224,9 @@ pub struct VecPerParamSpace<T> {
     //
     // AF(self) = (self.content[..self.type_limit],
     //             self.content[self.type_limit..self.self_limit],
-    //             self.content[self.self_limit..self.assoc_limit],
-    //             self.content[self.assoc_limit..])
+    //             self.content[self.self_limit..])
     type_limit: uint,
     self_limit: uint,
-    assoc_limit: uint,
     content: Vec<T>,
 }
 
@@ -248,7 +235,6 @@ pub struct VecPerParamSpace<T> {
 pub struct SeparateVecsPerParamSpace<T> {
     pub types: Vec<T>,
     pub selfs: Vec<T>,
-    pub assocs: Vec<T>,
     pub fns: Vec<T>,
 }
 
@@ -268,8 +254,7 @@ impl<T> VecPerParamSpace<T> {
         match space {
             TypeSpace => (0, self.type_limit),
             SelfSpace => (self.type_limit, self.self_limit),
-            AssocSpace => (self.self_limit, self.assoc_limit),
-            FnSpace => (self.assoc_limit, self.content.len()),
+            FnSpace => (self.self_limit, self.content.len()),
         }
     }
 
@@ -277,7 +262,6 @@ impl<T> VecPerParamSpace<T> {
         VecPerParamSpace {
             type_limit: 0,
             self_limit: 0,
-            assoc_limit: 0,
             content: Vec::new()
         }
     }
@@ -290,31 +274,27 @@ impl<T> VecPerParamSpace<T> {
     /// `s` is the self space.
     /// `a` is the assoc space.
     /// `f` is the fn space.
-    pub fn new(t: Vec<T>, s: Vec<T>, a: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
+    pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
         let type_limit = t.len();
         let self_limit = type_limit + s.len();
-        let assoc_limit = self_limit + a.len();
 
         let mut content = t;
         content.extend(s.into_iter());
-        content.extend(a.into_iter());
         content.extend(f.into_iter());
 
         VecPerParamSpace {
             type_limit: type_limit,
             self_limit: self_limit,
-            assoc_limit: assoc_limit,
             content: content,
         }
     }
 
-    fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint, assoc_limit: uint)
+    fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint)
                     -> VecPerParamSpace<T>
     {
         VecPerParamSpace {
             type_limit: type_limit,
             self_limit: self_limit,
-            assoc_limit: assoc_limit,
             content: content,
         }
     }
@@ -326,9 +306,8 @@ impl<T> VecPerParamSpace<T> {
     pub fn push(&mut self, space: ParamSpace, value: T) {
         let (_, limit) = self.limits(space);
         match space {
-            TypeSpace => { self.type_limit += 1; self.self_limit += 1; self.assoc_limit += 1; }
-            SelfSpace => { self.self_limit += 1; self.assoc_limit += 1; }
-            AssocSpace => { self.assoc_limit += 1; }
+            TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
+            SelfSpace => { self.self_limit += 1; }
             FnSpace => { }
         }
         self.content.insert(limit, value);
@@ -340,12 +319,15 @@ impl<T> VecPerParamSpace<T> {
             None
         } else {
             match space {
-                TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; self.assoc_limit -= 1; }
-                SelfSpace => { self.self_limit -= 1; self.assoc_limit -= 1; }
-                AssocSpace => { self.assoc_limit -= 1; }
+                TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
+                SelfSpace => { self.self_limit -= 1; }
                 FnSpace => {}
             }
-            self.content.remove(limit - 1)
+            if self.content.is_empty() {
+                None
+            } else {
+                Some(self.content.remove(limit - 1))
+            }
         }
     }
 
@@ -412,6 +394,10 @@ impl<T> VecPerParamSpace<T> {
         self.content.as_slice()
     }
 
+    pub fn to_vec(self) -> Vec<T> {
+        self.content
+    }
+
     pub fn all_vecs<P>(&self, mut pred: P) -> bool where
         P: FnMut(&[T]) -> bool,
     {
@@ -435,8 +421,7 @@ impl<T> VecPerParamSpace<T> {
         let result = self.iter().map(pred).collect();
         VecPerParamSpace::new_internal(result,
                                        self.type_limit,
-                                       self.self_limit,
-                                       self.assoc_limit)
+                                       self.self_limit)
     }
 
     pub fn map_enumerated<U, P>(&self, pred: P) -> VecPerParamSpace<U> where
@@ -445,8 +430,7 @@ impl<T> VecPerParamSpace<T> {
         let result = self.iter_enumerated().map(pred).collect();
         VecPerParamSpace::new_internal(result,
                                        self.type_limit,
-                                       self.self_limit,
-                                       self.assoc_limit)
+                                       self.self_limit)
     }
 
     pub fn map_move<U, F>(self, mut pred: F) -> VecPerParamSpace<U> where
@@ -455,25 +439,22 @@ impl<T> VecPerParamSpace<T> {
         let SeparateVecsPerParamSpace {
             types: t,
             selfs: s,
-            assocs: a,
             fns: f
         } = self.split();
 
         VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(),
                               s.into_iter().map(|p| pred(p)).collect(),
-                              a.into_iter().map(|p| pred(p)).collect(),
                               f.into_iter().map(|p| pred(p)).collect())
     }
 
     pub fn split(self) -> SeparateVecsPerParamSpace<T> {
-        let VecPerParamSpace { type_limit, self_limit, assoc_limit, content } = self;
+        let VecPerParamSpace { type_limit, self_limit, content } = self;
 
         let mut content_iter = content.into_iter();
 
         SeparateVecsPerParamSpace {
             types: content_iter.by_ref().take(type_limit).collect(),
             selfs: content_iter.by_ref().take(self_limit - type_limit).collect(),
-            assocs: content_iter.by_ref().take(assoc_limit - self_limit).collect(),
             fns: content_iter.collect()
         }
     }
@@ -487,6 +468,7 @@ impl<T> VecPerParamSpace<T> {
     }
 }
 
+#[deriving(Clone)]
 pub struct EnumeratedItems<'a,T:'a> {
     vec: &'a VecPerParamSpace<T>,
     space_index: uint,
diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs
index d48685ce27d..d8b39d92c69 100644
--- a/src/librustc/middle/traits/coherence.rs
+++ b/src/librustc/middle/traits/coherence.rs
@@ -45,7 +45,9 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
     let param_env = ty::empty_parameter_environment();
     let mut selcx = SelectionContext::intercrate(infcx, &param_env, infcx.tcx);
     let obligation = Obligation::new(ObligationCause::dummy(),
-                                     Rc::new(ty::Binder(impl1_trait_ref)));
+                                     ty::Binder(ty::TraitPredicate {
+                                         trait_ref: Rc::new(impl1_trait_ref),
+                                     }));
     debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx));
     selcx.evaluate_impl(impl2_def_id, &obligation)
 }
@@ -140,7 +142,7 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
         }
 
         ty::ty_trait(ref tt) => {
-            tt.principal.def_id().krate == ast::LOCAL_CRATE
+            tt.principal_def_id().krate == ast::LOCAL_CRATE
         }
 
         // Type parameters may be bound to types that are not local to
@@ -149,6 +151,11 @@ pub fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
             false
         }
 
+        // Associated types could be anything, I guess.
+        ty::ty_projection(..) => {
+            false
+        }
+
         ty::ty_infer(..) |
         ty::ty_open(..) |
         ty::ty_err => {
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index 462857de1d4..a0413701abc 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -8,12 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::{FulfillmentError, FulfillmentErrorCode,
-            ObligationCauseCode, SelectionError,
-            PredicateObligation, OutputTypeParameterMismatch};
+use super::{
+    FulfillmentError,
+    FulfillmentErrorCode,
+    MismatchedProjectionTypes,
+    ObligationCauseCode,
+    OutputTypeParameterMismatch,
+    PredicateObligation,
+    SelectionError,
+};
 
 use middle::infer::InferCtxt;
-use middle::ty::{mod};
+use middle::ty::{mod, AsPredicate, ReferencesError, ToPolyTraitRef};
 use syntax::codemap::Span;
 use util::ppaux::{Repr, UserString};
 
@@ -30,12 +36,32 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         FulfillmentErrorCode::CodeSelectionError(ref e) => {
             report_selection_error(infcx, &error.obligation, e);
         }
+        FulfillmentErrorCode::CodeProjectionError(ref e) => {
+            report_projection_error(infcx, &error.obligation, e);
+        }
         FulfillmentErrorCode::CodeAmbiguity => {
             maybe_report_ambiguity(infcx, &error.obligation);
         }
     }
 }
 
+pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+                                         obligation: &PredicateObligation<'tcx>,
+                                         error: &MismatchedProjectionTypes<'tcx>)
+{
+    let predicate =
+        infcx.resolve_type_vars_if_possible(&obligation.predicate);
+    if !predicate.references_error() {
+        infcx.tcx.sess.span_err(
+            obligation.cause.span,
+            format!(
+                "type mismatch resolving `{}`: {}",
+                predicate.user_string(infcx.tcx),
+                ty::type_err_to_str(infcx.tcx, &error.err)).as_slice());
+        note_obligation_cause(infcx, obligation);
+    }
+}
+
 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                         obligation: &PredicateObligation<'tcx>,
                                         error: &SelectionError<'tcx>)
@@ -43,71 +69,50 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     match *error {
         SelectionError::Overflow => {
             // We could track the stack here more precisely if we wanted, I imagine.
-            match obligation.trait_ref {
-                ty::Predicate::Trait(ref trait_ref) => {
-                    let trait_ref =
-                        infcx.resolve_type_vars_if_possible(&**trait_ref);
-                    infcx.tcx.sess.span_err(
-                        obligation.cause.span,
-                        format!(
-                            "overflow evaluating the trait `{}` for the type `{}`",
-                            trait_ref.user_string(infcx.tcx),
-                            trait_ref.self_ty().user_string(infcx.tcx))[]);
-                }
-
-                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::TypeOutlives(..) |
-                ty::Predicate::RegionOutlives(..) => {
-                    infcx.tcx.sess.span_err(
-                        obligation.cause.span,
-                        format!("overflow evaluating lifetime predicate").as_slice());
-                }
-            }
-
-            let current_limit = infcx.tcx.sess.recursion_limit.get();
-            let suggested_limit = current_limit * 2;
-            infcx.tcx.sess.span_note(
+            let predicate =
+                infcx.resolve_type_vars_if_possible(&obligation.predicate);
+            infcx.tcx.sess.span_err(
                 obligation.cause.span,
                 format!(
-                    "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-                    suggested_limit)[]);
+                    "overflow evaluating the requirement `{}`",
+                    predicate.user_string(infcx.tcx)).as_slice());
+
+            suggest_new_overflow_limit(infcx, obligation.cause.span);
 
             note_obligation_cause(infcx, obligation);
         }
         SelectionError::Unimplemented => {
-            match obligation.trait_ref {
-                ty::Predicate::Trait(ref trait_ref) => {
-                    let trait_ref =
-                        infcx.resolve_type_vars_if_possible(
-                            &**trait_ref);
-                    if !ty::type_is_error(trait_ref.self_ty()) {
+            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());
-                        note_obligation_cause(infcx, obligation);
                     }
                 }
 
                 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();
+                                                             &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!(
@@ -116,9 +121,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                             ty::type_err_to_str(infcx.tcx, &err)).as_slice());
                 }
 
-                ty::Predicate::TypeOutlives(..) |
-                ty::Predicate::RegionOutlives(..) => {
-                    let predicate = infcx.resolve_type_vars_if_possible(&obligation.trait_ref);
+                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!(
@@ -128,12 +134,8 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             }
         }
         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);
+            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);
             if !ty::type_is_error(actual_trait_ref.self_ty()) {
                 infcx.tcx.sess.span_err(
                     obligation.cause.span,
@@ -150,127 +152,114 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
-fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                    obligation: &PredicateObligation<'tcx>) {
+pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+                                        obligation: &PredicateObligation<'tcx>) {
     // Unable to successfully determine, probably means
     // insufficient type information, but could mean
     // ambiguous impls. The latter *ought* to be a
     // coherence violation, so we don't report it here.
 
-    let trait_ref = match obligation.trait_ref {
-        ty::Predicate::Trait(ref trait_ref) => {
-            infcx.resolve_type_vars_if_possible(&**trait_ref)
-        }
-        _ => {
-            infcx.tcx.sess.span_bug(
-                obligation.cause.span,
-                format!("ambiguity from something other than a trait: {}",
-                        obligation.trait_ref.repr(infcx.tcx)).as_slice());
-        }
-    };
-    let self_ty = trait_ref.self_ty();
+    let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
 
-    debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})",
-           trait_ref.repr(infcx.tcx),
-           self_ty.repr(infcx.tcx),
+    debug!("maybe_report_ambiguity(predicate={}, obligation={})",
+           predicate.repr(infcx.tcx),
            obligation.repr(infcx.tcx));
-    let all_types = &trait_ref.substs().types;
-    if all_types.iter().any(|&t| ty::type_is_error(t)) {
-    } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
-        // This is kind of a hack: it frequently happens that some earlier
-        // error prevents types from being fully inferred, and then we get
-        // a bunch of uninteresting errors saying something like "<generic
-        // #0> doesn't implement Sized".  It may even be true that we
-        // could just skip over all checks where the self-ty is an
-        // inference variable, but I was afraid that there might be an
-        // inference variable created, registered as an obligation, and
-        // then never forced by writeback, and hence by skipping here we'd
-        // be ignoring the fact that we don't KNOW the type works
-        // out. Though even that would probably be harmless, given that
-        // we're only talking about builtin traits, which are known to be
-        // inhabited. But in any case I just threw in this check for
-        // has_errors() to be sure that compilation isn't happening
-        // anyway. In that case, why inundate the user.
-        if !infcx.tcx.sess.has_errors() {
-            if infcx.tcx.lang_items.sized_trait()
-                  .map_or(false, |sized_id| sized_id == trait_ref.def_id()) {
-                infcx.tcx.sess.span_err(
+
+    match predicate {
+        ty::Predicate::Trait(ref data) => {
+            let trait_ref = data.to_poly_trait_ref();
+            let self_ty = trait_ref.self_ty();
+            let all_types = &trait_ref.substs().types;
+            if all_types.iter().any(|&t| ty::type_is_error(t)) {
+            } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
+                // This is kind of a hack: it frequently happens that some earlier
+                // error prevents types from being fully inferred, and then we get
+                // a bunch of uninteresting errors saying something like "<generic
+                // #0> doesn't implement Sized".  It may even be true that we
+                // could just skip over all checks where the self-ty is an
+                // inference variable, but I was afraid that there might be an
+                // inference variable created, registered as an obligation, and
+                // then never forced by writeback, and hence by skipping here we'd
+                // be ignoring the fact that we don't KNOW the type works
+                // out. Though even that would probably be harmless, given that
+                // we're only talking about builtin traits, which are known to be
+                // inhabited. But in any case I just threw in this check for
+                // has_errors() to be sure that compilation isn't happening
+                // anyway. In that case, why inundate the user.
+                if !infcx.tcx.sess.has_errors() {
+                    if
+                        infcx.tcx.lang_items.sized_trait()
+                        .map_or(false, |sized_id| sized_id == trait_ref.def_id())
+                    {
+                        infcx.tcx.sess.span_err(
+                            obligation.cause.span,
+                            format!(
+                                "unable to infer enough type information about `{}`; \
+                                 type annotations required",
+                                self_ty.user_string(infcx.tcx)).as_slice());
+                    } else {
+                        infcx.tcx.sess.span_err(
+                            obligation.cause.span,
+                            format!(
+                                "type annotations required: cannot resolve `{}`",
+                                predicate.user_string(infcx.tcx)).as_slice());
+                        note_obligation_cause(infcx, obligation);
+                    }
+                }
+            } else if !infcx.tcx.sess.has_errors() {
+                // Ambiguity. Coherence should have reported an error.
+                infcx.tcx.sess.span_bug(
                     obligation.cause.span,
                     format!(
-                        "unable to infer enough type information about `{}`; type annotations \
-                         required",
+                        "coherence failed to report ambiguity: \
+                         cannot locate the impl of the trait `{}` for \
+                         the type `{}`",
+                        trait_ref.user_string(infcx.tcx),
                         self_ty.user_string(infcx.tcx)).as_slice());
-            } else {
+            }
+        }
+
+        _ => {
+            if !infcx.tcx.sess.has_errors() {
                 infcx.tcx.sess.span_err(
                     obligation.cause.span,
                     format!(
-                        "unable to infer enough type information to \
-                         locate the impl of the trait `{}` for \
-                         the type `{}`; type annotations required",
-                        trait_ref.user_string(infcx.tcx),
-                        self_ty.user_string(infcx.tcx))[]);
+                        "type annotations required: cannot resolve `{}`",
+                        predicate.user_string(infcx.tcx)).as_slice());
                 note_obligation_cause(infcx, obligation);
             }
         }
-    } else if !infcx.tcx.sess.has_errors() {
-         // Ambiguity. Coherence should have reported an error.
-        infcx.tcx.sess.span_bug(
-            obligation.cause.span,
-            format!(
-                "coherence failed to report ambiguity: \
-                 cannot locate the impl of the trait `{}` for \
-                 the type `{}`",
-                trait_ref.user_string(infcx.tcx),
-                self_ty.user_string(infcx.tcx))[]);
     }
 }
 
 fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                    obligation: &PredicateObligation<'tcx>)
 {
-    let trait_ref = match obligation.trait_ref {
-        ty::Predicate::Trait(ref trait_ref) => {
-            infcx.resolve_type_vars_if_possible(&**trait_ref)
-        }
-        _ => {
-            infcx.tcx.sess.span_bug(
-                obligation.cause.span,
-                format!("ambiguity from something other than a trait: {}",
-                        obligation.trait_ref.repr(infcx.tcx)).as_slice());
-        }
-    };
-
     note_obligation_cause_code(infcx,
-                               &trait_ref,
+                               &obligation.predicate,
                                obligation.cause.span,
-                               &obligation.cause.code)
+                               &obligation.cause.code);
 }
 
 fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                        trait_ref: &ty::PolyTraitRef<'tcx>,
+                                        _predicate: &ty::Predicate<'tcx>,
                                         cause_span: Span,
                                         cause_code: &ObligationCauseCode<'tcx>)
 {
     let tcx = infcx.tcx;
-    let trait_name = ty::item_path_str(tcx, trait_ref.def_id());
     match *cause_code {
         ObligationCauseCode::MiscObligation => { }
         ObligationCauseCode::ItemObligation(item_def_id) => {
             let item_name = ty::item_path_str(tcx, item_def_id);
             tcx.sess.span_note(
                 cause_span,
-                format!(
-                    "the trait `{}` must be implemented because it is required by `{}`",
-                    trait_name,
-                    item_name).as_slice());
+                format!("required by `{}`", item_name).as_slice());
         }
         ObligationCauseCode::ObjectCastObligation(object_ty) => {
             tcx.sess.span_note(
                 cause_span,
                 format!(
-                    "the trait `{}` must be implemented for the cast \
-                     to the object type `{}`",
-                    trait_name,
+                    "required for the cast to the object type `{}`",
                     infcx.ty_to_string(object_ty)).as_slice());
         }
         ObligationCauseCode::RepeatVec => {
@@ -323,27 +312,32 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             span_note!(tcx.sess, cause_span,
                        "shared static variables must have a type that implements `Sync`");
         }
-        ObligationCauseCode::BuiltinDerivedObligation(ref root_trait_ref, ref root_cause_code) => {
-            let root_trait_ref =
-                infcx.resolve_type_vars_if_possible(&**root_trait_ref);
+        ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+            let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
             span_note!(tcx.sess, cause_span,
-                       "the type `{}` must implement `{}` because it appears within the type `{}`",
-                       trait_ref.self_ty().user_string(infcx.tcx),
-                       trait_ref.user_string(infcx.tcx),
-                       root_trait_ref.self_ty().user_string(infcx.tcx));
-            note_obligation_cause_code(infcx, &root_trait_ref, cause_span, &**root_cause_code);
+                       "required because it appears within the type `{}`",
+                       parent_trait_ref.0.self_ty().user_string(infcx.tcx));
+            let parent_predicate = parent_trait_ref.as_predicate();
+            note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
         }
-        ObligationCauseCode::ImplDerivedObligation(ref root_trait_ref, ref root_cause_code) => {
-            let root_trait_ref =
-                infcx.resolve_type_vars_if_possible(&**root_trait_ref);
+        ObligationCauseCode::ImplDerivedObligation(ref data) => {
+            let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
             span_note!(tcx.sess, cause_span,
-                       "the type `{}` must implement `{}` due to the requirements \
-                        on the impl of `{}` for the type `{}`",
-                       trait_ref.self_ty().user_string(infcx.tcx),
-                       trait_ref.user_string(infcx.tcx),
-                       root_trait_ref.user_string(infcx.tcx),
-                       root_trait_ref.self_ty().user_string(infcx.tcx));
-            note_obligation_cause_code(infcx, &root_trait_ref, cause_span, &**root_cause_code);
+                       "required because of the requirements on the impl of `{}` for `{}`",
+                       parent_trait_ref.user_string(infcx.tcx),
+                       parent_trait_ref.0.self_ty().user_string(infcx.tcx));
+            let parent_predicate = parent_trait_ref.as_predicate();
+            note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
         }
     }
 }
+
+pub fn suggest_new_overflow_limit(infcx: &InferCtxt, span: Span) {
+    let current_limit = infcx.tcx.sess.recursion_limit.get();
+    let suggested_limit = current_limit * 2;
+    infcx.tcx.sess.span_note(
+        span,
+        format!(
+            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
+            suggested_limit)[]);
+}
diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs
index e9e80ed8c18..2dbb15b215e 100644
--- a/src/librustc/middle/traits/fulfill.rs
+++ b/src/librustc/middle/traits/fulfill.rs
@@ -8,28 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::infer::InferCtxt;
+use middle::infer::{InferCtxt};
 use middle::mem_categorization::Typer;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, RegionEscape, Ty};
 use std::collections::HashSet;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::default::Default;
-use std::rc::Rc;
 use syntax::ast;
 use util::common::ErrorReported;
 use util::ppaux::Repr;
 use util::nodemap::NodeMap;
 
 use super::CodeAmbiguity;
+use super::CodeProjectionError;
 use super::CodeSelectionError;
 use super::FulfillmentError;
-use super::Obligation;
 use super::ObligationCause;
 use super::PredicateObligation;
-use super::Selection;
+use super::project;
 use super::select::SelectionContext;
-use super::poly_trait_ref_for_builtin_bound;
 use super::Unimplemented;
+use super::util::predicate_for_builtin_bound;
 
 /// The fulfillment context is used to drive trait resolution.  It
 /// consists of a list of obligations that must be (eventually)
@@ -101,55 +100,78 @@ impl<'tcx> FulfillmentContext<'tcx> {
         }
     }
 
-    pub fn register_builtin_bound(&mut self,
-                                  tcx: &ty::ctxt<'tcx>,
-                                  ty: Ty<'tcx>,
-                                  builtin_bound: ty::BuiltinBound,
-                                  cause: ObligationCause<'tcx>)
+    /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
+    /// creating a fresh type variable `$0` as well as a projection
+    /// predicate `<SomeType as SomeTrait>::X == $0`. When the
+    /// inference engine runs, it will attempt to find an impl of
+    /// `SomeTrait` or a where clause that lets us unify `$0` with
+    /// something concrete. If this fails, we'll unify `$0` with
+    /// `projection_ty` again.
+    pub fn normalize_projection_type<'a>(&mut self,
+                                         infcx: &InferCtxt<'a,'tcx>,
+                                         param_env: &ty::ParameterEnvironment<'tcx>,
+                                         typer: &ty::UnboxedClosureTyper<'tcx>,
+                                         projection_ty: ty::ProjectionTy<'tcx>,
+                                         cause: ObligationCause<'tcx>)
+                                         -> Ty<'tcx>
     {
-        match poly_trait_ref_for_builtin_bound(tcx, builtin_bound, ty) {
-            Ok(trait_ref) => {
-                self.register_trait_ref(tcx, trait_ref, cause);
-            }
-            Err(ErrorReported) => { }
+        debug!("normalize_associated_type(projection_ty={})",
+               projection_ty.repr(infcx.tcx));
+
+        assert!(!projection_ty.has_escaping_regions());
+
+        // FIXME(#20304) -- cache
+
+        let mut selcx = SelectionContext::new(infcx, param_env, typer);
+        let normalized = project::normalize_projection_type(&mut selcx, projection_ty, cause, 0);
+
+        for obligation in normalized.obligations.into_iter() {
+            self.register_predicate_obligation(infcx, obligation);
         }
+
+        debug!("normalize_associated_type: result={}", normalized.value.repr(infcx.tcx));
+
+        normalized.value
     }
 
-    pub fn register_trait_ref<'a>(&mut self,
-                                  tcx: &ty::ctxt<'tcx>,
-                                  trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
-                                  cause: ObligationCause<'tcx>)
+    pub fn register_builtin_bound<'a>(&mut self,
+                                      infcx: &InferCtxt<'a,'tcx>,
+                                      ty: Ty<'tcx>,
+                                      builtin_bound: ty::BuiltinBound,
+                                      cause: ObligationCause<'tcx>)
     {
-        /*!
-         * A convenience function for registering trait obligations.
-         */
-
-        let trait_obligation = Obligation { cause: cause,
-                                            recursion_depth: 0,
-                                            trait_ref: ty::Predicate::Trait(trait_ref) };
-        self.register_predicate(tcx, trait_obligation)
+        match predicate_for_builtin_bound(infcx.tcx, cause, builtin_bound, 0, ty) {
+            Ok(predicate) => {
+                self.register_predicate_obligation(infcx, predicate);
+            }
+            Err(ErrorReported) => { }
+        }
     }
 
-    pub fn register_region_obligation(&mut self,
-                                      tcx: &ty::ctxt<'tcx>,
-                                      t_a: Ty<'tcx>,
-                                      r_b: ty::Region,
-                                      cause: ObligationCause<'tcx>)
+    pub fn register_region_obligation<'a>(&mut self,
+                                          infcx: &InferCtxt<'a,'tcx>,
+                                          t_a: Ty<'tcx>,
+                                          r_b: ty::Region,
+                                          cause: ObligationCause<'tcx>)
     {
-        register_region_obligation(tcx, t_a, r_b, cause, &mut self.region_obligations);
+        register_region_obligation(infcx.tcx, t_a, r_b, cause, &mut self.region_obligations);
     }
 
-    pub fn register_predicate<'a>(&mut self,
-                                  tcx: &ty::ctxt<'tcx>,
-                                  predicate: PredicateObligation<'tcx>)
+    pub fn register_predicate_obligation<'a>(&mut self,
+                                             infcx: &InferCtxt<'a,'tcx>,
+                                             obligation: PredicateObligation<'tcx>)
     {
-        if !self.duplicate_set.insert(predicate.trait_ref.clone()) {
-            debug!("register_predicate({}) -- already seen, skip", predicate.repr(tcx));
+        // this helps to reduce duplicate errors, as well as making
+        // debug output much nicer to read and so on.
+        let obligation = infcx.resolve_type_vars_if_possible(&obligation);
+
+        if !self.duplicate_set.insert(obligation.predicate.clone()) {
+            debug!("register_predicate({}) -- already seen, skip", obligation.repr(infcx.tcx));
             return;
         }
 
-        debug!("register_predicate({})", predicate.repr(tcx));
-        self.predicates.push(predicate);
+        debug!("register_predicate({})", obligation.repr(infcx.tcx));
+        self.predicates.push(obligation);
     }
 
     pub fn region_obligations(&self,
@@ -165,7 +187,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
     pub fn select_all_or_error<'a>(&mut self,
                                    infcx: &InferCtxt<'a,'tcx>,
                                    param_env: &ty::ParameterEnvironment<'tcx>,
-                                   typer: &Typer<'tcx>)
+                                   typer: &ty::UnboxedClosureTyper<'tcx>)
                                    -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         try!(self.select_where_possible(infcx, param_env, typer));
@@ -191,7 +213,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
     pub fn select_new_obligations<'a>(&mut self,
                                       infcx: &InferCtxt<'a,'tcx>,
                                       param_env: &ty::ParameterEnvironment<'tcx>,
-                                      typer: &Typer<'tcx>)
+                                      typer: &ty::UnboxedClosureTyper<'tcx>)
                                       -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         let mut selcx = SelectionContext::new(infcx, param_env, typer);
@@ -201,7 +223,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
     pub fn select_where_possible<'a>(&mut self,
                                      infcx: &InferCtxt<'a,'tcx>,
                                      param_env: &ty::ParameterEnvironment<'tcx>,
-                                     typer: &Typer<'tcx>)
+                                     typer: &ty::UnboxedClosureTyper<'tcx>)
                                      -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         let mut selcx = SelectionContext::new(infcx, param_env, typer);
@@ -223,7 +245,6 @@ impl<'tcx> FulfillmentContext<'tcx> {
                self.predicates.len(),
                only_new_obligations);
 
-        let tcx = selcx.tcx();
         let mut errors = Vec::new();
 
         loop {
@@ -232,7 +253,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
             debug!("select_where_possible({} obligations) iteration",
                    count);
 
-            let mut selections = Vec::new();
+            let mut new_obligations = Vec::new();
 
             // If we are only attempting obligations we haven't seen yet,
             // then set `skip` to the number of obligations we've already
@@ -253,7 +274,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
                     let processed =
                         if skip == 0 {
                             process_predicate(selcx, predicate,
-                                              &mut selections, &mut errors, region_obligations)
+                                              &mut new_obligations, &mut errors, region_obligations)
                         } else {
                             skip -= 1;
                             false
@@ -271,8 +292,8 @@ impl<'tcx> FulfillmentContext<'tcx> {
 
             // Now go through all the successful ones,
             // registering any nested obligations for the future.
-            for selection in selections.into_iter() {
-                selection.map_move_nested(|p| self.register_predicate(tcx, p));
+            for new_obligation in new_obligations.into_iter() {
+                self.register_predicate_obligation(selcx.infcx(), new_obligation);
             }
         }
 
@@ -289,8 +310,8 @@ impl<'tcx> FulfillmentContext<'tcx> {
 }
 
 fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
-                              predicate: &PredicateObligation<'tcx>,
-                              selections: &mut Vec<Selection<'tcx>>,
+                              obligation: &PredicateObligation<'tcx>,
+                              new_obligations: &mut Vec<PredicateObligation<'tcx>>,
                               errors: &mut Vec<FulfillmentError<'tcx>>,
                               region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
                               -> bool
@@ -303,26 +324,24 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
      */
 
     let tcx = selcx.tcx();
-    match predicate.trait_ref {
-        ty::Predicate::Trait(ref trait_ref) => {
-            let trait_obligation = Obligation { cause: predicate.cause.clone(),
-                                                recursion_depth: predicate.recursion_depth,
-                                                trait_ref: trait_ref.clone() };
+    match obligation.predicate {
+        ty::Predicate::Trait(ref data) => {
+            let trait_obligation = obligation.with(data.clone());
             match selcx.select(&trait_obligation) {
                 Ok(None) => {
                     false
                 }
                 Ok(Some(s)) => {
-                    selections.push(s);
+                    s.map_move_nested(|p| new_obligations.push(p));
                     true
                 }
                 Err(selection_err) => {
                     debug!("predicate: {} error: {}",
-                           predicate.repr(tcx),
+                           obligation.repr(tcx),
                            selection_err.repr(tcx));
                     errors.push(
                         FulfillmentError::new(
-                            predicate.clone(),
+                            obligation.clone(),
                             CodeSelectionError(selection_err)));
                     true
                 }
@@ -330,12 +349,12 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         }
 
         ty::Predicate::Equate(ref binder) => {
-            match selcx.infcx().equality_predicate(predicate.cause.span, binder) {
+            match selcx.infcx().equality_predicate(obligation.cause.span, binder) {
                 Ok(()) => { }
                 Err(_) => {
                     errors.push(
                         FulfillmentError::new(
-                            predicate.clone(),
+                            obligation.clone(),
                             CodeSelectionError(Unimplemented)));
                 }
             }
@@ -343,12 +362,12 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         }
 
         ty::Predicate::RegionOutlives(ref binder) => {
-            match selcx.infcx().region_outlives_predicate(predicate.cause.span, binder) {
+            match selcx.infcx().region_outlives_predicate(obligation.cause.span, binder) {
                 Ok(()) => { }
                 Err(_) => {
                     errors.push(
                         FulfillmentError::new(
-                            predicate.clone(),
+                            obligation.clone(),
                             CodeSelectionError(Unimplemented)));
                 }
             }
@@ -364,16 +383,40 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
             if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 {
                 errors.push(
                     FulfillmentError::new(
-                        predicate.clone(),
+                        obligation.clone(),
                         CodeSelectionError(Unimplemented)));
             } else {
                 let ty::OutlivesPredicate(t_a, r_b) = binder.0;
                 register_region_obligation(tcx, t_a, r_b,
-                                           predicate.cause.clone(),
+                                           obligation.cause.clone(),
                                            region_obligations);
             }
             true
         }
+
+        ty::Predicate::Projection(ref data) => {
+            let project_obligation = obligation.with(data.clone());
+            let result = project::poly_project_and_unify_type(selcx, &project_obligation);
+            debug!("poly_project_and_unify_type({}) = {}",
+                   project_obligation.repr(tcx),
+                   result.repr(tcx));
+            match result {
+                Ok(Some(obligations)) => {
+                    new_obligations.extend(obligations.into_iter());
+                    true
+                }
+                Ok(None) => {
+                    false
+                }
+                Err(err) => {
+                    errors.push(
+                        FulfillmentError::new(
+                            obligation.clone(),
+                            CodeProjectionError(err)));
+                    true
+                }
+            }
+        }
     }
 }
 
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index 6597730846d..b10dfa5b718 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -18,27 +18,31 @@ pub use self::ObligationCauseCode::*;
 use middle::subst;
 use middle::ty::{mod, Ty};
 use middle::infer::InferCtxt;
-use std::rc::Rc;
 use std::slice::Iter;
+use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
+use util::ppaux::Repr;
 
 pub use self::error_reporting::report_fulfillment_errors;
 pub use self::fulfill::{FulfillmentContext, RegionObligation};
+pub use self::project::MismatchedProjectionTypes;
+pub use self::project::normalize;
+pub use self::project::Normalized;
 pub use self::select::SelectionContext;
 pub use self::select::SelectionCache;
 pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
 pub use self::select::{MethodMatchedData}; // intentionally don't export variants
 pub use self::util::elaborate_predicates;
+pub use self::util::trait_ref_for_builtin_bound;
 pub use self::util::supertraits;
 pub use self::util::Supertraits;
-pub use self::util::search_trait_and_supertraits_from_bound;
 pub use self::util::transitive_bounds;
-pub use self::util::poly_trait_ref_for_builtin_bound;
 
 mod coherence;
 mod error_reporting;
 mod fulfill;
+mod project;
 mod select;
 mod util;
 
@@ -52,11 +56,11 @@ mod util;
 pub struct Obligation<'tcx, T> {
     pub cause: ObligationCause<'tcx>,
     pub recursion_depth: uint,
-    pub trait_ref: T,
+    pub predicate: T,
 }
 
 pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
-pub type TraitObligation<'tcx> = Obligation<'tcx, Rc<ty::PolyTraitRef<'tcx>>>;
+pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
 
 /// Why did we incur this obligation? Used for error reporting.
 #[deriving(Clone)]
@@ -106,9 +110,21 @@ pub enum ObligationCauseCode<'tcx> {
     // static items must have `Sync` type
     SharedStatic,
 
-    BuiltinDerivedObligation(Rc<ty::PolyTraitRef<'tcx>>, Rc<ObligationCauseCode<'tcx>>),
+    BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
 
-    ImplDerivedObligation(Rc<ty::PolyTraitRef<'tcx>>, Rc<ObligationCauseCode<'tcx>>),
+    ImplDerivedObligation(DerivedObligationCause<'tcx>),
+}
+
+#[deriving(Clone)]
+pub struct DerivedObligationCause<'tcx> {
+    /// The trait reference of the parent obligation that led to the
+    /// current obligation. Note that only trait obligations lead to
+    /// derived obligations, so we just store the trait reference here
+    /// directly.
+    parent_trait_ref: ty::PolyTraitRef<'tcx>,
+
+    /// The parent trait had this cause
+    parent_code: Rc<ObligationCauseCode<'tcx>>
 }
 
 pub type Obligations<'tcx, O> = subst::VecPerParamSpace<Obligation<'tcx, O>>;
@@ -121,8 +137,8 @@ pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
 pub enum SelectionError<'tcx> {
     Unimplemented,
     Overflow,
-    OutputTypeParameterMismatch(Rc<ty::PolyTraitRef<'tcx>>,
-                                Rc<ty::PolyTraitRef<'tcx>>,
+    OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
+                                ty::PolyTraitRef<'tcx>,
                                 ty::type_err<'tcx>),
 }
 
@@ -134,6 +150,7 @@ pub struct FulfillmentError<'tcx> {
 #[deriving(Clone)]
 pub enum FulfillmentErrorCode<'tcx> {
     CodeSelectionError(SelectionError<'tcx>),
+    CodeProjectionError(MismatchedProjectionTypes<'tcx>),
     CodeAmbiguity,
 }
 
@@ -174,10 +191,10 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
 ///
 ///    // Case B: Vtable must be provided by caller. This applies when
 ///    // type is a type parameter.
-///    param.clone();    // VtableParam(Oblig_1)
+///    param.clone();    // VtableParam
 ///
 ///    // Case C: A mix of cases A and B.
-///    mixed.clone();    // Vtable(Impl_1, [VtableParam(Oblig_1)])
+///    mixed.clone();    // Vtable(Impl_1, [VtableParam])
 /// }
 /// ```
 ///
@@ -191,7 +208,7 @@ pub enum Vtable<'tcx, N> {
 
     /// Successful resolution to an obligation provided by the caller
     /// for some type parameter.
-    VtableParam(VtableParamData<'tcx>),
+    VtableParam,
 
     /// Successful resolution for a builtin trait.
     VtableBuiltin(VtableBuiltinData<N>),
@@ -228,15 +245,6 @@ pub struct VtableBuiltinData<N> {
     pub nested: subst::VecPerParamSpace<N>
 }
 
-/// A vtable provided as a parameter by the caller. For example, in a
-/// function like `fn foo<T:Eq>(...)`, if the `eq()` method is invoked
-/// on an instance of `T`, the vtable would be of type `VtableParam`.
-#[deriving(PartialEq,Eq,Clone)]
-pub struct VtableParamData<'tcx> {
-    // In the above example, this would `Eq`
-    pub bound: Rc<ty::PolyTraitRef<'tcx>>,
-}
-
 /// True if neither the trait nor self type is local. Note that `impl_def_id` must refer to an impl
 /// of a trait, not an inherent impl.
 pub fn is_orphan_impl(tcx: &ty::ctxt,
@@ -265,6 +273,43 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
     util::predicates_for_generics(tcx, cause, 0, generic_bounds)
 }
 
+/// Determines whether the type `ty` is known to meet `bound` and
+/// returns true if so. Returns false if `ty` either does not meet
+/// `bound` or is not known to meet bound (note that this is
+/// conservative towards *no impl*, which is the opposite of the
+/// `evaluate` methods).
+pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+                                                 param_env: &ty::ParameterEnvironment<'tcx>,
+                                                 ty: Ty<'tcx>,
+                                                 bound: ty::BuiltinBound)
+                                                 -> bool
+{
+    debug!("type_known_to_meet_builtin_bound(ty={}, bound={})",
+           ty.repr(infcx.tcx),
+           bound);
+
+    let mut fulfill_cx = FulfillmentContext::new();
+
+    // We can use dummy values here because we won't report any errors
+    // that result nor will we pay any mind to region obligations that arise
+    // (there shouldn't really be any anyhow).
+    let cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID);
+
+    fulfill_cx.register_builtin_bound(infcx, ty, bound, cause);
+
+    // Note: we only assume something is `Copy` if we can
+    // *definitively* show that it implements `Copy`. Otherwise,
+    // assume it is move; linear is always ok.
+    let result = fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx).is_ok();
+
+    debug!("type_known_to_meet_builtin_bound: ty={} bound={} result={}",
+           ty.repr(infcx.tcx),
+           bound,
+           result);
+
+    result
+}
+
 impl<'tcx,O> Obligation<'tcx,O> {
     pub fn new(cause: ObligationCause<'tcx>,
                trait_ref: O)
@@ -272,7 +317,17 @@ impl<'tcx,O> Obligation<'tcx,O> {
     {
         Obligation { cause: cause,
                      recursion_depth: 0,
-                     trait_ref: trait_ref }
+                     predicate: trait_ref }
+    }
+
+    fn with_depth(cause: ObligationCause<'tcx>,
+                  recursion_depth: uint,
+                  trait_ref: O)
+                  -> Obligation<'tcx, O>
+    {
+        Obligation { cause: cause,
+                     recursion_depth: recursion_depth,
+                     predicate: trait_ref }
     }
 
     pub fn misc(span: Span, body_id: ast::NodeId, trait_ref: O) -> Obligation<'tcx, O> {
@@ -282,13 +337,7 @@ impl<'tcx,O> Obligation<'tcx,O> {
     pub fn with<P>(&self, value: P) -> Obligation<'tcx,P> {
         Obligation { cause: self.cause.clone(),
                      recursion_depth: self.recursion_depth,
-                     trait_ref: value }
-    }
-}
-
-impl<'tcx> TraitObligation<'tcx> {
-    pub fn self_ty(&self) -> Ty<'tcx> {
-        self.trait_ref.self_ty()
+                     predicate: value }
     }
 }
 
@@ -315,7 +364,7 @@ impl<'tcx, N> Vtable<'tcx, N> {
             VtableImpl(ref i) => i.iter_nested(),
             VtableFnPointer(..) => (&[]).iter(),
             VtableUnboxedClosure(..) => (&[]).iter(),
-            VtableParam(_) => (&[]).iter(),
+            VtableParam => (&[]).iter(),
             VtableBuiltin(ref i) => i.iter_nested(),
         }
     }
@@ -325,7 +374,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(ref p) => VtableParam((*p).clone()),
+            VtableParam => VtableParam,
             VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
         }
     }
@@ -337,7 +386,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(p) => VtableParam(p),
+            VtableParam => VtableParam,
             VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
         }
     }
@@ -403,6 +452,13 @@ impl<'tcx> FulfillmentError<'tcx> {
             CodeAmbiguity => false,
             CodeSelectionError(Overflow) => true,
             CodeSelectionError(_) => false,
+            CodeProjectionError(_) => false,
         }
     }
 }
+
+impl<'tcx> TraitObligation<'tcx> {
+    fn self_ty(&self) -> Ty<'tcx> {
+        self.predicate.0.self_ty()
+    }
+}
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
new file mode 100644
index 00000000000..c84f31bf6c3
--- /dev/null
+++ b/src/librustc/middle/traits/project.rs
@@ -0,0 +1,674 @@
+// 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.
+
+//! Code for projecting associated types out of trait references.
+
+use super::elaborate_predicates;
+use super::Obligation;
+use super::ObligationCause;
+use super::Overflow;
+use super::PredicateObligation;
+use super::SelectionContext;
+use super::SelectionError;
+use super::VtableImplData;
+
+use middle::infer;
+use middle::subst::Subst;
+use middle::ty::{mod, AsPredicate, RegionEscape, HasProjectionTypes, ToPolyTraitRef, Ty};
+use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
+use util::ppaux::Repr;
+
+pub type PolyProjectionObligation<'tcx> =
+    Obligation<'tcx, ty::PolyProjectionPredicate<'tcx>>;
+
+pub type ProjectionObligation<'tcx> =
+    Obligation<'tcx, ty::ProjectionPredicate<'tcx>>;
+
+pub type ProjectionTyObligation<'tcx> =
+    Obligation<'tcx, ty::ProjectionTy<'tcx>>;
+
+/// When attempting to resolve `<T as TraitRef>::Name` ...
+pub enum ProjectionTyError<'tcx> {
+    /// ...we found multiple sources of information and couldn't resolve the ambiguity.
+    TooManyCandidates,
+
+    /// ...an error occurred matching `T : TraitRef`
+    TraitSelectionError(SelectionError<'tcx>),
+}
+
+#[deriving(Clone)]
+pub struct MismatchedProjectionTypes<'tcx> {
+    pub err: ty::type_err<'tcx>
+}
+
+enum ProjectionTyCandidate<'tcx> {
+    ParamEnv(ty::PolyProjectionPredicate<'tcx>),
+    Impl(VtableImplData<'tcx, PredicateObligation<'tcx>>),
+}
+
+struct ProjectionTyCandidateSet<'tcx> {
+    vec: Vec<ProjectionTyCandidate<'tcx>>,
+    ambiguous: bool
+}
+
+pub fn poly_project_and_unify_type<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &PolyProjectionObligation<'tcx>)
+    -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
+{
+    debug!("poly_project(obligation={})",
+           obligation.repr(selcx.tcx()));
+
+    let infcx = selcx.infcx();
+    let result = infcx.try(|snapshot| {
+        let (skol_predicate, skol_map) =
+            infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot);
+
+        let skol_obligation = obligation.with(skol_predicate);
+        match project_and_unify_type(selcx, &skol_obligation) {
+            Ok(Some(obligations)) => {
+                match infcx.leak_check(&skol_map, snapshot) {
+                    Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, &obligations)),
+                    Err(e) => Err(Some(MismatchedProjectionTypes { err: e })),
+                }
+            }
+            Ok(None) => {
+                // Signal ambiguity using Err just so that infcx.try()
+                // rolls back the snapshot. We adapt below.
+                Err(None)
+            }
+            Err(e) => {
+                Err(Some(e))
+            }
+        }
+    });
+
+    // Above, we use Err(None) to signal ambiguity so that the
+    // snapshot will be rolled back. But here, we want to translate to
+    // Ok(None). Kind of weird.
+    match result {
+        Ok(obligations) => Ok(Some(obligations)),
+        Err(None) => Ok(None),
+        Err(Some(e)) => Err(e),
+    }
+}
+
+/// Compute result of projecting an associated type and unify it with
+/// `obligation.predicate.ty` (if we can).
+fn project_and_unify_type<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionObligation<'tcx>)
+    -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
+{
+    debug!("project_and_unify(obligation={})",
+           obligation.repr(selcx.tcx()));
+
+    let Normalized { value: normalized_ty, obligations } =
+        match opt_normalize_projection_type(selcx,
+                                            obligation.predicate.projection_ty.clone(),
+                                            obligation.cause.clone(),
+                                            obligation.recursion_depth) {
+            Some(n) => n,
+            None => { return Ok(None); }
+        };
+
+    debug!("project_and_unify_type: normalized_ty={} obligations={}",
+           normalized_ty.repr(selcx.tcx()),
+           obligations.repr(selcx.tcx()));
+
+    let infcx = selcx.infcx();
+    let origin = infer::RelateOutputImplTypes(obligation.cause.span);
+    match infer::mk_eqty(infcx, true, origin, normalized_ty, obligation.predicate.ty) {
+        Ok(()) => Ok(Some(obligations)),
+        Err(err) => Err(MismatchedProjectionTypes { err: err }),
+    }
+}
+
+pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
+                               cause: ObligationCause<'tcx>,
+                               value: &T)
+                               -> Normalized<'tcx, T>
+    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+{
+    normalize_with_depth(selcx, cause, 0, value)
+}
+
+pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
+                                          cause: ObligationCause<'tcx>,
+                                          depth: uint,
+                                          value: &T)
+                                          -> Normalized<'tcx, T>
+    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+{
+    let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
+    let result = normalizer.fold(value);
+    Normalized {
+        value: result,
+        obligations: normalizer.obligations,
+    }
+}
+
+struct AssociatedTypeNormalizer<'a,'b:'a,'tcx:'b> {
+    selcx: &'a mut SelectionContext<'b,'tcx>,
+    cause: ObligationCause<'tcx>,
+    obligations: Vec<PredicateObligation<'tcx>>,
+    depth: uint,
+}
+
+impl<'a,'b,'tcx> AssociatedTypeNormalizer<'a,'b,'tcx> {
+    fn new(selcx: &'a mut SelectionContext<'b,'tcx>,
+           cause: ObligationCause<'tcx>,
+           depth: uint)
+           -> AssociatedTypeNormalizer<'a,'b,'tcx>
+    {
+        AssociatedTypeNormalizer {
+            selcx: selcx,
+            cause: cause,
+            obligations: vec!(),
+            depth: depth,
+        }
+    }
+
+    fn fold<T:TypeFoldable<'tcx> + HasProjectionTypes + Clone>(&mut self, value: &T) -> T {
+        let value = self.selcx.infcx().resolve_type_vars_if_possible(value);
+
+        if !value.has_projection_types() {
+            value.clone()
+        } else {
+            value.fold_with(self)
+        }
+    }
+}
+
+impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> {
+    fn tcx(&self) -> &ty::ctxt<'tcx> {
+        self.selcx.tcx()
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        // We don't want to normalize associated types that occur inside of region
+        // binders, because they may contain bound regions, and we can't cope with that.
+        //
+        // Example:
+        //
+        //     for<'a> fn(<T as Foo<&'a>>::A)
+        //
+        // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
+        // normalize it when we instantiate those bound regions (which
+        // should occur eventually).
+
+        match ty.sty {
+            ty::ty_projection(ref data) if !data.has_escaping_regions() => { // (*)
+
+                // (*) This is kind of hacky -- we need to be able to
+                // handle normalization within binders because
+                // otherwise we wind up a need to normalize when doing
+                // trait matching (since you can have a trait
+                // obligation like `for<'a> T::B : Fn(&'a int)`), but
+                // we can't normalize with bound regions in scope. So
+                // far now we just ignore binders but only normalize
+                // if all bound regions are gone (and then we still
+                // have to renormalize whenever we instantiate a
+                // binder). It would be better to normalize in a
+                // binding-aware fashion.
+
+                let Normalized { value: ty, obligations } =
+                    normalize_projection_type(self.selcx,
+                                              data.clone(),
+                                              self.cause.clone(),
+                                              self.depth);
+                self.obligations.extend(obligations.into_iter());
+                ty
+            }
+            _ => {
+                ty_fold::super_fold_ty(self, ty)
+            }
+        }
+    }
+}
+
+pub struct Normalized<'tcx,T> {
+    pub value: T,
+    pub obligations: Vec<PredicateObligation<'tcx>>,
+}
+
+pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>;
+
+pub fn normalize_projection_type<'a,'b,'tcx>(
+    selcx: &'a mut SelectionContext<'b,'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: uint)
+    -> NormalizedTy<'tcx>
+{
+    opt_normalize_projection_type(selcx, projection_ty.clone(), cause.clone(), depth)
+        .unwrap_or_else(move || {
+            // if we bottom out in ambiguity, create a type variable
+            // and a deferred predicate to resolve this when more type
+            // information is available.
+
+            let ty_var = selcx.infcx().next_ty_var();
+            let projection = ty::Binder(ty::ProjectionPredicate {
+                projection_ty: projection_ty,
+                ty: ty_var
+            });
+            let obligation = Obligation::with_depth(cause, depth+1, projection.as_predicate());
+            Normalized {
+                value: ty_var,
+                obligations: vec!(obligation)
+            }
+        })
+}
+
+fn opt_normalize_projection_type<'a,'b,'tcx>(
+    selcx: &'a mut SelectionContext<'b,'tcx>,
+    projection_ty: ty::ProjectionTy<'tcx>,
+    cause: ObligationCause<'tcx>,
+    depth: uint)
+    -> Option<NormalizedTy<'tcx>>
+{
+    debug!("normalize_projection_type(\
+           projection_ty={}, \
+           depth={})",
+           projection_ty.repr(selcx.tcx()),
+           depth);
+
+    let obligation = Obligation::with_depth(cause.clone(), depth, projection_ty.clone());
+    match project_type(selcx, &obligation) {
+        Ok(ProjectedTy::Progress(projected_ty, mut obligations)) => {
+            // if projection succeeded, then what we get out of this
+            // is also non-normalized (consider: it was derived from
+            // an impl, where-clause etc) and hence we must
+            // re-normalize it
+
+            debug!("normalize_projection_type: projected_ty={} depth={} obligations={}",
+                   projected_ty.repr(selcx.tcx()),
+                   depth,
+                   obligations.repr(selcx.tcx()));
+
+            if ty::type_has_projection(projected_ty) {
+                let tcx = selcx.tcx();
+                let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
+                let normalized_ty = normalizer.fold(&projected_ty);
+
+                debug!("normalize_projection_type: normalized_ty={} depth={}",
+                       normalized_ty.repr(tcx),
+                       depth);
+
+                obligations.extend(normalizer.obligations.into_iter());
+                Some(Normalized {
+                    value: normalized_ty,
+                    obligations: obligations,
+                })
+            } else {
+                Some(Normalized {
+                    value: projected_ty,
+                    obligations: obligations,
+                })
+            }
+        }
+        Ok(ProjectedTy::NoProgress(projected_ty)) => {
+            Some(Normalized {
+                value: projected_ty,
+                obligations: vec!()
+            })
+        }
+        Err(ProjectionTyError::TooManyCandidates) => {
+            None
+        }
+        Err(ProjectionTyError::TraitSelectionError(_)) => {
+            // if we got an error processing the `T as Trait` part,
+            // just return `ty::err` but add the obligation `T :
+            // Trait`, which when processed will cause the error to be
+            // reported later
+
+            Some(normalize_to_error(selcx, projection_ty, cause, depth))
+        }
+    }
+}
+
+/// in various error cases, we just set ty_err and return an obligation
+/// that, when fulfiled, will lead to an error
+fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
+                               projection_ty: ty::ProjectionTy<'tcx>,
+                               cause: ObligationCause<'tcx>,
+                               depth: uint)
+                               -> NormalizedTy<'tcx>
+{
+    let trait_ref = projection_ty.trait_ref.to_poly_trait_ref();
+    let trait_obligation = Obligation { cause: cause,
+                                        recursion_depth: depth,
+                                        predicate: trait_ref.as_predicate() };
+    Normalized {
+        value: selcx.tcx().types.err,
+        obligations: vec!(trait_obligation)
+    }
+}
+
+enum ProjectedTy<'tcx> {
+    Progress(Ty<'tcx>, Vec<PredicateObligation<'tcx>>),
+    NoProgress(Ty<'tcx>),
+}
+
+/// Compute the result of a projection type (if we can).
+fn project_type<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>)
+    -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>>
+{
+    debug!("project(obligation={})",
+           obligation.repr(selcx.tcx()));
+
+    let recursion_limit = selcx.tcx().sess.recursion_limit.get();
+    if obligation.recursion_depth >= recursion_limit {
+        debug!("project: overflow!");
+        return Err(ProjectionTyError::TraitSelectionError(Overflow));
+    }
+
+    let mut candidates = ProjectionTyCandidateSet {
+        vec: Vec::new(),
+        ambiguous: false,
+    };
+
+    assemble_candidates_from_object_type(selcx,
+                                         obligation,
+                                         &mut candidates);
+
+    if candidates.vec.is_empty() {
+        assemble_candidates_from_param_env(selcx,
+                                           obligation,
+                                           &mut candidates);
+
+        if let Err(e) = assemble_candidates_from_impls(selcx,
+                                                       obligation,
+                                                       &mut candidates) {
+            return Err(ProjectionTyError::TraitSelectionError(e));
+        }
+    }
+
+    debug!("{} candidates, ambiguous={}",
+           candidates.vec.len(),
+           candidates.ambiguous);
+
+    // We probably need some winnowing logic similar to select here.
+
+    if candidates.ambiguous || candidates.vec.len() > 1 {
+        return Err(ProjectionTyError::TooManyCandidates);
+    }
+
+    match candidates.vec.pop() {
+        Some(candidate) => {
+            let (ty, obligations) = confirm_candidate(selcx, obligation, candidate);
+            Ok(ProjectedTy::Progress(ty, obligations))
+        }
+        None => {
+            Ok(ProjectedTy::NoProgress(ty::mk_projection(selcx.tcx(),
+                                                         obligation.predicate.trait_ref.clone(),
+                                                         obligation.predicate.item_name)))
+        }
+    }
+}
+
+/// The first thing we have to do is scan through the parameter
+/// environment to see whether there are any projection predicates
+/// there that can answer this question.
+fn assemble_candidates_from_param_env<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation:  &ProjectionTyObligation<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
+{
+    let env_predicates = selcx.param_env().caller_bounds.predicates.clone();
+    let env_predicates = env_predicates.iter().cloned().collect();
+    assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates);
+}
+
+fn assemble_candidates_from_predicates<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation:  &ProjectionTyObligation<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
+    env_predicates: Vec<ty::Predicate<'tcx>>)
+{
+    debug!("assemble_candidates_from_predicates(obligation={}, env_predicates={})",
+           obligation.repr(selcx.tcx()),
+           env_predicates.repr(selcx.tcx()));
+    let infcx = selcx.infcx();
+    for predicate in elaborate_predicates(selcx.tcx(), env_predicates) {
+        match predicate {
+            ty::Predicate::Projection(ref data) => {
+                let is_match = infcx.probe(|_| {
+                    let origin = infer::Misc(obligation.cause.span);
+                    let obligation_poly_trait_ref =
+                        obligation.predicate.trait_ref.to_poly_trait_ref();
+                    let data_poly_trait_ref =
+                        data.to_poly_trait_ref();
+                    infcx.sub_poly_trait_refs(false,
+                                              origin,
+                                              obligation_poly_trait_ref,
+                                              data_poly_trait_ref).is_ok()
+                });
+
+                if is_match {
+                    candidate_set.vec.push(
+                        ProjectionTyCandidate::ParamEnv(data.clone()));
+                }
+            }
+            _ => { }
+        }
+    }
+}
+
+fn assemble_candidates_from_object_type<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation:  &ProjectionTyObligation<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
+{
+    let infcx = selcx.infcx();
+    let trait_ref = infcx.resolve_type_vars_if_possible(&obligation.predicate.trait_ref);
+    debug!("assemble_candidates_from_object_type(trait_ref={})",
+           trait_ref.repr(infcx.tcx));
+    let self_ty = trait_ref.self_ty();
+    let data = match self_ty.sty {
+        ty::ty_trait(ref data) => data,
+        _ => { return; }
+    };
+    let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), self_ty);
+    let env_predicates = projection_bounds.iter()
+                                          .map(|p| p.as_predicate())
+                                          .collect();
+    assemble_candidates_from_predicates(selcx, obligation, candidate_set, env_predicates)
+}
+
+fn assemble_candidates_from_impls<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
+    -> Result<(), SelectionError<'tcx>>
+{
+    // If we are resolving `<T as TraitRef<...>>::Item == Type`,
+    // start out by selecting the predicate `T as TraitRef<...>`:
+    let trait_ref =
+        obligation.predicate.trait_ref.to_poly_trait_ref();
+    let trait_obligation =
+        obligation.with(trait_ref.to_poly_trait_predicate());
+    let vtable = match selcx.select(&trait_obligation) {
+        Ok(Some(vtable)) => vtable,
+        Ok(None) => {
+            candidate_set.ambiguous = true;
+            return Ok(());
+        }
+        Err(e) => {
+            debug!("assemble_candidates_from_impls: selection error {}",
+                   e.repr(selcx.tcx()));
+            return Err(e);
+        }
+    };
+
+    match vtable {
+        super::VtableImpl(data) => {
+            candidate_set.vec.push(
+                ProjectionTyCandidate::Impl(data));
+        }
+        super::VtableParam(..) => {
+            // This case tell us nothing about the value of an
+            // associated type. Consider:
+            //
+            // ```
+            // trait SomeTrait { type Foo; }
+            // fn foo<T:SomeTrait>(...) { }
+            // ```
+            //
+            // If the user writes `<T as SomeTrait>::Foo`, then the `T
+            // : SomeTrait` binding does not help us decide what the
+            // type `Foo` is (at least, not more specifically than
+            // what we already knew).
+            //
+            // But wait, you say! What about an example like this:
+            //
+            // ```
+            // fn bar<T:SomeTrait<Foo=uint>>(...) { ... }
+            // ```
+            //
+            // Doesn't the `T : Sometrait<Foo=uint>` predicate help
+            // resolve `T::Foo`? And of course it does, but in fact
+            // that single predicate is desugared into two predicates
+            // in the compiler: a trait predicate (`T : SomeTrait`) and a
+            // projection. And the projection where clause is handled
+            // in `assemble_candidates_from_param_env`.
+        }
+        super::VtableBuiltin(..) |
+        super::VtableUnboxedClosure(..) |
+        super::VtableFnPointer(..) => {
+            // These traits have no associated types.
+            selcx.tcx().sess.span_bug(
+                obligation.cause.span,
+                format!("Cannot project an associated type from `{}`",
+                        vtable.repr(selcx.tcx())).as_slice());
+        }
+    }
+
+    Ok(())
+}
+
+fn confirm_candidate<'cx,'tcx>(
+    selcx: &mut SelectionContext<'cx,'tcx>,
+    obligation: &ProjectionTyObligation<'tcx>,
+    candidate: ProjectionTyCandidate<'tcx>)
+    -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
+{
+    let infcx = selcx.infcx();
+
+    debug!("confirm_candidate(candidate={}, obligation={})",
+           candidate.repr(infcx.tcx),
+           obligation.repr(infcx.tcx));
+
+    match candidate {
+        ProjectionTyCandidate::ParamEnv(poly_projection) => {
+            let projection =
+                infcx.replace_late_bound_regions_with_fresh_var(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    &poly_projection).0;
+
+            assert_eq!(projection.projection_ty.item_name,
+                       obligation.predicate.item_name);
+
+            let origin = infer::RelateOutputImplTypes(obligation.cause.span);
+            match infcx.sub_trait_refs(false,
+                                       origin,
+                                       obligation.predicate.trait_ref.clone(),
+                                       projection.projection_ty.trait_ref.clone()) {
+                Ok(()) => { }
+                Err(e) => {
+                    selcx.tcx().sess.span_bug(
+                        obligation.cause.span,
+                        format!("Failed to unify `{}` and `{}` in projection: {}",
+                                obligation.repr(selcx.tcx()),
+                                projection.repr(selcx.tcx()),
+                                ty::type_err_to_str(selcx.tcx(), &e)).as_slice());
+                }
+            }
+
+            (projection.ty, vec!())
+        }
+
+        ProjectionTyCandidate::Impl(impl_vtable) => {
+            // there don't seem to be nicer accessors to these:
+            let impl_items_map = selcx.tcx().impl_items.borrow();
+            let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
+
+            let impl_items = &impl_items_map[impl_vtable.impl_def_id];
+            let mut impl_ty = None;
+            for impl_item in impl_items.iter() {
+                let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] {
+                    ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
+                    ty::MethodTraitItem(..) => { continue; }
+                };
+
+                if assoc_type.name != obligation.predicate.item_name {
+                    continue;
+                }
+
+                let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id);
+                impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs));
+                break;
+            }
+
+            match impl_ty {
+                Some(ty) => (ty, impl_vtable.nested.to_vec()),
+                None => {
+                    selcx.tcx().sess.span_bug(
+                        obligation.cause.span,
+                        format!("impl `{}` did not contain projection for `{}`",
+                                impl_vtable.repr(selcx.tcx()),
+                                obligation.repr(selcx.tcx())).as_slice());
+                }
+            }
+        }
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ProjectionTyError<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        match *self {
+            ProjectionTyError::TooManyCandidates =>
+                format!("NoCandidate"),
+            ProjectionTyError::TraitSelectionError(ref e) =>
+                format!("TraitSelectionError({})", e.repr(tcx)),
+        }
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        match *self {
+            ProjectionTyCandidate::ParamEnv(ref data) =>
+                format!("ParamEnv({})", data.repr(tcx)),
+            ProjectionTyCandidate::Impl(ref data) =>
+                format!("Impl({})", data.repr(tcx))
+        }
+    }
+}
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Normalized<'tcx, T> {
+        Normalized {
+            value: self.value.fold_with(folder),
+            obligations: self.obligations.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Normalized<'tcx, T> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        format!("Normalized({},{})",
+                self.value.repr(tcx),
+                self.obligations.repr(tcx))
+    }
+}
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index b10b1ce35c4..f9dced088f8 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -13,23 +13,25 @@
 
 pub use self::MethodMatchResult::*;
 pub use self::MethodMatchedData::*;
-use self::Candidate::*;
+use self::SelectionCandidate::*;
 use self::BuiltinBoundConditions::*;
 use self::EvaluationResult::*;
 
+use super::{DerivedObligationCause};
+use super::{project};
 use super::{PredicateObligation, Obligation, TraitObligation, ObligationCause};
 use super::{ObligationCauseCode, BuiltinDerivedObligation};
 use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
 use super::{Selection};
 use super::{SelectionResult};
 use super::{VtableBuiltin, VtableImpl, VtableParam, VtableUnboxedClosure, VtableFnPointer};
-use super::{VtableImplData, VtableParamData, VtableBuiltinData};
+use super::{VtableImplData, VtableBuiltinData};
 use super::{util};
 
 use middle::fast_reject;
 use middle::mem_categorization::Typer;
-use middle::subst::{Subst, Substs, VecPerParamSpace};
-use middle::ty::{mod, AsPredicate, RegionEscape, Ty};
+use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace};
+use middle::ty::{mod, AsPredicate, RegionEscape, ToPolyTraitRef, Ty};
 use middle::infer;
 use middle::infer::{InferCtxt, TypeFreshener};
 use middle::ty_fold::TypeFoldable;
@@ -43,7 +45,7 @@ use util::ppaux::Repr;
 pub struct SelectionContext<'cx, 'tcx:'cx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     param_env: &'cx ty::ParameterEnvironment<'tcx>,
-    typer: &'cx (Typer<'tcx>+'cx),
+    closure_typer: &'cx (ty::UnboxedClosureTyper<'tcx>+'cx),
 
     /// Freshener used specifically for skolemizing entries on the
     /// obligation stack. This ensures that all entries on the stack
@@ -75,15 +77,15 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
 
     /// Trait ref from `obligation` but skolemized with the
     /// selection-context's freshener. Used to check for recursion.
-    fresh_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+    fresh_trait_ref: ty::PolyTraitRef<'tcx>,
 
     previous: Option<&'prev TraitObligationStack<'prev, 'tcx>>
 }
 
 #[deriving(Clone)]
 pub struct SelectionCache<'tcx> {
-    hashmap: RefCell<HashMap<Rc<ty::PolyTraitRef<'tcx>>,
-                             SelectionResult<'tcx, Candidate<'tcx>>>>,
+    hashmap: RefCell<HashMap<Rc<ty::TraitRef<'tcx>>,
+                             SelectionResult<'tcx, SelectionCandidate<'tcx>>>>,
 }
 
 pub enum MethodMatchResult {
@@ -128,11 +130,15 @@ pub enum MethodMatchedData {
 /// clauses can give additional information (like, the types of output
 /// parameters) that would have to be inferred from the impl.
 #[deriving(PartialEq,Eq,Show,Clone)]
-enum Candidate<'tcx> {
+enum SelectionCandidate<'tcx> {
     BuiltinCandidate(ty::BuiltinBound),
-    ParamCandidate(VtableParamData<'tcx>),
+    ParamCandidate(ty::PolyTraitRef<'tcx>),
     ImplCandidate(ast::DefId),
 
+    /// This is a trait matching with a projected type as `Self`, and
+    /// we found an applicable bound in the trait definition.
+    ProjectionCandidate,
+
     /// Implementation of a `Fn`-family trait by one of the
     /// anonymous types generated for a `||` expression.
     UnboxedClosureCandidate(/* closure */ ast::DefId, Substs<'tcx>),
@@ -144,9 +150,16 @@ enum Candidate<'tcx> {
     ErrorCandidate,
 }
 
-struct CandidateSet<'tcx> {
-    vec: Vec<Candidate<'tcx>>,
-    ambiguous: bool
+struct SelectionCandidateSet<'tcx> {
+    // a list of candidates that definitely apply to the current
+    // obligation (meaning: types unify).
+    vec: Vec<SelectionCandidate<'tcx>>,
+
+    // if this is true, then there were candidates that might or might
+    // not have applied, but we couldn't tell. This occurs when some
+    // of the input types are type variables, in which case there are
+    // various "builtin" rules that might or might not trigger.
+    ambiguous: bool,
 }
 
 enum BuiltinBoundConditions<'tcx> {
@@ -165,12 +178,12 @@ enum EvaluationResult<'tcx> {
 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>,
                param_env: &'cx ty::ParameterEnvironment<'tcx>,
-               typer: &'cx Typer<'tcx>)
+               closure_typer: &'cx ty::UnboxedClosureTyper<'tcx>)
                -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx: infcx,
             param_env: param_env,
-            typer: typer,
+            closure_typer: closure_typer,
             freshener: infcx.freshener(),
             intercrate: false,
         }
@@ -178,12 +191,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>,
                       param_env: &'cx ty::ParameterEnvironment<'tcx>,
-                      typer: &'cx Typer<'tcx>)
+                      closure_typer: &'cx ty::UnboxedClosureTyper<'tcx>)
                       -> SelectionContext<'cx, 'tcx> {
         SelectionContext {
             infcx: infcx,
             param_env: param_env,
-            typer: typer,
+            closure_typer: closure_typer,
             freshener: infcx.freshener(),
             intercrate: true,
         }
@@ -193,6 +206,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         self.infcx
     }
 
+    pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'tcx> {
+        self.param_env
+    }
+
     pub fn tcx(&self) -> &'cx ty::ctxt<'tcx> {
         self.infcx.tcx
     }
@@ -218,7 +235,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
                   -> SelectionResult<'tcx, Selection<'tcx>> {
         debug!("select({})", obligation.repr(self.tcx()));
-        assert!(!obligation.trait_ref.has_escaping_regions());
+        assert!(!obligation.predicate.has_escaping_regions());
 
         let stack = self.push_stack(None, obligation);
         match try!(self.candidate_from_obligation(&stack)) {
@@ -280,7 +297,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         debug!("evaluate_predicate_recursively({})",
                obligation.repr(self.tcx()));
 
-        match obligation.trait_ref {
+        match obligation.predicate {
             ty::Predicate::Trait(ref t) => {
                 assert!(!t.has_escaping_regions());
                 let obligation = obligation.with(t.clone());
@@ -302,6 +319,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // evaluating trait matches
                 EvaluatedToOk
             }
+
+            ty::Predicate::Projection(..) => {
+                // FIXME(#20296) -- we should be able to give a more precise answer here
+                EvaluatedToAmbig
+            }
         }
     }
 
@@ -411,9 +433,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         self.infcx.probe(|snapshot| {
             let (skol_obligation_trait_ref, skol_map) =
-                self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
+                self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
             match self.match_impl(impl_def_id, obligation, snapshot,
-                                  &skol_map, Rc::new(skol_obligation_trait_ref)) {
+                                  &skol_map, skol_obligation_trait_ref.trait_ref.clone()) {
                 Ok(substs) => {
                     let vtable_impl = self.vtable_impl(impl_def_id,
                                                        substs,
@@ -439,7 +461,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn candidate_from_obligation<'o>(&mut self,
                                      stack: &TraitObligationStack<'o, 'tcx>)
-                                     -> SelectionResult<'tcx, Candidate<'tcx>>
+                                     -> SelectionResult<'tcx, SelectionCandidate<'tcx>>
     {
         // Watch out for overflow. This intentionally bypasses (and does
         // not update) the cache.
@@ -455,17 +477,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // separately rather than using `stack.fresh_trait_ref` -- this
         // is because we want the unbound variables to be replaced
         // with fresh skolemized types starting from index 0.
-        let cache_fresh_trait_ref =
-            self.infcx.freshen(stack.obligation.trait_ref.clone());
-        debug!("candidate_from_obligation(cache_fresh_trait_ref={}, obligation={})",
-               cache_fresh_trait_ref.repr(self.tcx()),
+        let cache_fresh_trait_pred =
+            self.infcx.freshen(stack.obligation.predicate.clone());
+        debug!("candidate_from_obligation(cache_fresh_trait_pred={}, obligation={})",
+               cache_fresh_trait_pred.repr(self.tcx()),
                stack.repr(self.tcx()));
-        assert!(!stack.obligation.trait_ref.has_escaping_regions());
+        assert!(!stack.obligation.predicate.has_escaping_regions());
 
-        match self.check_candidate_cache(cache_fresh_trait_ref.clone()) {
+        match self.check_candidate_cache(&cache_fresh_trait_pred) {
             Some(c) => {
-                debug!("CACHE HIT: cache_fresh_trait_ref={}, candidate={}",
-                       cache_fresh_trait_ref.repr(self.tcx()),
+                debug!("CACHE HIT: cache_fresh_trait_pred={}, candidate={}",
+                       cache_fresh_trait_pred.repr(self.tcx()),
                        c.repr(self.tcx()));
                 return c;
             }
@@ -474,17 +496,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // If no match, compute result and insert into cache.
         let candidate = self.candidate_from_obligation_no_cache(stack);
-        debug!("CACHE MISS: cache_fresh_trait_ref={}, candidate={}",
-               cache_fresh_trait_ref.repr(self.tcx()), candidate.repr(self.tcx()));
-        self.insert_candidate_cache(cache_fresh_trait_ref, candidate.clone());
+        debug!("CACHE MISS: cache_fresh_trait_pred={}, candidate={}",
+               cache_fresh_trait_pred.repr(self.tcx()), candidate.repr(self.tcx()));
+        self.insert_candidate_cache(cache_fresh_trait_pred, candidate.clone());
         candidate
     }
 
     fn candidate_from_obligation_no_cache<'o>(&mut self,
                                               stack: &TraitObligationStack<'o, 'tcx>)
-                                              -> SelectionResult<'tcx, Candidate<'tcx>>
+                                              -> SelectionResult<'tcx, SelectionCandidate<'tcx>>
     {
-        if ty::type_is_error(stack.obligation.self_ty()) {
+        if ty::type_is_error(stack.obligation.predicate.0.self_ty()) {
             return Ok(Some(ErrorCandidate));
         }
 
@@ -497,8 +519,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let mut candidates = candidate_set.vec;
 
-        debug!("assembled {} candidates for {}",
-               candidates.len(), stack.repr(self.tcx()));
+        debug!("assembled {} candidates for {}: {}",
+               candidates.len(),
+               stack.repr(self.tcx()),
+               candidates.repr(self.tcx()));
 
         // At this point, we know that each of the entries in the
         // candidate set is *individually* applicable. Now we have to
@@ -576,7 +600,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 
     fn pick_candidate_cache(&self,
-                            cache_fresh_trait_ref: &Rc<ty::PolyTraitRef<'tcx>>)
+                            cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>)
                             -> &SelectionCache<'tcx>
     {
         // High-level idea: we have to decide whether to consult the
@@ -598,7 +622,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // If the trait refers to any parameters in scope, then use
         // the cache of the param-environment.
         if
-            cache_fresh_trait_ref.0.input_types().iter().any(
+            cache_fresh_trait_pred.0.input_types().iter().any(
                 |&t| ty::type_has_self(t) || ty::type_has_params(t))
         {
             return &self.param_env.selection_cache;
@@ -611,7 +635,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // See the discussion in doc.rs for more details.
         if
             !self.param_env.caller_bounds.is_empty() &&
-            cache_fresh_trait_ref.0.input_types().iter().any(
+            cache_fresh_trait_pred.0.input_types().iter().any(
                 |&t| ty::type_has_ty_infer(t))
         {
             return &self.param_env.selection_cache;
@@ -622,32 +646,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 
     fn check_candidate_cache(&mut self,
-                             cache_fresh_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
-                             -> Option<SelectionResult<'tcx, Candidate<'tcx>>>
+                             cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>)
+                             -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>>
     {
-        let cache = self.pick_candidate_cache(&cache_fresh_trait_ref);
+        let cache = self.pick_candidate_cache(cache_fresh_trait_pred);
         let hashmap = cache.hashmap.borrow();
-        hashmap.get(&cache_fresh_trait_ref).map(|c| (*c).clone())
+        hashmap.get(&cache_fresh_trait_pred.0.trait_ref).map(|c| (*c).clone())
     }
 
     fn insert_candidate_cache(&mut self,
-                              cache_fresh_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
-                              candidate: SelectionResult<'tcx, Candidate<'tcx>>)
+                              cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
+                              candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>)
     {
-        let cache = self.pick_candidate_cache(&cache_fresh_trait_ref);
+        let cache = self.pick_candidate_cache(&cache_fresh_trait_pred);
         let mut hashmap = cache.hashmap.borrow_mut();
-        hashmap.insert(cache_fresh_trait_ref, candidate);
+        hashmap.insert(cache_fresh_trait_pred.0.trait_ref.clone(), candidate);
     }
 
     fn assemble_candidates<'o>(&mut self,
                                stack: &TraitObligationStack<'o, 'tcx>)
-                               -> Result<CandidateSet<'tcx>, SelectionError<'tcx>>
+                               -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>>
     {
         // Check for overflow.
 
         let TraitObligationStack { obligation, .. } = *stack;
 
-        let mut candidates = CandidateSet {
+        let mut candidates = SelectionCandidateSet {
             vec: Vec::new(),
             ambiguous: false
         };
@@ -655,10 +679,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Other bounds. Consider both in-scope bounds from fn decl
         // and applicable impls. There is a certain set of precedence rules here.
 
-        match self.tcx().lang_items.to_builtin_kind(obligation.trait_ref.def_id()) {
+        match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
             Some(ty::BoundCopy) => {
                 debug!("obligation self ty is {}",
-                       obligation.self_ty().repr(self.tcx()));
+                       obligation.predicate.0.self_ty().repr(self.tcx()));
 
                 // If the user has asked for the older, compatibility
                 // behavior, ignore user-defined impls here. This will
@@ -696,18 +720,147 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         }
 
+        self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
         try!(self.assemble_candidates_from_caller_bounds(obligation, &mut candidates));
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
     }
 
+    fn assemble_candidates_from_projected_tys(&mut self,
+                                              obligation: &TraitObligation<'tcx>,
+                                              candidates: &mut SelectionCandidateSet<'tcx>)
+    {
+        let poly_trait_predicate =
+            self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
+
+        debug!("assemble_candidates_for_projected_tys({},{})",
+               obligation.repr(self.tcx()),
+               poly_trait_predicate.repr(self.tcx()));
+
+        // FIXME(#20297) -- just examining the self-type is very simplistic
+
+        // before we go into the whole skolemization thing, just
+        // quickly check if the self-type is a projection at all.
+        let trait_def_id = match poly_trait_predicate.0.trait_ref.self_ty().sty {
+            ty::ty_projection(ref data) => data.trait_ref.def_id,
+            ty::ty_infer(ty::TyVar(_)) => {
+                // If the self-type is an inference variable, then it MAY wind up
+                // being a projected type, so induce an ambiguity.
+                //
+                // FIXME(#20297) -- being strict about this can cause
+                // inference failures with BorrowFrom, which is
+                // unfortunate. Can we do better here?
+                candidates.ambiguous = true;
+                return;
+            }
+            _ => { return; }
+        };
+
+        debug!("assemble_candidates_for_projected_tys: trait_def_id={}",
+               trait_def_id.repr(self.tcx()));
+
+        let result = self.infcx.probe(|snapshot| {
+            self.match_projection_obligation_against_bounds_from_trait(obligation,
+                                                                       snapshot)
+        });
+
+        if result {
+            candidates.vec.push(ProjectionCandidate);
+        }
+    }
+
+    fn match_projection_obligation_against_bounds_from_trait(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        snapshot: &infer::CombinedSnapshot)
+        -> bool
+    {
+        let poly_trait_predicate =
+            self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
+        let (skol_trait_predicate, skol_map) =
+            self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot);
+        debug!("match_projection_obligation_against_bounds_from_trait: \
+                skol_trait_predicate={} skol_map={}",
+               skol_trait_predicate.repr(self.tcx()),
+               skol_map.repr(self.tcx()));
+
+        let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty {
+            ty::ty_projection(ref data) => &data.trait_ref,
+            _ => {
+                self.tcx().sess.span_bug(
+                    obligation.cause.span,
+                    format!("match_projection_obligation_against_bounds_from_trait() called \
+                             but self-ty not a projection: {}",
+                            skol_trait_predicate.trait_ref.self_ty().repr(self.tcx())).as_slice());
+            }
+        };
+        debug!("match_projection_obligation_against_bounds_from_trait: \
+                projection_trait_ref={}",
+               projection_trait_ref.repr(self.tcx()));
+
+        let trait_def = ty::lookup_trait_def(self.tcx(), projection_trait_ref.def_id);
+        let bounds = trait_def.generics.to_bounds(self.tcx(), projection_trait_ref.substs);
+        debug!("match_projection_obligation_against_bounds_from_trait: \
+                bounds={}",
+               bounds.repr(self.tcx()));
+
+        let matching_bound =
+            util::elaborate_predicates(self.tcx(), bounds.predicates.to_vec())
+            .filter_to_traits()
+            .find(
+                |bound| self.infcx.probe(
+                    |_| self.match_projection(obligation,
+                                              bound.clone(),
+                                              skol_trait_predicate.trait_ref.clone(),
+                                              &skol_map,
+                                              snapshot)));
+
+        debug!("match_projection_obligation_against_bounds_from_trait: \
+                matching_bound={}",
+               matching_bound.repr(self.tcx()));
+        match matching_bound {
+            None => false,
+            Some(bound) => {
+                // Repeat the successful match, if any, this time outside of a probe.
+                let result = self.match_projection(obligation,
+                                                   bound,
+                                                   skol_trait_predicate.trait_ref.clone(),
+                                                   &skol_map,
+                                                   snapshot);
+                assert!(result);
+                true
+            }
+        }
+    }
+
+    fn match_projection(&mut self,
+                        obligation: &TraitObligation<'tcx>,
+                        trait_bound: ty::PolyTraitRef<'tcx>,
+                        skol_trait_ref: Rc<ty::TraitRef<'tcx>>,
+                        skol_map: &infer::SkolemizationMap,
+                        snapshot: &infer::CombinedSnapshot)
+                        -> bool
+    {
+        assert!(!skol_trait_ref.has_escaping_regions());
+        let origin = infer::RelateOutputImplTypes(obligation.cause.span);
+        match self.infcx.sub_poly_trait_refs(false,
+                                             origin,
+                                             trait_bound.clone(),
+                                             ty::Binder(skol_trait_ref.clone())) {
+            Ok(()) => { }
+            Err(_) => { return false; }
+        }
+
+        self.infcx.leak_check(skol_map, snapshot).is_ok()
+    }
+
     /// Given an obligation like `<SomeTrait for T>`, search the obligations that the caller
     /// 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 CandidateSet<'tcx>)
+                                              candidates: &mut SelectionCandidateSet<'tcx>)
                                               -> Result<(),SelectionError<'tcx>>
     {
         debug!("assemble_candidates_from_caller_bounds({})",
@@ -715,7 +868,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let caller_trait_refs: Vec<_> =
             self.param_env.caller_bounds.predicates.iter()
-            .filter_map(|o| o.to_trait())
+            .filter_map(|o| o.to_opt_poly_trait_ref())
             .collect();
 
         let all_bounds =
@@ -728,8 +881,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     |_| self.match_where_clause(obligation, bound.clone())).is_ok());
 
         let param_candidates =
-            matching_bounds.map(
-                |bound| ParamCandidate(VtableParamData { bound: bound }));
+            matching_bounds.map(|bound| ParamCandidate(bound));
 
         candidates.vec.extend(param_candidates);
 
@@ -744,10 +896,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// unified during the confirmation step.
     fn assemble_unboxed_closure_candidates(&mut self,
                                            obligation: &TraitObligation<'tcx>,
-                                           candidates: &mut CandidateSet<'tcx>)
+                                           candidates: &mut SelectionCandidateSet<'tcx>)
                                            -> Result<(),SelectionError<'tcx>>
     {
-        let kind = match self.fn_family_trait_kind(obligation.trait_ref.def_id()) {
+        let kind = match self.fn_family_trait_kind(obligation.predicate.0.def_id()) {
             Some(k) => k,
             None => { return Ok(()); }
         };
@@ -767,15 +919,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                kind,
                obligation.repr(self.tcx()));
 
-        let closure_kind = match self.typer.unboxed_closures().borrow().get(&closure_def_id) {
-            Some(closure) => closure.kind,
-            None => {
-                self.tcx().sess.span_bug(
-                    obligation.cause.span,
-                    format!("No entry for unboxed closure: {}",
-                            closure_def_id.repr(self.tcx()))[]);
-            }
-        };
+        let closure_kind = self.closure_typer.unboxed_closure_kind(closure_def_id);
 
         debug!("closure_kind = {}", closure_kind);
 
@@ -789,13 +933,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// Implement one of the `Fn()` family for a fn pointer.
     fn assemble_fn_pointer_candidates(&mut self,
                                       obligation: &TraitObligation<'tcx>,
-                                      candidates: &mut CandidateSet<'tcx>)
+                                      candidates: &mut SelectionCandidateSet<'tcx>)
                                       -> Result<(),SelectionError<'tcx>>
     {
         // We provide a `Fn` impl for fn pointers. There is no need to provide
         // the other traits (e.g. `FnMut`) since those are provided by blanket
         // impls.
-        if Some(obligation.trait_ref.def_id()) != self.tcx().lang_items.fn_trait() {
+        if Some(obligation.predicate.def_id()) != self.tcx().lang_items.fn_trait() {
             return Ok(());
         }
 
@@ -827,16 +971,16 @@ 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<Candidate<'tcx>>)
+                                      candidate_vec: &mut Vec<SelectionCandidate<'tcx>>)
                                       -> Result<(), SelectionError<'tcx>>
     {
-        let all_impls = self.all_impls(obligation.trait_ref.def_id());
+        let all_impls = self.all_impls(obligation.predicate.def_id());
         for &impl_def_id in all_impls.iter() {
             self.infcx.probe(|snapshot| {
-                let (skol_obligation_trait_ref, skol_map) =
-                    self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
+                let (skol_obligation_trait_pred, skol_map) =
+                    self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
                 match self.match_impl(impl_def_id, obligation, snapshot,
-                                      &skol_map, Rc::new(skol_obligation_trait_ref)) {
+                                      &skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
                     Ok(_) => {
                         candidate_vec.push(ImplCandidate(impl_def_id));
                     }
@@ -861,7 +1005,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// scrutiny.
     fn winnow_candidate<'o>(&mut self,
                             stack: &TraitObligationStack<'o, 'tcx>,
-                            candidate: &Candidate<'tcx>)
+                            candidate: &SelectionCandidate<'tcx>)
                             -> EvaluationResult<'tcx>
     {
         debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx()));
@@ -918,12 +1062,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// a case where doing the opposite caused us harm.
     fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
                                                    stack: &TraitObligationStack<'o, 'tcx>,
-                                                   candidate_i: &Candidate<'tcx>,
-                                                   candidate_j: &Candidate<'tcx>)
+                                                   candidate_i: &SelectionCandidate<'tcx>,
+                                                   candidate_j: &SelectionCandidate<'tcx>)
                                                    -> bool
     {
         match (candidate_i, candidate_j) {
-            (&ImplCandidate(impl_def_id), &ParamCandidate(ref vt)) => {
+            (&ImplCandidate(impl_def_id), &ParamCandidate(ref bound)) => {
                 debug!("Considering whether to drop param {} in favor of impl {}",
                        candidate_i.repr(self.tcx()),
                        candidate_j.repr(self.tcx()));
@@ -931,23 +1075,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 self.infcx.probe(|snapshot| {
                     let (skol_obligation_trait_ref, skol_map) =
                         self.infcx().skolemize_late_bound_regions(
-                            &*stack.obligation.trait_ref, snapshot);
+                            &stack.obligation.predicate, snapshot);
                     let impl_substs =
                         self.rematch_impl(impl_def_id, stack.obligation, snapshot,
-                                          &skol_map, Rc::new(skol_obligation_trait_ref));
+                                          &skol_map, skol_obligation_trait_ref.trait_ref.clone());
                     let impl_trait_ref =
                         ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
                     let impl_trait_ref =
                         impl_trait_ref.subst(self.tcx(), &impl_substs);
                     let poly_impl_trait_ref =
-                        Rc::new(ty::Binder((*impl_trait_ref).clone()));
+                        ty::Binder(impl_trait_ref);
                     let origin =
                         infer::RelateOutputImplTypes(stack.obligation.cause.span);
                     self.infcx
-                        .sub_poly_trait_refs(false, origin, poly_impl_trait_ref, vt.bound.clone())
+                        .sub_poly_trait_refs(false, origin, poly_impl_trait_ref, bound.clone())
                         .is_ok()
                 })
             }
+            (&ProjectionCandidate, &ParamCandidate(_)) => {
+                // FIXME(#20297) -- this gives where clauses precedent
+                // over projections. Really these are just two means
+                // of deducing information (one based on the where
+                // clauses on the trait definition; one based on those
+                // on the enclosing scope), and it'd be better to
+                // integrate them more intelligently. But for now this
+                // seems ok. If we DON'T give where clauses
+                // precedence, we run into trouble in default methods,
+                // where both the projection bounds for `Self::A` and
+                // the where clauses are in scope.
+                true
+            }
             _ => {
                 *candidate_i == *candidate_j
             }
@@ -966,7 +1123,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     fn assemble_builtin_bound_candidates<'o>(&mut self,
                                              bound: ty::BuiltinBound,
                                              stack: &TraitObligationStack<'o, 'tcx>,
-                                             candidates: &mut CandidateSet<'tcx>)
+                                             candidates: &mut SelectionCandidateSet<'tcx>)
                                              -> Result<(),SelectionError<'tcx>>
     {
         match self.builtin_bound(bound, stack.obligation) {
@@ -987,7 +1144,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                      obligation: &TraitObligation<'tcx>)
                      -> Result<BuiltinBoundConditions<'tcx>,SelectionError<'tcx>>
     {
-        let self_ty = self.infcx.shallow_resolve(obligation.trait_ref.self_ty());
+        // Note: these tests operate on types that may contain bound
+        // regions. To be proper, we ought to skolemize here, but we
+        // forego the skolemization and defer it until the
+        // confirmation step.
+
+        let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
         return match self_ty.sty {
             ty::ty_infer(ty::IntVar(_)) |
             ty::ty_infer(ty::FloatVar(_)) |
@@ -1100,11 +1262,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         } else {
                             // Recursively check all supertraits to find out if any further
                             // bounds are required and thus we must fulfill.
-                            let tmp_tr = data.principal_trait_ref_with_self_ty(self.tcx(),
-                                                                               ty::mk_err());
-                            for tr in util::supertraits(self.tcx(), tmp_tr) {
+                            let principal =
+                                data.principal_trait_ref_with_self_ty(self.tcx(),
+                                                                      self.tcx().types.err);
+                            for tr in util::supertraits(self.tcx(), principal) {
                                 let td = ty::lookup_trait_def(self.tcx(), tr.def_id());
-
                                 if td.bounds.builtin_bounds.contains(&bound) {
                                     return Ok(If(Vec::new()))
                                 }
@@ -1229,32 +1391,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     return Ok(ParameterBuiltin);
                 }
 
-                match self.tcx().freevars.borrow().get(&def_id.node) {
-                    None => {
-                        // No upvars.
-                        Ok(If(Vec::new()))
+                match self.closure_typer.unboxed_closure_upvars(def_id, substs) {
+                    Some(upvars) => {
+                        Ok(If(upvars.iter().map(|c| c.ty).collect()))
                     }
-
-                    Some(freevars) => {
-                        let tys: Vec<Ty> =
-                            freevars
-                            .iter()
-                            .map(|freevar| {
-                                let freevar_def_id = freevar.def.def_id();
-                                self.typer.node_ty(freevar_def_id.node).subst(self.tcx(), substs)
-                            })
-                            .collect();
-                        Ok(If(tys))
+                    None => {
+                        Ok(AmbiguousBuiltin)
                     }
                 }
             }
 
             ty::ty_struct(def_id, substs) => {
                 let types: Vec<Ty> =
-                    ty::struct_fields(self.tcx(), def_id, substs)
-                    .iter()
-                    .map(|f| f.mt.ty)
-                    .collect();
+                    ty::struct_fields(self.tcx(), def_id, substs).iter()
+                                                                 .map(|f| f.mt.ty)
+                                                                 .collect();
                 nominal(self, bound, def_id, types)
             }
 
@@ -1268,6 +1419,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 nominal(self, bound, def_id, types)
             }
 
+            ty::ty_projection(_) |
             ty::ty_param(_) => {
                 // Note: A type parameter is only considered to meet a
                 // particular bound if there is a where clause telling
@@ -1359,7 +1511,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn confirm_candidate(&mut self,
                          obligation: &TraitObligation<'tcx>,
-                         candidate: Candidate<'tcx>)
+                         candidate: SelectionCandidate<'tcx>)
                          -> Result<Selection<'tcx>,SelectionError<'tcx>>
     {
         debug!("confirm_candidate({}, {})",
@@ -1377,8 +1529,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             ParamCandidate(param) => {
-                Ok(VtableParam(
-                    try!(self.confirm_param_candidate(obligation, param))))
+                self.confirm_param_candidate(obligation, param);
+                Ok(VtableParam)
             }
 
             ImplCandidate(impl_def_id) => {
@@ -1397,14 +1549,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     try!(self.confirm_fn_pointer_candidate(obligation));
                 Ok(VtableFnPointer(fn_type))
             }
+
+            ProjectionCandidate => {
+                self.confirm_projection_candidate(obligation);
+                Ok(VtableParam)
+            }
         }
     }
 
+    fn confirm_projection_candidate(&mut self,
+                                    obligation: &TraitObligation<'tcx>)
+    {
+        let _: Result<(),()> =
+            self.infcx.try(|snapshot| {
+                let result =
+                    self.match_projection_obligation_against_bounds_from_trait(obligation,
+                                                                               snapshot);
+                assert!(result);
+                Ok(())
+            });
+    }
+
     fn confirm_param_candidate(&mut self,
                                obligation: &TraitObligation<'tcx>,
-                               param: VtableParamData<'tcx>)
-                               -> Result<VtableParamData<'tcx>,
-                                         SelectionError<'tcx>>
+                               param: ty::PolyTraitRef<'tcx>)
     {
         debug!("confirm_param_candidate({},{})",
                obligation.repr(self.tcx()),
@@ -1415,13 +1583,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // trait-ref. Repeat that unification now without any
         // transactional boundary; it should not fail.
         match self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                           obligation.trait_ref.clone(),
-                                           param.bound.clone()) {
-            Ok(()) => Ok(param),
+                                           obligation.predicate.to_poly_trait_ref(),
+                                           param.clone()) {
+            Ok(()) => { }
             Err(_) => {
                 self.tcx().sess.bug(
                     format!("Where clause `{}` was applicable to `{}` but now is not",
-                            param.bound.repr(self.tcx()),
+                            param.repr(self.tcx()),
                             obligation.repr(self.tcx())).as_slice());
             }
         }
@@ -1454,13 +1622,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                            -> VtableBuiltinData<PredicateObligation<'tcx>>
     {
         let derived_cause = self.derived_cause(obligation, BuiltinDerivedObligation);
-        let obligations = nested.iter().map(|&t| {
-            util::predicate_for_builtin_bound(
-                self.tcx(),
-                derived_cause.clone(),
-                bound,
-                obligation.recursion_depth + 1,
-                t)
+        let obligations = nested.iter().map(|&bound_ty| {
+            // the obligation might be higher-ranked, e.g. for<'a> &'a
+            // int : Copy. In that case, we will wind up with
+            // late-bound regions in the `nested` vector. So for each
+            // one we instantiate to a skolemized region, do our work
+            // to produce something like `&'0 int : Copy`, and then
+            // re-bind it. This is a bit of busy-work but preserves
+            // the invariant that we only manipulate free regions, not
+            // bound ones.
+            self.infcx.try(|snapshot| {
+                let (skol_ty, skol_map) =
+                    self.infcx().skolemize_late_bound_regions(&ty::Binder(bound_ty), snapshot);
+                let skol_predicate =
+                    util::predicate_for_builtin_bound(
+                        self.tcx(),
+                        derived_cause.clone(),
+                        bound,
+                        obligation.recursion_depth + 1,
+                        skol_ty);
+                match skol_predicate {
+                    Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot,
+                                                                     &skol_predicate)),
+                    Err(ErrorReported) => Err(ErrorReported)
+                }
+            })
         }).collect::<Result<_, _>>();
         let mut obligations = match obligations {
             Ok(o) => o,
@@ -1472,13 +1658,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             obligations.push(Obligation {
                 cause: obligation.cause.clone(),
                 recursion_depth: obligation.recursion_depth+1,
-                trait_ref: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
+                predicate: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
                                                             ty::ReStatic)).as_predicate(),
             });
         }
 
-        let obligations = VecPerParamSpace::new(obligations, Vec::new(),
-                                                Vec::new(), Vec::new());
+        let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
 
         debug!("vtable_builtin_data: obligations={}",
                obligations.repr(self.tcx()));
@@ -1500,9 +1685,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // this time not in a probe.
         self.infcx.try(|snapshot| {
             let (skol_obligation_trait_ref, skol_map) =
-                self.infcx().skolemize_late_bound_regions(&*obligation.trait_ref, snapshot);
-            let substs = self.rematch_impl(impl_def_id, obligation,
-                                           snapshot, &skol_map, Rc::new(skol_obligation_trait_ref));
+                self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
+            let substs =
+                self.rematch_impl(impl_def_id, obligation,
+                                  snapshot, &skol_map, skol_obligation_trait_ref.trait_ref);
             debug!("confirm_impl_candidate substs={}", substs);
             Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
                                 obligation.recursion_depth + 1, skol_map, snapshot))
@@ -1571,15 +1757,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             Substs::new_trait(
                 vec![arguments_tuple, output_type],
                 vec![],
-                vec![],
                 self_ty);
-        let trait_ref = Rc::new(ty::Binder(ty::TraitRef {
-            def_id: obligation.trait_ref.def_id(),
+        let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
+            def_id: obligation.predicate.def_id(),
             substs: self.tcx().mk_substs(substs),
         }));
 
         try!(self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                          obligation.trait_ref.clone(),
+                                          obligation.predicate.to_poly_trait_ref(),
                                           trait_ref));
         Ok(self_ty)
     }
@@ -1595,28 +1780,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                closure_def_id.repr(self.tcx()),
                substs.repr(self.tcx()));
 
-        let closure_type = match self.typer.unboxed_closures().borrow().get(&closure_def_id) {
-            Some(closure) => closure.closure_type.clone(),
-            None => {
-                self.tcx().sess.span_bug(
-                    obligation.cause.span,
-                    format!("No entry for unboxed closure: {}",
-                            closure_def_id.repr(self.tcx()))[]);
-            }
-        };
+        let closure_type = self.closure_typer.unboxed_closure_type(closure_def_id, substs);
+
+        debug!("confirm_unboxed_closure_candidate: closure_def_id={} closure_type={}",
+               closure_def_id.repr(self.tcx()),
+               closure_type.repr(self.tcx()));
 
         let closure_sig = &closure_type.sig;
         let arguments_tuple = closure_sig.0.inputs[0];
-        let substs =
+        let trait_substs =
             Substs::new_trait(
-                vec![arguments_tuple.subst(self.tcx(), substs),
-                     closure_sig.0.output.unwrap().subst(self.tcx(), substs)],
-                vec![],
+                vec![arguments_tuple, closure_sig.0.output.unwrap()],
                 vec![],
                 obligation.self_ty());
-        let trait_ref = Rc::new(ty::Binder(ty::TraitRef {
-            def_id: obligation.trait_ref.def_id(),
-            substs: self.tcx().mk_substs(substs),
+        let trait_ref = ty::Binder(Rc::new(ty::TraitRef {
+            def_id: obligation.predicate.def_id(),
+            substs: self.tcx().mk_substs(trait_substs),
         }));
 
         debug!("confirm_unboxed_closure_candidate(closure_def_id={}, trait_ref={})",
@@ -1624,7 +1803,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                trait_ref.repr(self.tcx()));
 
         self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                     obligation.trait_ref.clone(),
+                                     obligation.predicate.to_poly_trait_ref(),
                                      trait_ref)
     }
 
@@ -1655,8 +1834,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// report an error to the user.
     fn confirm_poly_trait_refs(&mut self,
                                obligation_cause: ObligationCause,
-                               obligation_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
-                               expected_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+                               obligation_trait_ref: ty::PolyTraitRef<'tcx>,
+                               expected_trait_ref: ty::PolyTraitRef<'tcx>)
                                -> Result<(), SelectionError<'tcx>>
     {
         let origin = infer::RelateOutputImplTypes(obligation_cause.span);
@@ -1769,7 +1948,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // substitution if we find that any of the input types, when
         // simplified, do not match.
 
-        obligation.trait_ref.input_types().iter()
+        obligation.predicate.0.input_types().iter()
             .zip(impl_trait_ref.input_types().iter())
             .any(|(&obligation_ty, &impl_ty)| {
                 let simplified_obligation_ty =
@@ -1785,7 +1964,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
     fn match_where_clause(&mut self,
                           obligation: &TraitObligation<'tcx>,
-                          where_clause_trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+                          where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
                         -> Result<(),()>
     {
         debug!("match_where_clause: obligation={} where_clause_trait_ref={}",
@@ -1796,7 +1975,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         match self.infcx.sub_poly_trait_refs(false,
                                              origin,
                                              where_clause_trait_ref,
-                                             obligation.trait_ref.clone()) {
+                                             obligation.predicate.to_poly_trait_ref()) {
             Ok(()) => Ok(()),
             Err(_) => Err(()),
         }
@@ -1878,7 +2057,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             obligation: &'o TraitObligation<'tcx>)
                             -> TraitObligationStack<'o, 'tcx>
     {
-        let fresh_trait_ref = obligation.trait_ref.fold_with(&mut self.freshener);
+        let fresh_trait_ref =
+            obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener);
 
         TraitObligationStack {
             obligation: obligation,
@@ -1897,7 +2077,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
-    fn impl_predicates(&self,
+    fn impl_predicates(&mut self,
                        cause: ObligationCause<'tcx>,
                        recursion_depth: uint,
                        impl_def_id: ast::DefId,
@@ -1908,8 +2088,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
         let bounds = impl_generics.to_bounds(self.tcx(), impl_substs);
-        let bounds = self.infcx().plug_leaks(skol_map, snapshot, &bounds);
-        util::predicates_for_generics(self.tcx(), cause, recursion_depth, &bounds)
+        let normalized_bounds =
+            project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds);
+        let normalized_bounds =
+            self.infcx().plug_leaks(skol_map, snapshot, &normalized_bounds);
+        let mut impl_obligations =
+            util::predicates_for_generics(self.tcx(),
+                                          cause,
+                                          recursion_depth,
+                                          &normalized_bounds.value);
+        for obligation in normalized_bounds.obligations.into_iter() {
+            impl_obligations.push(TypeSpace, obligation);
+        }
+        impl_obligations
     }
 
     fn fn_family_trait_kind(&self,
@@ -1931,9 +2122,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     #[allow(unused_comparisons)]
     fn derived_cause(&self,
                      obligation: &TraitObligation<'tcx>,
-                     variant: fn(Rc<ty::Binder<ty::TraitRef<'tcx>>>,
-                                 Rc<ObligationCauseCode<'tcx>>)
-                                 -> ObligationCauseCode<'tcx>)
+                     variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
                      -> ObligationCause<'tcx>
     {
         /*!
@@ -1950,29 +2139,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // chain. Ideally, we should have a way to configure this either
         // by using -Z verbose or just a CLI argument.
         if obligation.recursion_depth >= 0 {
+            let derived_cause = DerivedObligationCause {
+                parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
+                parent_code: Rc::new(obligation.cause.code.clone()),
+            };
             ObligationCause::new(obligation.cause.span,
-                                 obligation.trait_ref.def_id().node,
-                                 variant(obligation.trait_ref.clone(),
-                                         Rc::new(obligation.cause.code.clone())))
+                                 obligation.cause.body_id,
+                                 variant(derived_cause))
         } else {
             obligation.cause.clone()
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for Candidate<'tcx> {
+impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
             ErrorCandidate => format!("ErrorCandidate"),
             BuiltinCandidate(b) => format!("BuiltinCandidate({})", b),
+            ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
+            ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
+            ProjectionCandidate => format!("ProjectionCandidate"),
+            FnPointerCandidate => format!("FnPointerCandidate"),
             UnboxedClosureCandidate(c, ref s) => {
                 format!("UnboxedClosureCandidate({},{})", c, s.repr(tcx))
             }
-            FnPointerCandidate => {
-                format!("FnPointerCandidate")
-            }
-            ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
-            ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
         }
     }
 }
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index e75478b3243..109810fc7ee 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use middle::subst::{Subst, Substs, VecPerParamSpace};
+use middle::subst::{Substs, VecPerParamSpace};
 use middle::infer::InferCtxt;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, Ty, AsPredicate, ToPolyTraitRef};
 use std::collections::HashSet;
 use std::fmt;
 use std::rc::Rc;
@@ -20,7 +20,7 @@ use util::common::ErrorReported;
 use util::ppaux::Repr;
 
 use super::{Obligation, ObligationCause, PredicateObligation,
-            VtableImpl, VtableParam, VtableParamData, VtableImplData};
+            VtableImpl, VtableParam, VtableImplData};
 
 ///////////////////////////////////////////////////////////////////////////
 // `Elaboration` iterator
@@ -46,19 +46,19 @@ struct StackEntry<'tcx> {
 
 pub fn elaborate_trait_ref<'cx, 'tcx>(
     tcx: &'cx ty::ctxt<'tcx>,
-    trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+    trait_ref: ty::PolyTraitRef<'tcx>)
     -> Elaborator<'cx, 'tcx>
 {
-    elaborate_predicates(tcx, vec![ty::Predicate::Trait(trait_ref)])
+    elaborate_predicates(tcx, vec![trait_ref.as_predicate()])
 }
 
 pub fn elaborate_trait_refs<'cx, 'tcx>(
     tcx: &'cx ty::ctxt<'tcx>,
-    trait_refs: &[Rc<ty::PolyTraitRef<'tcx>>])
+    trait_refs: &[ty::PolyTraitRef<'tcx>])
     -> Elaborator<'cx, 'tcx>
 {
     let predicates = trait_refs.iter()
-                               .map(|trait_ref| ty::Predicate::Trait((*trait_ref).clone()))
+                               .map(|trait_ref| trait_ref.as_predicate())
                                .collect();
     elaborate_predicates(tcx, predicates)
 }
@@ -78,23 +78,34 @@ pub fn elaborate_predicates<'cx, 'tcx>(
 }
 
 impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
+    pub fn filter_to_traits(self) -> Supertraits<'cx, 'tcx> {
+        Supertraits { elaborator: self }
+    }
+
     fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
         match *predicate {
-            ty::Predicate::Trait(ref trait_ref) => {
+            ty::Predicate::Trait(ref data) => {
                 let mut predicates =
-                    ty::predicates_for_trait_ref(self.tcx, &**trait_ref);
+                    ty::predicates_for_trait_ref(self.tcx,
+                                                 &data.to_poly_trait_ref());
 
                 // Only keep those bounds that we haven't already
                 // seen.  This is necessary to prevent infinite
                 // recursion in some cases.  One common case is when
                 // people define `trait Sized { }` rather than `trait
                 // Sized for Sized? { }`.
-                predicates.retain(|r| self.visited.insert((*r).clone()));
+                predicates.retain(|r| self.visited.insert(r.clone()));
 
                 self.stack.push(StackEntry { position: 0,
                                              predicates: predicates });
             }
             ty::Predicate::Equate(..) => {
+                // Currently, we do not "elaborate" predicates like
+                // `X == Y`, though conceivably we might. For example,
+                // `&X == &Y` implies that `X == Y`.
+            }
+            ty::Predicate::Projection(..) => {
+                // Nothing to elaborate in a projection predicate.
             }
             ty::Predicate::RegionOutlives(..) |
             ty::Predicate::TypeOutlives(..) => {
@@ -173,34 +184,30 @@ pub struct Supertraits<'cx, 'tcx:'cx> {
 }
 
 pub fn supertraits<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
-                              trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+                              trait_ref: ty::PolyTraitRef<'tcx>)
                               -> Supertraits<'cx, 'tcx>
 {
-    let elaborator = elaborate_trait_ref(tcx, trait_ref);
-    Supertraits { elaborator: elaborator }
+    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
 }
 
 pub fn transitive_bounds<'cx, 'tcx>(tcx: &'cx ty::ctxt<'tcx>,
-                                    bounds: &[Rc<ty::PolyTraitRef<'tcx>>])
+                                    bounds: &[ty::PolyTraitRef<'tcx>])
                                     -> Supertraits<'cx, 'tcx>
 {
-    let elaborator = elaborate_trait_refs(tcx, bounds);
-    Supertraits { elaborator: elaborator }
+    elaborate_trait_refs(tcx, bounds).filter_to_traits()
 }
 
-impl<'cx, 'tcx> Iterator<Rc<ty::PolyTraitRef<'tcx>>> for Supertraits<'cx, 'tcx> {
-    fn next(&mut self) -> Option<Rc<ty::PolyTraitRef<'tcx>>> {
+impl<'cx, 'tcx> Iterator<ty::PolyTraitRef<'tcx>> for Supertraits<'cx, 'tcx> {
+    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
         loop {
             match self.elaborator.next() {
                 None => {
                     return None;
                 }
-                Some(ty::Predicate::Trait(trait_ref)) => {
-                    return Some(trait_ref);
+                Some(ty::Predicate::Trait(data)) => {
+                    return Some(data.to_poly_trait_ref());
                 }
-                Some(ty::Predicate::Equate(..)) |
-                Some(ty::Predicate::RegionOutlives(..)) |
-                Some(ty::Predicate::TypeOutlives(..)) => {
+                Some(_) => {
                 }
             }
         }
@@ -222,18 +229,7 @@ pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 {
     let tcx = infcx.tcx;
     let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
-    let input_substs = infcx.fresh_substs_for_generics(span, &impl_generics);
-
-    // Add substs for the associated types bound in the impl.
-    let ref items = tcx.impl_items.borrow()[impl_def_id];
-    let mut assoc_tys = Vec::new();
-    for item in items.iter() {
-        if let &ty::ImplOrTraitItemId::TypeTraitItemId(id) = item {
-            assoc_tys.push(tcx.tcache.borrow()[id].ty.subst(tcx, &input_substs));
-        }
-    }
-
-    input_substs.with_assoc_tys(assoc_tys)
+    infcx.fresh_substs_for_generics(span, &impl_generics)
 }
 
 impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> {
@@ -242,12 +238,6 @@ impl<'tcx, N> fmt::Show for VtableImplData<'tcx, N> {
     }
 }
 
-impl<'tcx> fmt::Show for VtableParamData<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "VtableParam(...)")
-    }
-}
-
 /// See `super::obligations_for_generics`
 pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      cause: ObligationCause<'tcx>,
@@ -261,22 +251,22 @@ pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
     generic_bounds.predicates.map(|predicate| {
         Obligation { cause: cause.clone(),
                      recursion_depth: recursion_depth,
-                     trait_ref: predicate.clone() }
+                     predicate: predicate.clone() }
     })
 }
 
-pub fn poly_trait_ref_for_builtin_bound<'tcx>(
+pub fn trait_ref_for_builtin_bound<'tcx>(
     tcx: &ty::ctxt<'tcx>,
     builtin_bound: ty::BuiltinBound,
     param_ty: Ty<'tcx>)
-    -> Result<Rc<ty::PolyTraitRef<'tcx>>, ErrorReported>
+    -> Result<Rc<ty::TraitRef<'tcx>>, ErrorReported>
 {
     match tcx.lang_items.from_builtin_kind(builtin_bound) {
         Ok(def_id) => {
-            Ok(Rc::new(ty::Binder(ty::TraitRef {
+            Ok(Rc::new(ty::TraitRef {
                 def_id: def_id,
                 substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
-            })))
+            }))
         }
         Err(e) => {
             tcx.sess.err(e.as_slice());
@@ -293,38 +283,18 @@ pub fn predicate_for_builtin_bound<'tcx>(
     param_ty: Ty<'tcx>)
     -> Result<PredicateObligation<'tcx>, ErrorReported>
 {
-    let trait_ref = try!(poly_trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
+    let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
     Ok(Obligation {
         cause: cause,
         recursion_depth: recursion_depth,
-        trait_ref: ty::Predicate::Trait(trait_ref),
+        predicate: trait_ref.as_predicate(),
     })
 }
 
-/// Starting from a caller obligation `caller_bound` (which has coordinates `space`/`i` in the list
-/// of caller obligations), search through the trait and supertraits to find one where `test(d)` is
-/// true, where `d` is the def-id of the trait/supertrait. If any is found, return `Some(p)` where
-/// `p` is the path to that trait/supertrait. Else `None`.
-pub fn search_trait_and_supertraits_from_bound<'tcx,F>(tcx: &ty::ctxt<'tcx>,
-                                                       caller_bound: Rc<ty::PolyTraitRef<'tcx>>,
-                                                       mut test: F)
-                                                       -> Option<VtableParamData<'tcx>>
-    where F: FnMut(ast::DefId) -> bool,
-{
-    for bound in transitive_bounds(tcx, &[caller_bound]) {
-        if test(bound.def_id()) {
-            let vtable_param = VtableParamData { bound: bound };
-            return Some(vtable_param);
-        }
-    }
-
-    return None;
-}
-
 impl<'tcx,O:Repr<'tcx>> Repr<'tcx> for super::Obligation<'tcx, O> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("Obligation(trait_ref={},depth={})",
-                self.trait_ref.repr(tcx),
+        format!("Obligation(predicate={},depth={})",
+                self.predicate.repr(tcx),
                 self.recursion_depth)
     }
 }
@@ -344,8 +314,8 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::Vtable<'tcx, N> {
                 format!("VtableFnPointer({})",
                         d.repr(tcx)),
 
-            super::VtableParam(ref v) =>
-                format!("VtableParam({})", v.repr(tcx)),
+            super::VtableParam =>
+                format!("VtableParam"),
 
             super::VtableBuiltin(ref d) =>
                 d.repr(tcx)
@@ -369,13 +339,6 @@ impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableBuiltinData<N> {
     }
 }
 
-impl<'tcx> Repr<'tcx> for super::VtableParamData<'tcx> {
-    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("VtableParam(bound={})",
-                self.bound.repr(tcx))
-    }
-}
-
 impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
@@ -406,6 +369,7 @@ impl<'tcx> Repr<'tcx> for super::FulfillmentErrorCode<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
             super::CodeSelectionError(ref o) => o.repr(tcx),
+            super::CodeProjectionError(ref o) => o.repr(tcx),
             super::CodeAmbiguity => format!("Ambiguity")
         }
     }
@@ -415,13 +379,22 @@ impl<'tcx> fmt::Show for super::FulfillmentErrorCode<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             super::CodeSelectionError(ref e) => write!(f, "{}", e),
+            super::CodeProjectionError(ref e) => write!(f, "{}", e),
             super::CodeAmbiguity => write!(f, "Ambiguity")
         }
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> {
+impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        ty::type_err_to_str(tcx, self)
+        self.err.repr(tcx)
     }
 }
+
+impl<'tcx> fmt::Show for super::MismatchedProjectionTypes<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "MismatchedProjectionTypes(..)")
+    }
+}
+
+
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 02ca72fffa1..07ff0ed67a6 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -56,16 +56,15 @@ use middle::resolve_lifetime;
 use middle::infer;
 use middle::stability;
 use middle::subst::{mod, Subst, Substs, VecPerParamSpace};
-use middle::traits::ObligationCause;
 use middle::traits;
 use middle::ty;
 use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
 use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
 use util::ppaux::{trait_store_to_string, ty_to_string};
 use util::ppaux::{Repr, UserString};
-use util::common::{indenter, memoized, ErrorReported};
+use util::common::{memoized, ErrorReported};
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
-use util::nodemap::{FnvHashMap, FnvHashSet};
+use util::nodemap::{FnvHashMap};
 
 use arena::TypedArena;
 use std::borrow::BorrowFrom;
@@ -80,14 +79,14 @@ use collections::enum_set::{EnumSet, CLike};
 use std::collections::{HashMap, HashSet};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use syntax::abi;
-use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, Ident, ItemTrait, LOCAL_CRATE};
+use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE};
 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
 use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
 use syntax::ast::{Visibility};
 use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod};
 use syntax::attr::{mod, AttrMetaMethods};
-use syntax::codemap::{DUMMY_SP, Span};
-use syntax::parse::token::{mod, InternedString};
+use syntax::codemap::Span;
+use syntax::parse::token::{mod, InternedString, special_idents};
 use syntax::{ast, ast_map};
 
 pub type Disr = u64;
@@ -397,14 +396,14 @@ pub fn type_of_adjust<'tcx>(cx: &ctxt<'tcx>, adj: &AutoAdjustment<'tcx>) -> Opti
     fn type_of_autoref<'tcx>(cx: &ctxt<'tcx>, autoref: &AutoRef<'tcx>) -> Option<Ty<'tcx>> {
         match autoref {
             &AutoUnsize(ref k) => match k {
-                &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
-                    Some(mk_trait(cx, (*principal).clone(), bounds))
+                &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+                    Some(mk_trait(cx, principal.clone(), bounds.clone()))
                 }
                 _ => None
             },
             &AutoUnsizeUniq(ref k) => match k {
-                &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
-                    Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds)))
+                &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+                    Some(mk_uniq(cx, mk_trait(cx, principal.clone(), bounds.clone())))
                 }
                 _ => None
             },
@@ -588,19 +587,36 @@ pub enum vtable_origin<'tcx> {
 
 // For every explicit cast into an object type, maps from the cast
 // expr to the associated trait ref.
-pub type ObjectCastMap<'tcx> = RefCell<NodeMap<Rc<ty::PolyTraitRef<'tcx>>>>;
+pub type ObjectCastMap<'tcx> = RefCell<NodeMap<ty::PolyTraitRef<'tcx>>>;
 
 /// A restriction that certain types must be the same size. The use of
-/// `transmute` gives rise to these restrictions.
+/// `transmute` gives rise to these restrictions. These generally
+/// cannot be checked until trans; therefore, each call to `transmute`
+/// will push one or more such restriction into the
+/// `transmute_restrictions` vector during `intrinsicck`. They are
+/// then checked during `trans` by the fn `check_intrinsics`.
 #[deriving(Copy)]
 pub struct TransmuteRestriction<'tcx> {
-    /// The span from whence the restriction comes.
+    /// The span whence the restriction comes.
     pub span: Span,
+
     /// The type being transmuted from.
-    pub from: Ty<'tcx>,
+    pub original_from: Ty<'tcx>,
+
     /// The type being transmuted to.
-    pub to: Ty<'tcx>,
-    /// NodeIf of the transmute intrinsic.
+    pub original_to: Ty<'tcx>,
+
+    /// The type being transmuted from, with all type parameters
+    /// substituted for an arbitrary representative. Not to be shown
+    /// to the end user.
+    pub substituted_from: Ty<'tcx>,
+
+    /// The type being transmuted to, with all type parameters
+    /// substituted for an arbitrary representative. Not to be shown
+    /// to the end user.
+    pub substituted_to: Ty<'tcx>,
+
+    /// NodeId of the transmute intrinsic.
     pub id: ast::NodeId,
 }
 
@@ -623,6 +639,24 @@ impl<'tcx> CtxtArenas<'tcx> {
     }
 }
 
+pub struct CommonTypes<'tcx> {
+    pub bool: Ty<'tcx>,
+    pub char: Ty<'tcx>,
+    pub int: Ty<'tcx>,
+    pub i8: Ty<'tcx>,
+    pub i16: Ty<'tcx>,
+    pub i32: Ty<'tcx>,
+    pub i64: Ty<'tcx>,
+    pub uint: Ty<'tcx>,
+    pub u8: Ty<'tcx>,
+    pub u16: Ty<'tcx>,
+    pub u32: Ty<'tcx>,
+    pub u64: Ty<'tcx>,
+    pub f32: Ty<'tcx>,
+    pub f64: Ty<'tcx>,
+    pub err: Ty<'tcx>,
+}
+
 /// The data structure to keep track of all the information that typechecker
 /// generates so that so that it can be reused and doesn't have to be redone
 /// later on.
@@ -635,11 +669,15 @@ pub struct ctxt<'tcx> {
     // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
     // queried from a HashSet.
     interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
+
     // FIXME as above, use a hashset if equivalent elements can be queried.
     substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
     bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
     region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
 
+    /// Common types, pre-interned for your convenience.
+    pub types: CommonTypes<'tcx>,
+
     pub sess: Session,
     pub def_map: DefMap,
 
@@ -679,10 +717,9 @@ pub struct ctxt<'tcx> {
     pub map: ast_map::Map<'tcx>,
     pub intrinsic_defs: RefCell<DefIdMap<Ty<'tcx>>>,
     pub freevars: RefCell<FreevarMap>,
-    pub tcache: RefCell<DefIdMap<Polytype<'tcx>>>,
+    pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
     pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
     pub short_names_cache: RefCell<FnvHashMap<Ty<'tcx>, String>>,
-    pub needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
     pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
     pub ast_ty_to_ty_cache: RefCell<NodeMap<ast_ty_to_ty_cache_entry<'tcx>>>,
     pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>,
@@ -781,8 +818,15 @@ pub struct ctxt<'tcx> {
     /// Caches the representation hints for struct definitions.
     pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
 
-    /// Caches whether types move by default.
-    pub type_moves_by_default_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
+    /// Caches whether types are known to impl Copy. Note that type
+    /// parameters are never placed into this cache, because their
+    /// results are dependent on the parameter environment.
+    pub type_impls_copy_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
+
+    /// Caches whether types are known to impl Sized. Note that type
+    /// parameters are never placed into this cache, because their
+    /// results are dependent on the parameter environment.
+    pub type_impls_sized_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
 }
 
 // Flags that we track on types. These flags are propagated upwards
@@ -799,6 +843,7 @@ bitflags! {
         const HAS_RE_LATE_BOUND   = 0b10000,
         const HAS_REGIONS         = 0b100000,
         const HAS_TY_ERR          = 0b1000000,
+        const HAS_PROJECTION      = 0b10000000,
         const NEEDS_SUBST   = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits,
     }
 }
@@ -869,7 +914,7 @@ impl<'tcx> ctxt<'tcx> {
         sty_debug_print!(
             self,
             ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_closure, ty_trait,
-            ty_struct, ty_unboxed_closure, ty_tup, ty_param, ty_open, ty_infer);
+            ty_struct, ty_unboxed_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection);
 
         println!("Substs interner: #{}", self.substs_interner.borrow().len());
         println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
@@ -945,6 +990,9 @@ pub fn type_has_ty_infer(ty: Ty) -> bool {
 pub fn type_needs_infer(ty: Ty) -> bool {
     ty.flags.intersects(HAS_TY_INFER | HAS_RE_INFER)
 }
+pub fn type_has_projection(ty: Ty) -> bool {
+    ty.flags.intersects(HAS_PROJECTION)
+}
 
 pub fn type_has_late_bound_regions(ty: Ty) -> bool {
     ty.flags.intersects(HAS_RE_LATE_BOUND)
@@ -992,7 +1040,7 @@ pub struct ClosureTy<'tcx> {
     pub unsafety: ast::Unsafety,
     pub onceness: ast::Onceness,
     pub store: TraitStore,
-    pub bounds: ExistentialBounds,
+    pub bounds: ExistentialBounds<'tcx>,
     pub sig: PolyFnSig<'tcx>,
     pub abi: abi::Abi,
 }
@@ -1031,7 +1079,7 @@ pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>;
 pub struct ParamTy {
     pub space: subst::ParamSpace,
     pub idx: u32,
-    pub def_id: DefId
+    pub name: ast::Name,
 }
 
 /// A [De Bruijn index][dbi] is a standard means of representing
@@ -1275,54 +1323,6 @@ pub enum BoundRegion {
     BrEnv
 }
 
-#[inline]
-pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> {
-    // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
-    unsafe { &*(primitive as *const _ as *const TyS<'tcx>) }
-}
-
-// Do not change these from static to const, interning types requires
-// the primitives to have a significant address.
-macro_rules! def_prim_tys {
-    ($($name:ident -> $sty:expr;)*) => (
-        $(#[inline] pub fn $name<'tcx>() -> Ty<'tcx> {
-            static PRIM_TY: TyS<'static> = TyS {
-                sty: $sty,
-                flags: NO_TYPE_FLAGS,
-                region_depth: 0,
-            };
-            mk_prim_t(&PRIM_TY)
-        })*
-    )
-}
-
-def_prim_tys!{
-    mk_bool ->  ty_bool;
-    mk_char ->  ty_char;
-    mk_int ->   ty_int(ast::TyI);
-    mk_i8 ->    ty_int(ast::TyI8);
-    mk_i16 ->   ty_int(ast::TyI16);
-    mk_i32 ->   ty_int(ast::TyI32);
-    mk_i64 ->   ty_int(ast::TyI64);
-    mk_uint ->  ty_uint(ast::TyU);
-    mk_u8 ->    ty_uint(ast::TyU8);
-    mk_u16 ->   ty_uint(ast::TyU16);
-    mk_u32 ->   ty_uint(ast::TyU32);
-    mk_u64 ->   ty_uint(ast::TyU64);
-    mk_f32 ->   ty_float(ast::TyF32);
-    mk_f64 ->   ty_float(ast::TyF64);
-}
-
-#[inline]
-pub fn mk_err<'tcx>() -> Ty<'tcx> {
-    static TY_ERR: TyS<'static> = TyS {
-        sty: ty_err,
-        flags: HAS_TY_ERR,
-        region_depth: 0,
-    };
-    mk_prim_t(&TY_ERR)
-}
-
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
@@ -1358,7 +1358,9 @@ pub enum sty<'tcx> {
 
     ty_tup(Vec<Ty<'tcx>>),
 
+    ty_projection(ProjectionTy<'tcx>),
     ty_param(ParamTy), // type parameter
+
     ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value
                        // and its size. Only ever used in trans. It is not necessary
                        // earlier since we don't need to distinguish a DST with its
@@ -1373,25 +1375,59 @@ pub enum sty<'tcx> {
 
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct TyTrait<'tcx> {
-    // Principal trait reference.
-    pub principal: PolyTraitRef<'tcx>,
-    pub bounds: ExistentialBounds
+    pub principal: ty::PolyTraitRef<'tcx>,
+    pub bounds: ExistentialBounds<'tcx>,
 }
 
 impl<'tcx> TyTrait<'tcx> {
+    pub fn principal_def_id(&self) -> ast::DefId {
+        self.principal.0.def_id
+    }
+
     /// Object types don't have a self-type specified. Therefore, when
     /// we convert the principal trait-ref into a normal trait-ref,
     /// you must give *some* self-type. A common choice is `mk_err()`
     /// or some skolemized type.
     pub fn principal_trait_ref_with_self_ty(&self,
-                                            tcx: &ctxt<'tcx>, self_ty: Ty<'tcx>)
-                                            -> Rc<ty::PolyTraitRef<'tcx>>
+                                            tcx: &ctxt<'tcx>,
+                                            self_ty: Ty<'tcx>)
+                                            -> ty::PolyTraitRef<'tcx>
     {
-        Rc::new(ty::Binder(ty::TraitRef {
-            def_id: self.principal.def_id(),
-            substs: tcx.mk_substs(self.principal.substs().with_self_ty(self_ty)),
+        // otherwise the escaping regions would be captured by the binder
+        assert!(!self_ty.has_escaping_regions());
+
+        ty::Binder(Rc::new(ty::TraitRef {
+            def_id: self.principal.0.def_id,
+            substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)),
         }))
     }
+
+    pub fn projection_bounds_with_self_ty(&self,
+                                          tcx: &ctxt<'tcx>,
+                                          self_ty: Ty<'tcx>)
+                                          -> Vec<ty::PolyProjectionPredicate<'tcx>>
+    {
+        // otherwise the escaping regions would be captured by the binders
+        assert!(!self_ty.has_escaping_regions());
+
+        self.bounds.projection_bounds.iter()
+            .map(|in_poly_projection_predicate| {
+                let in_projection_ty = &in_poly_projection_predicate.0.projection_ty;
+                let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty));
+                let trait_ref =
+                    Rc::new(ty::TraitRef::new(in_projection_ty.trait_ref.def_id,
+                                              substs));
+                let projection_ty = ty::ProjectionTy {
+                    trait_ref: trait_ref,
+                    item_name: in_projection_ty.item_name
+                };
+                ty::Binder(ty::ProjectionPredicate {
+                    projection_ty: projection_ty,
+                    ty: in_poly_projection_predicate.0.ty
+                })
+            })
+            .collect()
+    }
 }
 
 /// A complete reference to a trait. These take numerous guises in syntax,
@@ -1415,7 +1451,7 @@ pub struct TraitRef<'tcx> {
     pub substs: &'tcx Substs<'tcx>,
 }
 
-pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;
+pub type PolyTraitRef<'tcx> = Binder<Rc<TraitRef<'tcx>>>;
 
 impl<'tcx> PolyTraitRef<'tcx> {
     pub fn self_ty(&self) -> Ty<'tcx> {
@@ -1433,6 +1469,11 @@ impl<'tcx> PolyTraitRef<'tcx> {
     pub fn input_types(&self) -> &[Ty<'tcx>] {
         self.0.input_types()
     }
+
+    pub fn to_poly_trait_predicate(&self) -> PolyTraitPredicate<'tcx> {
+        // Note that we preserve binding levels
+        Binder(TraitPredicate { trait_ref: self.0.clone() })
+    }
 }
 
 /// Binder is a binder for higher-ranked lifetimes. It is part of the
@@ -1496,7 +1537,9 @@ pub enum type_err<'tcx> {
     terr_builtin_bounds(expected_found<BuiltinBounds>),
     terr_variadic_mismatch(expected_found<bool>),
     terr_cyclic_ty,
-    terr_convergence_mismatch(expected_found<bool>)
+    terr_convergence_mismatch(expected_found<bool>),
+    terr_projection_name_mismatched(expected_found<ast::Name>),
+    terr_projection_bounds_length(expected_found<uint>),
 }
 
 /// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
@@ -1505,7 +1548,8 @@ pub enum type_err<'tcx> {
 pub struct ParamBounds<'tcx> {
     pub region_bounds: Vec<ty::Region>,
     pub builtin_bounds: BuiltinBounds,
-    pub trait_bounds: Vec<Rc<PolyTraitRef<'tcx>>>
+    pub trait_bounds: Vec<PolyTraitRef<'tcx>>,
+    pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
 }
 
 /// Bounds suitable for an existentially quantified type parameter
@@ -1513,10 +1557,11 @@ pub struct ParamBounds<'tcx> {
 /// major difference between this case and `ParamBounds` is that
 /// general purpose trait bounds are omitted and there must be
 /// *exactly one* region.
-#[deriving(Copy, PartialEq, Eq, Hash, Clone, Show)]
-pub struct ExistentialBounds {
+#[deriving(PartialEq, Eq, Hash, Clone, Show)]
+pub struct ExistentialBounds<'tcx> {
     pub region_bound: ty::Region,
-    pub builtin_bounds: BuiltinBounds
+    pub builtin_bounds: BuiltinBounds,
+    pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
 }
 
 pub type BuiltinBounds = EnumSet<BuiltinBound>;
@@ -1544,9 +1589,10 @@ pub fn all_builtin_bounds() -> BuiltinBounds {
 }
 
 /// An existential bound that does not implement any traits.
-pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds {
+pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> {
     ty::ExistentialBounds { region_bound: r,
-                            builtin_bounds: empty_builtin_bounds() }
+                            builtin_bounds: empty_builtin_bounds(),
+                            projection_bounds: Vec::new() }
 }
 
 impl CLike for BuiltinBound {
@@ -1595,6 +1641,14 @@ pub enum InferTy {
     FreshIntTy(u32),
 }
 
+#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)]
+pub enum UnconstrainedNumeric {
+    UnconstrainedFloat,
+    UnconstrainedInt,
+    Neither,
+}
+
+
 #[deriving(Clone, RustcEncodable, RustcDecodable, Eq, Hash, Show, Copy)]
 pub enum InferRegion {
     ReVar(RegionVid),
@@ -1676,7 +1730,6 @@ pub struct TypeParameterDef<'tcx> {
     pub def_id: ast::DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
-    pub associated_with: Option<ast::DefId>,
     pub bounds: ParamBounds<'tcx>,
     pub default: Option<Ty<'tcx>>,
 }
@@ -1735,7 +1788,7 @@ pub enum Predicate<'tcx> {
     /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
     /// would be the parameters in the `TypeSpace`.
-    Trait(Rc<PolyTraitRef<'tcx>>),
+    Trait(PolyTraitPredicate<'tcx>),
 
     /// where `T1 == T2`.
     Equate(PolyEquatePredicate<'tcx>),
@@ -1745,6 +1798,36 @@ pub enum Predicate<'tcx> {
 
     /// where T : 'a
     TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
+
+    /// where <T as TraitRef>::Name == X, approximately.
+    /// See `ProjectionPredicate` struct for details.
+    Projection(PolyProjectionPredicate<'tcx>),
+}
+
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
+pub struct TraitPredicate<'tcx> {
+    pub trait_ref: Rc<TraitRef<'tcx>>
+}
+pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
+
+impl<'tcx> TraitPredicate<'tcx> {
+    pub fn def_id(&self) -> ast::DefId {
+        self.trait_ref.def_id
+    }
+
+    pub fn input_types(&self) -> &[Ty<'tcx>] {
+        self.trait_ref.substs.types.as_slice()
+    }
+
+    pub fn self_ty(&self) -> Ty<'tcx> {
+        self.trait_ref.self_ty()
+    }
+}
+
+impl<'tcx> PolyTraitPredicate<'tcx> {
+    pub fn def_id(&self) -> ast::DefId {
+        self.0.def_id()
+    }
 }
 
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
@@ -1757,13 +1840,98 @@ pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
 pub type PolyRegionOutlivesPredicate = PolyOutlivesPredicate<ty::Region, ty::Region>;
 pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region>;
 
+/// This kind of predicate has no *direct* correspondent in the
+/// syntax, but it roughly corresponds to the syntactic forms:
+///
+/// 1. `T : TraitRef<..., Item=Type>`
+/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
+///
+/// In particular, form #1 is "desugared" to the combination of a
+/// normal trait predicate (`T : TraitRef<...>`) and one of these
+/// predicates. Form #2 is a broader form in that it also permits
+/// equality between arbitrary types. Processing an instance of Form
+/// #2 eventually yields one of these `ProjectionPredicate`
+/// instances to normalize the LHS.
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
+pub struct ProjectionPredicate<'tcx> {
+    pub projection_ty: ProjectionTy<'tcx>,
+    pub ty: Ty<'tcx>,
+}
+
+pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
+
+impl<'tcx> PolyProjectionPredicate<'tcx> {
+    pub fn sort_key(&self) -> (ast::DefId, ast::Name) {
+        self.0.projection_ty.sort_key()
+    }
+}
+
+/// Represents the projection of an associated type. In explicit UFCS
+/// form this would be written `<T as Trait<..>>::N`.
+#[deriving(Clone, PartialEq, Eq, Hash, Show)]
+pub struct ProjectionTy<'tcx> {
+    /// The trait reference `T as Trait<..>`.
+    pub trait_ref: Rc<ty::TraitRef<'tcx>>,
+
+    /// The name `N` of the associated type.
+    pub item_name: ast::Name,
+}
+
+impl<'tcx> ProjectionTy<'tcx> {
+    pub fn sort_key(&self) -> (ast::DefId, ast::Name) {
+        (self.trait_ref.def_id, self.item_name)
+    }
+}
+
+pub trait ToPolyTraitRef<'tcx> {
+    fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
+}
+
+impl<'tcx> ToPolyTraitRef<'tcx> for Rc<TraitRef<'tcx>> {
+    fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
+        assert!(!self.has_escaping_regions());
+        ty::Binder(self.clone())
+    }
+}
+
+impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
+    fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
+        // We are just preserving the binder levels here
+        ty::Binder(self.0.trait_ref.clone())
+    }
+}
+
+impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> {
+    fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
+        // Note: unlike with TraitRef::to_poly_trait_ref(),
+        // self.0.trait_ref is permitted to have escaping regions.
+        // This is because here `self` has a `Binder` and so does our
+        // return value, so we are preserving the number of binding
+        // levels.
+        ty::Binder(self.0.projection_ty.trait_ref.clone())
+    }
+}
+
 pub trait AsPredicate<'tcx> {
     fn as_predicate(&self) -> Predicate<'tcx>;
 }
 
-impl<'tcx> AsPredicate<'tcx> for Rc<PolyTraitRef<'tcx>> {
+impl<'tcx> AsPredicate<'tcx> for Rc<TraitRef<'tcx>> {
     fn as_predicate(&self) -> Predicate<'tcx> {
-        Predicate::Trait(self.clone())
+        // we're about to add a binder, so let's check that we don't
+        // accidentally capture anything, or else that might be some
+        // weird debruijn accounting.
+        assert!(!self.has_escaping_regions());
+
+        ty::Predicate::Trait(ty::Binder(ty::TraitPredicate {
+            trait_ref: self.clone()
+        }))
+    }
+}
+
+impl<'tcx> AsPredicate<'tcx> for PolyTraitRef<'tcx> {
+    fn as_predicate(&self) -> Predicate<'tcx> {
+        ty::Predicate::Trait(self.to_poly_trait_predicate())
     }
 }
 
@@ -1785,6 +1953,12 @@ impl<'tcx> AsPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
     }
 }
 
+impl<'tcx> AsPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
+    fn as_predicate(&self) -> Predicate<'tcx> {
+        Predicate::Projection(self.clone())
+    }
+}
+
 impl<'tcx> Predicate<'tcx> {
     pub fn has_escaping_regions(&self) -> bool {
         match *self {
@@ -1792,14 +1966,16 @@ impl<'tcx> Predicate<'tcx> {
             Predicate::Equate(ref p) => p.has_escaping_regions(),
             Predicate::RegionOutlives(ref p) => p.has_escaping_regions(),
             Predicate::TypeOutlives(ref p) => p.has_escaping_regions(),
+            Predicate::Projection(ref p) => p.has_escaping_regions(),
         }
     }
 
-    pub fn to_trait(&self) -> Option<Rc<PolyTraitRef<'tcx>>> {
+    pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> {
         match *self {
             Predicate::Trait(ref t) => {
-                Some(t.clone())
+                Some(t.to_poly_trait_ref())
             }
+            Predicate::Projection(..) |
             Predicate::Equate(..) |
             Predicate::RegionOutlives(..) |
             Predicate::TypeOutlives(..) => {
@@ -2007,18 +2183,29 @@ impl<'tcx> ParameterEnvironment<'tcx> {
     }
 }
 
-/// A polytype.
+/// A "type scheme", in ML terminology, is a type combined with some
+/// set of generic types that the type is, well, generic over. In Rust
+/// terms, it is the "type" of a fn item or struct -- this type will
+/// include various generic parameters that must be substituted when
+/// the item/struct is referenced. That is called converting the type
+/// scheme to a monotype.
 ///
 /// - `generics`: the set of type parameters and their bounds
 /// - `ty`: the base types, which may reference the parameters defined
 ///   in `generics`
+///
+/// Note that TypeSchemes are also sometimes called "polytypes" (and
+/// in fact this struct used to carry that name, so you may find some
+/// stray references in a comment or something). We try to reserve the
+/// "poly" prefix to refer to higher-ranked things, as in
+/// `PolyTraitRef`.
 #[deriving(Clone, Show)]
-pub struct Polytype<'tcx> {
+pub struct TypeScheme<'tcx> {
     pub generics: Generics<'tcx>,
     pub ty: Ty<'tcx>
 }
 
-/// As `Polytype` but for a trait ref.
+/// As `TypeScheme` but for a trait ref.
 pub struct TraitDef<'tcx> {
     pub unsafety: ast::Unsafety,
 
@@ -2031,7 +2218,12 @@ pub struct TraitDef<'tcx> {
 
     /// The "supertrait" bounds.
     pub bounds: ParamBounds<'tcx>,
+
     pub trait_ref: Rc<ty::TraitRef<'tcx>>,
+
+    /// A list of the associated types defined in this trait. Useful
+    /// for resolving `X::Foo` type markers.
+    pub associated_type_names: Vec<ast::Name>,
 }
 
 /// Records the substitutions used to translate the polytype for an
@@ -2075,6 +2267,48 @@ impl UnboxedClosureKind {
     }
 }
 
+pub trait UnboxedClosureTyper<'tcx> {
+    fn unboxed_closure_kind(&self,
+                            def_id: ast::DefId)
+                            -> ty::UnboxedClosureKind;
+
+    fn unboxed_closure_type(&self,
+                            def_id: ast::DefId,
+                            substs: &subst::Substs<'tcx>)
+                            -> ty::ClosureTy<'tcx>;
+
+    // Returns `None` if the upvar types cannot yet be definitively determined.
+    fn unboxed_closure_upvars(&self,
+                              def_id: ast::DefId,
+                              substs: &Substs<'tcx>)
+                              -> Option<Vec<UnboxedClosureUpvar<'tcx>>>;
+}
+
+impl<'tcx> CommonTypes<'tcx> {
+    fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
+           interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>)
+           -> CommonTypes<'tcx>
+    {
+        CommonTypes {
+            bool: intern_ty(arena, interner, ty_bool),
+            char: intern_ty(arena, interner, ty_char),
+            err: intern_ty(arena, interner, ty_err),
+            int: intern_ty(arena, interner, ty_int(ast::TyI)),
+            i8: intern_ty(arena, interner, ty_int(ast::TyI8)),
+            i16: intern_ty(arena, interner, ty_int(ast::TyI16)),
+            i32: intern_ty(arena, interner, ty_int(ast::TyI32)),
+            i64: intern_ty(arena, interner, ty_int(ast::TyI64)),
+            uint: intern_ty(arena, interner, ty_uint(ast::TyU)),
+            u8: intern_ty(arena, interner, ty_uint(ast::TyU8)),
+            u16: intern_ty(arena, interner, ty_uint(ast::TyU16)),
+            u32: intern_ty(arena, interner, ty_uint(ast::TyU32)),
+            u64: intern_ty(arena, interner, ty_uint(ast::TyU64)),
+            f32: intern_ty(arena, interner, ty_float(ast::TyF32)),
+            f64: intern_ty(arena, interner, ty_float(ast::TyF64)),
+        }
+    }
+}
+
 pub fn mk_ctxt<'tcx>(s: Session,
                      arenas: &'tcx CtxtArenas<'tcx>,
                      dm: DefMap,
@@ -2084,13 +2318,18 @@ pub fn mk_ctxt<'tcx>(s: Session,
                      capture_modes: RefCell<CaptureModeMap>,
                      region_maps: middle::region::RegionMaps,
                      lang_items: middle::lang_items::LanguageItems,
-                     stability: stability::Index) -> ctxt<'tcx> {
+                     stability: stability::Index) -> ctxt<'tcx>
+{
+    let mut interner = FnvHashMap::new();
+    let common_types = CommonTypes::new(&arenas.type_, &mut interner);
+
     ctxt {
         arenas: arenas,
-        interner: RefCell::new(FnvHashMap::new()),
+        interner: RefCell::new(interner),
         substs_interner: RefCell::new(FnvHashMap::new()),
         bare_fn_interner: RefCell::new(FnvHashMap::new()),
         region_interner: RefCell::new(FnvHashMap::new()),
+        types: common_types,
         named_region_map: named_region_map,
         item_variance_map: RefCell::new(DefIdMap::new()),
         variance_computed: Cell::new(false),
@@ -2108,7 +2347,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
         tcache: RefCell::new(DefIdMap::new()),
         rcache: RefCell::new(FnvHashMap::new()),
         short_names_cache: RefCell::new(FnvHashMap::new()),
-        needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()),
         tc_cache: RefCell::new(FnvHashMap::new()),
         ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
         enum_var_cache: RefCell::new(DefIdMap::new()),
@@ -2144,7 +2382,8 @@ pub fn mk_ctxt<'tcx>(s: Session,
         associated_types: RefCell::new(DefIdMap::new()),
         selection_cache: traits::SelectionCache::new(),
         repr_hint_cache: RefCell::new(DefIdMap::new()),
-        type_moves_by_default_cache: RefCell::new(HashMap::new()),
+        type_impls_copy_cache: RefCell::new(HashMap::new()),
+        type_impls_sized_cache: RefCell::new(HashMap::new()),
    }
 }
 
@@ -2185,31 +2424,32 @@ impl<'tcx> ctxt<'tcx> {
 // Interns a type/name combination, stores the resulting box in cx.interner,
 // and returns the box as cast to an unsafe ptr (see comments for Ty above).
 pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: sty<'tcx>) -> Ty<'tcx> {
-    // Check for primitive types.
-    match st {
-        ty_err => return mk_err(),
-        ty_bool => return mk_bool(),
-        ty_int(i) => return mk_mach_int(i),
-        ty_uint(u) => return mk_mach_uint(u),
-        ty_float(f) => return mk_mach_float(f),
-        ty_char => return mk_char(),
-        _ => {}
-    };
+    let mut interner = cx.interner.borrow_mut();
+    intern_ty(&cx.arenas.type_, &mut *interner, st)
+}
 
-    match cx.interner.borrow().get(&st) {
+fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
+                   interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
+                   st: sty<'tcx>)
+                   -> Ty<'tcx>
+{
+    match interner.get(&st) {
         Some(ty) => return *ty,
         _ => ()
     }
 
     let flags = FlagComputation::for_sty(&st);
 
-    let ty = cx.arenas.type_.alloc(TyS {
+    let ty = type_arena.alloc(TyS {
         sty: st,
         flags: flags.flags,
         region_depth: flags.depth,
     });
 
-    cx.interner.borrow_mut().insert(InternedTy { ty: ty }, ty);
+    debug!("Interned type: {} Pointer: {}",
+           ty, ty as *const _);
+
+    interner.insert(InternedTy { ty: ty }, ty);
 
     ty
 }
@@ -2298,9 +2538,14 @@ impl FlagComputation {
                 self.add_substs(substs);
             }
 
+            &ty_projection(ref data) => {
+                self.add_flags(HAS_PROJECTION);
+                self.add_substs(data.trait_ref.substs);
+            }
+
             &ty_trait(box TyTrait { ref principal, ref bounds }) => {
                 let mut computation = FlagComputation::new();
-                computation.add_substs(principal.substs());
+                computation.add_substs(principal.0.substs);
                 self.add_bound_computation(&computation);
 
                 self.add_bounds(bounds);
@@ -2389,30 +2634,30 @@ impl FlagComputation {
     }
 }
 
-pub fn mk_mach_int<'tcx>(tm: ast::IntTy) -> Ty<'tcx> {
+pub fn mk_mach_int<'tcx>(tcx: &ctxt<'tcx>, tm: ast::IntTy) -> Ty<'tcx> {
     match tm {
-        ast::TyI    => mk_int(),
-        ast::TyI8   => mk_i8(),
-        ast::TyI16  => mk_i16(),
-        ast::TyI32  => mk_i32(),
-        ast::TyI64  => mk_i64(),
+        ast::TyI    => tcx.types.int,
+        ast::TyI8   => tcx.types.i8,
+        ast::TyI16  => tcx.types.i16,
+        ast::TyI32  => tcx.types.i32,
+        ast::TyI64  => tcx.types.i64,
     }
 }
 
-pub fn mk_mach_uint<'tcx>(tm: ast::UintTy) -> Ty<'tcx> {
+pub fn mk_mach_uint<'tcx>(tcx: &ctxt<'tcx>, tm: ast::UintTy) -> Ty<'tcx> {
     match tm {
-        ast::TyU    => mk_uint(),
-        ast::TyU8   => mk_u8(),
-        ast::TyU16  => mk_u16(),
-        ast::TyU32  => mk_u32(),
-        ast::TyU64  => mk_u64(),
+        ast::TyU    => tcx.types.uint,
+        ast::TyU8   => tcx.types.u8,
+        ast::TyU16  => tcx.types.u16,
+        ast::TyU32  => tcx.types.u32,
+        ast::TyU64  => tcx.types.u64,
     }
 }
 
-pub fn mk_mach_float<'tcx>(tm: ast::FloatTy) -> Ty<'tcx> {
+pub fn mk_mach_float<'tcx>(tcx: &ctxt<'tcx>, tm: ast::FloatTy) -> Ty<'tcx> {
     match tm {
-        ast::TyF32  => mk_f32(),
-        ast::TyF64  => mk_f64(),
+        ast::TyF32  => tcx.types.f32,
+        ast::TyF64  => tcx.types.f64,
     }
 }
 
@@ -2508,12 +2753,13 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
                 }))
 }
 
-
 pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
                       principal: ty::PolyTraitRef<'tcx>,
-                      bounds: ExistentialBounds)
-                      -> Ty<'tcx> {
-    // take a copy of substs so that we own the vectors inside
+                      bounds: ExistentialBounds<'tcx>)
+                      -> Ty<'tcx>
+{
+    assert!(bound_list_is_sorted(bounds.projection_bounds.as_slice()));
+
     let inner = box TyTrait {
         principal: principal,
         bounds: bounds
@@ -2521,6 +2767,25 @@ pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
     mk_t(cx, ty_trait(inner))
 }
 
+fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
+    bounds.len() == 0 ||
+        bounds[1..].iter().enumerate().all(
+            |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
+}
+
+pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) {
+    bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()))
+}
+
+pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>,
+                           trait_ref: Rc<ty::TraitRef<'tcx>>,
+                           item_name: ast::Name)
+                           -> Ty<'tcx> {
+    // take a copy of substs so that we own the vectors inside
+    let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
+    mk_t(cx, ty_projection(inner))
+}
+
 pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId,
                        substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
     // take a copy of substs so that we own the vectors inside
@@ -2549,17 +2814,19 @@ pub fn mk_infer<'tcx>(cx: &ctxt<'tcx>, it: InferTy) -> Ty<'tcx> {
     mk_t(cx, ty_infer(it))
 }
 
-pub fn mk_param<'tcx>(cx: &ctxt<'tcx>, space: subst::ParamSpace,
-                      n: u32, k: DefId) -> Ty<'tcx> {
-    mk_t(cx, ty_param(ParamTy { space: space, idx: n, def_id: k }))
+pub fn mk_param<'tcx>(cx: &ctxt<'tcx>,
+                      space: subst::ParamSpace,
+                      index: u32,
+                      name: ast::Name) -> Ty<'tcx> {
+    mk_t(cx, ty_param(ParamTy { space: space, idx: index, name: name }))
 }
 
-pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) -> Ty<'tcx> {
-    mk_param(cx, subst::SelfSpace, 0, did)
+pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
+    mk_param(cx, subst::SelfSpace, 0, special_idents::type_self.name)
 }
 
 pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'tcx> {
-    mk_param(cx, def.space, def.index, def.def_id)
+    mk_param(cx, def.space, def.index, def.name)
 }
 
 pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
@@ -2570,44 +2837,53 @@ pub fn walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where
     maybe_walk_ty(ty, |ty| { f(ty); true });
 }
 
-// FIXME(#19596) unbox `f`
-pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) {
-    if !f(ty) {
-        return;
-    }
-    match ty.sty {
-        ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
-        ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
-        ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
-        ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
-            maybe_walk_ty(tm.ty, f);
+pub fn maybe_walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where F: FnMut(Ty<'tcx>) -> bool {
+    // FIXME(#19596) This is a workaround, but there should be a better way to do this
+    fn maybe_walk_ty_<'tcx, F>(ty: Ty<'tcx>, f: &mut F) where F: FnMut(Ty<'tcx>) -> bool {
+        if !(*f)(ty) {
+            return;
         }
-        ty_trait(box TyTrait { ref principal, .. }) => {
-            for subty in principal.substs().types.iter() {
-                maybe_walk_ty(*subty, |x| f(x));
+        match ty.sty {
+            ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
+            ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
+            ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty_(ty, f),
+            ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
+                maybe_walk_ty_(tm.ty, f);
+            }
+            ty_trait(box TyTrait { ref principal, .. }) => {
+                for subty in principal.0.substs.types.iter() {
+                    maybe_walk_ty_(*subty, f);
+                }
             }
-        }
-        ty_enum(_, ref substs) |
-        ty_struct(_, ref substs) |
-        ty_unboxed_closure(_, _, ref substs) => {
-            for subty in substs.types.iter() {
-                maybe_walk_ty(*subty, |x| f(x));
+            ty_projection(ProjectionTy { ref trait_ref, .. }) => {
+                for subty in trait_ref.substs.types.iter() {
+                    maybe_walk_ty_(*subty, f);
+                }
             }
-        }
-        ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
-        ty_bare_fn(_, ref ft) => {
-            for a in ft.sig.0.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
-            if let ty::FnConverging(output) = ft.sig.0.output {
-                maybe_walk_ty(output, f);
+            ty_enum(_, ref substs) |
+            ty_struct(_, ref substs) |
+            ty_unboxed_closure(_, _, ref substs) => {
+                for subty in substs.types.iter() {
+                    maybe_walk_ty_(*subty, f);
+                }
             }
-        }
-        ty_closure(ref ft) => {
-            for a in ft.sig.0.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
-            if let ty::FnConverging(output) = ft.sig.0.output {
-                maybe_walk_ty(output, f);
+            ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty_(*tt, f); } }
+            ty_bare_fn(_, ref ft) => {
+                for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); }
+                if let ty::FnConverging(output) = ft.sig.0.output {
+                    maybe_walk_ty_(output, f);
+                }
+            }
+            ty_closure(ref ft) => {
+                for a in ft.sig.0.inputs.iter() { maybe_walk_ty_(*a, f); }
+                if let ty::FnConverging(output) = ft.sig.0.output {
+                    maybe_walk_ty_(output, f);
+                }
             }
         }
     }
+
+    maybe_walk_ty_(ty, &mut f);
 }
 
 // Folds types from the bottom up.
@@ -2623,21 +2899,21 @@ pub fn fold_ty<'tcx, F>(cx: &ctxt<'tcx>, t0: Ty<'tcx>,
 impl ParamTy {
     pub fn new(space: subst::ParamSpace,
                index: u32,
-               def_id: ast::DefId)
+               name: ast::Name)
                -> ParamTy {
-        ParamTy { space: space, idx: index, def_id: def_id }
+        ParamTy { space: space, idx: index, name: name }
     }
 
-    pub fn for_self(trait_def_id: ast::DefId) -> ParamTy {
-        ParamTy::new(subst::SelfSpace, 0, trait_def_id)
+    pub fn for_self() -> ParamTy {
+        ParamTy::new(subst::SelfSpace, 0, special_idents::type_self.name)
     }
 
     pub fn for_def(def: &TypeParameterDef) -> ParamTy {
-        ParamTy::new(def.space, def.index, def.def_id)
+        ParamTy::new(def.space, def.index, def.name)
     }
 
     pub fn to_ty<'tcx>(self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
-        ty::mk_param(tcx, self.space, self.idx, self.def_id)
+        ty::mk_param(tcx, self.space, self.idx, self.name)
     }
 
     pub fn is_self(&self) -> bool {
@@ -2661,6 +2937,7 @@ impl<'tcx> ParamBounds<'tcx> {
             builtin_bounds: empty_builtin_bounds(),
             trait_bounds: Vec::new(),
             region_bounds: Vec::new(),
+            projection_bounds: Vec::new(),
         }
     }
 }
@@ -2742,7 +3019,7 @@ pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool {
 pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
         ty_vec(ty, _) => ty,
-        ty_str => mk_mach_uint(ast::TyU8),
+        ty_str => mk_mach_uint(cx, ast::TyU8),
         ty_open(ty) => sequence_element_type(cx, ty),
         _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}",
                                  ty_to_string(cx, ty))[]),
@@ -2793,14 +3070,6 @@ pub fn type_is_unique(ty: Ty) -> bool {
     }
 }
 
-pub fn type_is_fat_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.sty {
-        ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..})
-        | ty_uniq(ty) if !type_is_sized(cx, ty) => true,
-        _ => false,
-    }
-}
-
 /*
  A scalar type is one that denotes an atomic datum, with no sub-components.
  (A ty_ptr is scalar because it represents a non-managed pointer, so its
@@ -2824,48 +3093,6 @@ pub fn type_is_floating_point(ty: Ty) -> bool {
     }
 }
 
-pub fn type_needs_drop<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    type_contents(cx, ty).needs_drop(cx)
-}
-
-// Some things don't need cleanups during unwinding because the
-// task can free them all at once later. Currently only things
-// that only contain scalars and shared boxes can avoid unwind
-// cleanups.
-pub fn type_needs_unwind_cleanup<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    return memoized(&cx.needs_unwind_cleanup_cache, ty, |ty| {
-        type_needs_unwind_cleanup_(cx, ty, &mut FnvHashSet::new())
-    });
-
-    fn type_needs_unwind_cleanup_<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>,
-                                        tycache: &mut FnvHashSet<Ty<'tcx>>) -> bool {
-        // Prevent infinite recursion
-        if !tycache.insert(ty) {
-            return false;
-        }
-
-        let mut needs_unwind_cleanup = false;
-        maybe_walk_ty(ty, |ty| {
-            needs_unwind_cleanup |= match ty.sty {
-                ty_bool | ty_int(_) | ty_uint(_) |
-                ty_float(_) | ty_tup(_) | ty_ptr(_) => false,
-
-                ty_enum(did, substs) =>
-                    enum_variants(cx, did).iter().any(|v|
-                        v.args.iter().any(|aty| {
-                            let t = aty.subst(cx, substs);
-                            type_needs_unwind_cleanup_(cx, t, tycache)
-                        })
-                    ),
-
-                _ => true
-            };
-            !needs_unwind_cleanup
-        });
-        needs_unwind_cleanup
-    }
-}
-
 /// Type contents is how the type checker reasons about kinds.
 /// They track what kinds of things are found within a type.  You can
 /// think of them as kind of an "anti-kind".  They track the kinds of values
@@ -2901,6 +3128,7 @@ def_type_content_sets! {
         // Things that are interior to the value (first nibble):
         InteriorUnsized                     = 0b0000_0000__0000_0000__0001,
         InteriorUnsafe                      = 0b0000_0000__0000_0000__0010,
+        InteriorParam                       = 0b0000_0000__0000_0000__0100,
         // InteriorAll                         = 0b00000000__00000000__1111,
 
         // Things that are owned by the value (second and third nibbles):
@@ -2955,6 +3183,10 @@ impl TypeContents {
         !self.intersects(TC::Nonsized)
     }
 
+    pub fn interior_param(&self) -> bool {
+        self.intersects(TC::InteriorParam)
+    }
+
     pub fn interior_unsafe(&self) -> bool {
         self.intersects(TC::InteriorUnsafe)
     }
@@ -3083,7 +3315,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
             }
 
             ty_closure(ref c) => {
-                closure_contents(cx, &**c) | TC::ReachesFfiUnsafe
+                closure_contents(&**c) | TC::ReachesFfiUnsafe
             }
 
             ty_uniq(typ) => {
@@ -3093,8 +3325,8 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
                 }
             }
 
-            ty_trait(box TyTrait { bounds, .. }) => {
-                object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
+            ty_trait(box TyTrait { ref bounds, .. }) => {
+                object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
             }
 
             ty_ptr(ref mt) => {
@@ -3138,7 +3370,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
             ty_unboxed_closure(did, r, substs) => {
                 // FIXME(#14449): `borrowed_contents` below assumes `&mut`
                 // unboxed closure.
-                let upvars = unboxed_closure_upvars(cx, did, substs);
+                let upvars = unboxed_closure_upvars(cx, did, substs).unwrap();
                 TypeContents::union(upvars.as_slice(),
                                     |f| tc_ty(cx, f.ty, cache))
                     | borrowed_contents(*r, MutMutable)
@@ -3204,26 +3436,8 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
                 apply_lang_items(cx, did, res)
             }
 
-            ty_param(p) => {
-                // We only ever ask for the kind of types that are defined in
-                // the current crate; therefore, the only type parameters that
-                // could be in scope are those defined in the current crate.
-                // If this assertion fails, it is likely because of a
-                // failure of the cross-crate inlining code to translate a
-                // def-id.
-                assert_eq!(p.def_id.krate, ast::LOCAL_CRATE);
-
-                let ty_param_defs = cx.ty_param_defs.borrow();
-                let tp_def = &(*ty_param_defs)[p.def_id.node];
-                kind_bounds_to_contents(
-                    cx,
-                    tp_def.bounds.builtin_bounds,
-                    tp_def.bounds.trait_bounds[])
-            }
-
-            ty_infer(_) => {
-                // This occurs during coherence, but shouldn't occur at other
-                // times.
+            ty_projection(..) |
+            ty_param(_) => {
                 TC::All
             }
 
@@ -3233,6 +3447,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
                 result.unsafe_pointer() | TC::Nonsized
             }
 
+            ty_infer(_) |
             ty_err => {
                 cx.sess.bug("asked to compute contents of error type");
             }
@@ -3272,10 +3487,10 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
         b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
     }
 
-    fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
+    fn closure_contents(cty: &ClosureTy) -> TypeContents {
         // Closure contents are just like trait contents, but with potentially
         // even more stuff.
-        let st = object_contents(cx, cty.bounds);
+        let st = object_contents(&cty.bounds);
 
         let st = match cty.store {
             UniqTraitStore => {
@@ -3289,61 +3504,37 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
         st
     }
 
-    fn object_contents(cx: &ctxt,
-                       bounds: ExistentialBounds)
-                       -> TypeContents {
-        // These are the type contents of the (opaque) interior
-        kind_bounds_to_contents(cx, bounds.builtin_bounds, &[])
-    }
-
-    fn kind_bounds_to_contents<'tcx>(cx: &ctxt<'tcx>,
-                                     bounds: BuiltinBounds,
-                                     traits: &[Rc<PolyTraitRef<'tcx>>])
-                                     -> TypeContents {
-        let _i = indenter();
-        let mut tc = TC::All;
-        each_inherited_builtin_bound(cx, bounds, traits, |bound| {
+    fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
+        // These are the type contents of the (opaque) interior. We
+        // make no assumptions (other than that it cannot have an
+        // in-scope type parameter within, which makes no sense).
+        let mut tc = TC::All - TC::InteriorParam;
+        for bound in bounds.builtin_bounds.iter() {
             tc = tc - match bound {
                 BoundSync | BoundSend | BoundCopy => TC::None,
                 BoundSized => TC::Nonsized,
             };
-        });
-        return tc;
-
-        // Iterates over all builtin bounds on the type parameter def, including
-        // those inherited from traits with builtin-kind-supertraits.
-        fn each_inherited_builtin_bound<'tcx, F>(cx: &ctxt<'tcx>,
-                                                 bounds: BuiltinBounds,
-                                                 traits: &[Rc<PolyTraitRef<'tcx>>],
-                                                 mut f: F) where
-            F: FnMut(BuiltinBound),
-        {
-            for bound in bounds.iter() {
-                f(bound);
-            }
-
-            each_bound_trait_and_supertraits(cx, traits, |trait_ref| {
-                let trait_def = lookup_trait_def(cx, trait_ref.def_id());
-                for bound in trait_def.bounds.builtin_bounds.iter() {
-                    f(bound);
-                }
-                true
-            });
         }
+        return tc;
     }
 }
 
-pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>,
-                                   ty: Ty<'tcx>,
-                                   param_env: &ParameterEnvironment<'tcx>)
-                                   -> bool
+fn type_impls_bound<'tcx>(cx: &ctxt<'tcx>,
+                          cache: &RefCell<HashMap<Ty<'tcx>,bool>>,
+                          param_env: &ParameterEnvironment<'tcx>,
+                          ty: Ty<'tcx>,
+                          bound: ty::BuiltinBound)
+                          -> bool
 {
+    assert!(!ty::type_needs_infer(ty));
+
     if !type_has_params(ty) && !type_has_self(ty) {
-        match cx.type_moves_by_default_cache.borrow().get(&ty) {
+        match cache.borrow().get(&ty) {
             None => {}
             Some(&result) => {
-                debug!("determined whether {} moves by default (cached): {}",
+                debug!("type_impls_bound({}, {}) = {} (cached)",
                        ty_to_string(cx, ty),
+                       bound,
                        result);
                 return result
             }
@@ -3351,27 +3542,35 @@ pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>,
     }
 
     let infcx = infer::new_infer_ctxt(cx);
-    let mut fulfill_cx = traits::FulfillmentContext::new();
+    let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound);
 
-    // we can use dummy values here because we won't report any errors
-    // that result nor will we pay any mind to region obligations that arise
-    // (there shouldn't really be any anyhow)
-    let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID);
+    debug!("type_impls_bound({}, {}) = {}",
+           ty_to_string(cx, ty),
+           bound,
+           is_impld);
 
-    fulfill_cx.register_builtin_bound(cx, ty, ty::BoundCopy, cause);
+    if !type_has_params(ty) && !type_has_self(ty) {
+        let old_value = cache.borrow_mut().insert(ty, is_impld);
+        assert!(old_value.is_none());
+    }
 
-    // Note: we only assuming something is `Copy` if we can
-    // *definitively* show that it implements `Copy`. Otherwise,
-    // assume it is move; linear is always ok.
-    let is_copy = fulfill_cx.select_all_or_error(&infcx, param_env, cx).is_ok();
-    let is_move = !is_copy;
+    is_impld
+}
 
-    debug!("determined whether {} moves by default: {}",
-           ty_to_string(cx, ty),
-           is_move);
+pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>,
+                                   ty: Ty<'tcx>,
+                                   param_env: &ParameterEnvironment<'tcx>)
+                                   -> bool
+{
+    !type_impls_bound(cx, &cx.type_impls_copy_cache, param_env, ty, ty::BoundCopy)
+}
 
-    cx.type_moves_by_default_cache.borrow_mut().insert(ty, is_move);
-    is_move
+pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>,
+                           ty: Ty<'tcx>,
+                           param_env: &ParameterEnvironment<'tcx>)
+                           -> bool
+{
+    type_impls_bound(cx, &cx.type_impls_sized_cache, param_env, ty, ty::BoundSized)
 }
 
 pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -3419,6 +3618,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
             ty_infer(_) |
             ty_err |
             ty_param(_) |
+            ty_projection(_) |
             ty_vec(_, None) => {
                 false
             }
@@ -3450,7 +3650,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
             }
 
             ty_unboxed_closure(did, _, substs) => {
-                let upvars = unboxed_closure_upvars(cx, did, substs);
+                let upvars = unboxed_closure_upvars(cx, did, substs).unwrap();
                 upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty))
             }
 
@@ -3542,7 +3742,7 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
                 find_nonrepresentable(cx, sp, seen, iter)
             }
             ty_unboxed_closure(did, _, substs) => {
-                let upvars = unboxed_closure_upvars(cx, did, substs);
+                let upvars = unboxed_closure_upvars(cx, did, substs).unwrap();
                 find_nonrepresentable(cx, sp, seen, upvars.iter().map(|f| f.ty))
             }
             _ => Representable,
@@ -3743,40 +3943,6 @@ pub fn type_is_machine(ty: Ty) -> bool {
     }
 }
 
-// Is the type's representation size known at compile time?
-pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    type_contents(cx, ty).is_sized(cx)
-}
-
-pub fn lltype_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.sty {
-        ty_open(_) => true,
-        _ => type_contents(cx, ty).is_sized(cx)
-    }
-}
-
-// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized.
-// 'Smallest' here means component of the static representation of the type; not
-// the size of an object at runtime.
-pub fn unsized_part_of_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        ty_str | ty_trait(..) | ty_vec(..) => ty,
-        ty_struct(def_id, substs) => {
-            let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
-                .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
-            // Exactly one of the fields must be unsized.
-            assert!(unsized_fields.len() == 1);
-
-            unsized_part_of_type(cx, unsized_fields[0])
-        }
-        _ => {
-            assert!(type_is_sized(cx, ty),
-                    "unsized_part_of_type failed even though ty is unsized");
-            panic!("called unsized_part_of_type with sized ty");
-        }
-    }
-}
-
 // Whether a type is enum like, that is an enum type with only nullary
 // constructors
 pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool {
@@ -3846,10 +4012,10 @@ pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
 // Returns the type of elements contained within an 'array-like' type.
 // This is exactly the same as the above, except it supports strings,
 // which can't actually be indexed.
-pub fn array_element_ty<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+pub fn array_element_ty<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     match ty.sty {
         ty_vec(ty, _) => Some(ty),
-        ty_str => Some(mk_u8()),
+        ty_str => Some(tcx.types.u8),
         _ => None
     }
 }
@@ -4138,6 +4304,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
                             let bounds = ty::ExistentialBounds {
                                 region_bound: ReStatic,
                                 builtin_bounds: all_builtin_bounds(),
+                                projection_bounds: vec!(),
                             };
 
                             ty::mk_closure(
@@ -4272,8 +4439,8 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
                                   format!("UnsizeStruct with bad sty: {}",
                                           ty_to_string(cx, ty))[])
         },
-        &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
-            mk_trait(cx, (*principal).clone(), bounds)
+        &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+            mk_trait(cx, principal.clone(), bounds.clone())
         }
     }
 }
@@ -4322,9 +4489,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             // the index method invoked for `a[i]` always yields an `&T`
             ast::ExprIndex(..) => LvalueExpr,
 
-            // the slice method invoked for `a[..]` always yields an `&T`
-            ast::ExprSlice(..) => LvalueExpr,
-
             // `for` loops are statements
             ast::ExprForLoop(..) => RvalueStmtExpr,
 
@@ -4389,8 +4553,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprUnary(ast::UnDeref, _) |
         ast::ExprField(..) |
         ast::ExprTupField(..) |
-        ast::ExprIndex(..) |
-        ast::ExprSlice(..) => {
+        ast::ExprIndex(..) => {
             LvalueExpr
         }
 
@@ -4533,7 +4696,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
         ty_bare_fn(None, _) => "fn pointer".to_string(),
         ty_closure(_) => "fn".to_string(),
         ty_trait(ref inner) => {
-            format!("trait {}", item_path_str(cx, inner.principal.def_id()))
+            format!("trait {}", item_path_str(cx, inner.principal_def_id()))
         }
         ty_struct(id, _) => {
             format!("struct {}", item_path_str(cx, id))
@@ -4545,6 +4708,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
         ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
         ty_infer(FreshTy(_)) => "skolemized type".to_string(),
         ty_infer(FreshIntTy(_)) => "skolemized integral type".to_string(),
+        ty_projection(_) => "associated type".to_string(),
         ty_param(ref p) => {
             if p.space == subst::SelfSpace {
                 "Self".to_string()
@@ -4557,6 +4721,12 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
     }
 }
 
+impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        ty::type_err_to_str(tcx, self)
+    }
+}
+
 /// Explains the source of a type err in a short, human readable way. This is meant to be placed
 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
 /// afterwards to present additional details, particularly when it comes to lifetime-related
@@ -4696,6 +4866,16 @@ pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String {
                     if values.expected { "converging" } else { "diverging" },
                     if values.found { "converging" } else { "diverging" })
         }
+        terr_projection_name_mismatched(ref values) => {
+            format!("expected {}, found {}",
+                    token::get_name(values.expected),
+                    token::get_name(values.found))
+        }
+        terr_projection_bounds_length(ref values) => {
+            format!("expected {} associated type bindings, found {}",
+                    values.expected,
+                    values.found)
+        }
     }
 }
 
@@ -4744,7 +4924,7 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
         match cx.map.find(id.node) {
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
-                    ItemTrait(_, _, _, _, ref ms) => {
+                    ItemTrait(_, _, _, ref ms) => {
                         let (_, p) =
                             ast_util::split_trait_methods(ms[]);
                         p.iter()
@@ -4956,7 +5136,7 @@ pub fn try_add_builtin_trait(
 pub fn ty_to_def_id(ty: Ty) -> Option<ast::DefId> {
     match ty.sty {
         ty_trait(ref tt) =>
-            Some(tt.principal.def_id()),
+            Some(tt.principal_def_id()),
         ty_struct(id, _) |
         ty_enum(id, _) |
         ty_unboxed_closure(id, _, _) =>
@@ -5197,7 +5377,7 @@ pub fn enum_variant_with_id<'tcx>(cx: &ctxt<'tcx>,
 // the type cache. Returns the type parameters and type.
 pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
                               did: ast::DefId)
-                              -> Polytype<'tcx> {
+                              -> TypeScheme<'tcx> {
     lookup_locally_or_in_crate_store(
         "tcache", did, &mut *cx.tcache.borrow_mut(),
         || csearch::get_type(cx, did))
@@ -5213,7 +5393,12 @@ pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
 }
 
 /// Given a reference to a trait, returns the "superbounds" declared
-/// on the trait, with appropriate substitutions applied.
+/// on the trait, with appropriate substitutions applied. Basically,
+/// this applies a filter to the where clauses on the trait, returning
+/// those that have the form:
+///
+///     Self : SuperTrait<...>
+///     Self : 'region
 pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>,
                                       trait_ref: &PolyTraitRef<'tcx>)
                                       -> Vec<ty::Predicate<'tcx>>
@@ -5290,17 +5475,18 @@ pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>,
     let trait_bounds: Vec<_> =
         trait_def.bounds.trait_bounds
         .iter()
-        .map(|bound_trait_ref| {
-            let substs = tcx.mk_substs(bound_trait_ref.substs().subst(tcx, trait_ref.substs()));
-            ty::Binder(
-                ty::TraitRef::new(bound_trait_ref.def_id(),
-                                  substs))
-        })
-        .map(|bound_trait_ref| Rc::new(bound_trait_ref))
+        .map(|poly_trait_ref| ty::Binder(poly_trait_ref.0.subst(tcx, trait_ref.substs())))
+        .collect();
+
+    let projection_bounds: Vec<_> =
+        trait_def.bounds.projection_bounds
+        .iter()
+        .map(|poly_proj| ty::Binder(poly_proj.0.subst(tcx, trait_ref.substs())))
         .collect();
 
-    debug!("bounds_for_trait_ref: trait_bounds={}",
-           trait_bounds.repr(tcx));
+    debug!("bounds_for_trait_ref: trait_bounds={} projection_bounds={}",
+           trait_bounds.repr(tcx),
+           projection_bounds.repr(tcx));
 
     // The region bounds and builtin bounds do not currently introduce
     // binders so we can just substitute in a straightforward way here.
@@ -5313,6 +5499,7 @@ pub fn predicates_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>,
         trait_bounds: trait_bounds,
         region_bounds: region_bounds,
         builtin_bounds: builtin_bounds,
+        projection_bounds: projection_bounds,
     };
 
     predicates(tcx, trait_ref.self_ty(), &bounds)
@@ -5327,7 +5514,7 @@ pub fn predicates<'tcx>(
     let mut vec = Vec::new();
 
     for builtin_bound in bounds.builtin_bounds.iter() {
-        match traits::poly_trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) {
+        match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) {
             Ok(trait_ref) => { vec.push(trait_ref.as_predicate()); }
             Err(ErrorReported) => { }
         }
@@ -5344,6 +5531,10 @@ pub fn predicates<'tcx>(
         vec.push(bound_trait_ref.as_predicate());
     }
 
+    for projection in bounds.projection_bounds.iter() {
+        vec.push(projection.as_predicate());
+    }
+
     vec
 }
 
@@ -5482,7 +5673,7 @@ pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
     }).collect()
 }
 
-#[deriving(Copy)]
+#[deriving(Copy, Clone)]
 pub struct UnboxedClosureUpvar<'tcx> {
     pub def: def::Def,
     pub span: Span,
@@ -5490,38 +5681,67 @@ pub struct UnboxedClosureUpvar<'tcx> {
 }
 
 // Returns a list of `UnboxedClosureUpvar`s for each upvar.
-pub fn unboxed_closure_upvars<'tcx>(tcx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>)
-                                    -> Vec<UnboxedClosureUpvar<'tcx>> {
+pub fn unboxed_closure_upvars<'tcx>(typer: &mc::Typer<'tcx>,
+                                    closure_id: ast::DefId,
+                                    substs: &Substs<'tcx>)
+                                    -> Option<Vec<UnboxedClosureUpvar<'tcx>>>
+{
     // Presently an unboxed closure type cannot "escape" out of a
     // function, so we will only encounter ones that originated in the
     // local crate or were inlined into it along with some function.
     // This may change if abstract return types of some sort are
     // implemented.
     assert!(closure_id.krate == ast::LOCAL_CRATE);
+    let tcx = typer.tcx();
     let capture_mode = tcx.capture_modes.borrow()[closure_id.node].clone();
     match tcx.freevars.borrow().get(&closure_id.node) {
-        None => vec![],
+        None => Some(vec![]),
         Some(ref freevars) => {
-            freevars.iter().map(|freevar| {
-                let freevar_def_id = freevar.def.def_id();
-                let freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
-                let mut freevar_ty = freevar_ty.subst(tcx, substs);
-                if capture_mode == ast::CaptureByRef {
-                    let borrow = tcx.upvar_borrow_map.borrow()[ty::UpvarId {
-                        var_id: freevar_def_id.node,
-                        closure_expr_id: closure_id.node
-                    }].clone();
-                    freevar_ty = mk_rptr(tcx, tcx.mk_region(borrow.region), ty::mt {
-                        ty: freevar_ty,
-                        mutbl: borrow.kind.to_mutbl_lossy()
-                    });
-                }
-                UnboxedClosureUpvar {
-                    def: freevar.def,
-                    span: freevar.span,
-                    ty: freevar_ty
-                }
-            }).collect()
+            freevars.iter()
+                    .map(|freevar| {
+                        let freevar_def_id = freevar.def.def_id();
+                        let freevar_ty = typer.node_ty(freevar_def_id.node);
+                        let freevar_ty = freevar_ty.subst(tcx, substs);
+
+                        match capture_mode {
+                            ast::CaptureByValue => {
+                                Some(UnboxedClosureUpvar { def: freevar.def,
+                                                           span: freevar.span,
+                                                           ty: freevar_ty })
+                            }
+
+                            ast::CaptureByRef => {
+                                let upvar_id = ty::UpvarId {
+                                    var_id: freevar_def_id.node,
+                                    closure_expr_id: closure_id.node
+                                };
+
+                                // FIXME
+                                let freevar_ref_ty = match typer.upvar_borrow(upvar_id) {
+                                    Some(borrow) => {
+                                        mk_rptr(tcx,
+                                                tcx.mk_region(borrow.region),
+                                                ty::mt {
+                                                    ty: freevar_ty,
+                                                    mutbl: borrow.kind.to_mutbl_lossy(),
+                                                })
+                                    }
+                                    None => {
+                                        // FIXME(#16640) we should really return None here;
+                                        // but that requires better inference integration,
+                                        // for now gin up something.
+                                        freevar_ty
+                                    }
+                                };
+                                Some(UnboxedClosureUpvar {
+                                    def: freevar.def,
+                                    span: freevar.span,
+                                    ty: freevar_ref_ty,
+                                })
+                            }
+                        }
+                    })
+                    .collect()
         }
     }
 }
@@ -5679,10 +5899,10 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
 // relation on the supertraits from each bounded trait's constraint
 // list.
 pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>,
-                                                 bounds: &[Rc<PolyTraitRef<'tcx>>],
+                                                 bounds: &[PolyTraitRef<'tcx>],
                                                  mut f: F)
                                                  -> bool where
-    F: FnMut(Rc<PolyTraitRef<'tcx>>) -> bool,
+    F: FnMut(PolyTraitRef<'tcx>) -> bool,
 {
     for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
         if !f(bound_trait_ref) {
@@ -5692,10 +5912,11 @@ pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>,
     return true;
 }
 
-pub fn object_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
-                                  opt_principal: Option<&PolyTraitRef<'tcx>>, // None for closures
-                                  others: BuiltinBounds)
-                                  -> Vec<ty::Region>
+pub fn object_region_bounds<'tcx>(
+    tcx: &ctxt<'tcx>,
+    opt_principal: Option<&PolyTraitRef<'tcx>>, // None for closures
+    others: BuiltinBounds)
+    -> Vec<ty::Region>
 {
     // Since we don't actually *know* the self type for an object,
     // this "open(err)" serves as a kind of dummy standin -- basically
@@ -5703,14 +5924,17 @@ pub fn object_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
     let open_ty = ty::mk_infer(tcx, FreshTy(0));
 
     let opt_trait_ref = opt_principal.map_or(Vec::new(), |principal| {
-        let substs = principal.substs().with_self_ty(open_ty);
-        vec!(Rc::new(ty::Binder(ty::TraitRef::new(principal.def_id(), tcx.mk_substs(substs)))))
+        // Note that we preserve the overall binding levels here.
+        assert!(!open_ty.has_escaping_regions());
+        let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
+        vec!(ty::Binder(Rc::new(ty::TraitRef::new(principal.0.def_id, substs))))
     });
 
     let param_bounds = ty::ParamBounds {
         region_bounds: Vec::new(),
         builtin_bounds: others,
         trait_bounds: opt_trait_ref,
+        projection_bounds: Vec::new(), // not relevant to computing region bounds
     };
 
     let predicates = ty::predicates(tcx, open_ty, &param_bounds);
@@ -5741,6 +5965,7 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
     traits::elaborate_predicates(tcx, predicates)
         .filter_map(|predicate| {
             match predicate {
+                ty::Predicate::Projection(..) |
                 ty::Predicate::Trait(..) |
                 ty::Predicate::Equate(..) |
                 ty::Predicate::RegionOutlives(..) => {
@@ -5988,7 +6213,7 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
         macro_rules! byte( ($b:expr) => { ($b as u8).hash(state) } );
         macro_rules! hash( ($e:expr) => { $e.hash(state) } );
 
-        let region = |state: &mut sip::SipState, r: Region| {
+        let region = |&: state: &mut sip::SipState, r: Region| {
             match r {
                 ReStatic => {}
                 ReLateBound(db, BrAnon(i)) => {
@@ -6005,7 +6230,7 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
                 }
             }
         };
-        let did = |state: &mut sip::SipState, did: DefId| {
+        let did = |&: state: &mut sip::SipState, did: DefId| {
             let h = if ast_util::is_local(did) {
                 svh.clone()
             } else {
@@ -6014,10 +6239,10 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
             h.as_str().hash(state);
             did.node.hash(state);
         };
-        let mt = |state: &mut sip::SipState, mt: mt| {
+        let mt = |&: state: &mut sip::SipState, mt: mt| {
             mt.mutbl.hash(state);
         };
-        let fn_sig = |state: &mut sip::SipState, sig: &Binder<FnSig<'tcx>>| {
+        let fn_sig = |&: state: &mut sip::SipState, sig: &Binder<FnSig<'tcx>>| {
             let sig = anonymize_late_bound_regions(tcx, sig);
             for a in sig.inputs.iter() { helper(tcx, *a, svh, state); }
             if let ty::FnConverging(output) = sig.output {
@@ -6092,12 +6317,12 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
 
                     return false;
                 }
-                ty_trait(box TyTrait { ref principal, bounds }) => {
+                ty_trait(ref data) => {
                     byte!(17);
-                    did(state, principal.def_id());
-                    hash!(bounds);
+                    did(state, data.principal_def_id());
+                    hash!(data.bounds);
 
-                    let principal = anonymize_late_bound_regions(tcx, principal);
+                    let principal = anonymize_late_bound_regions(tcx, &data.principal);
                     for subty in principal.substs.types.iter() {
                         helper(tcx, *subty, svh, state);
                     }
@@ -6114,8 +6339,9 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
                 }
                 ty_param(p) => {
                     byte!(20);
+                    hash!(p.space);
                     hash!(p.idx);
-                    did(state, p.def_id);
+                    hash!(token::get_name(p.name));
                 }
                 ty_open(_) => byte!(22),
                 ty_infer(_) => unreachable!(),
@@ -6125,6 +6351,11 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
                     did(state, d);
                     region(state, *r);
                 }
+                ty_projection(ref data) => {
+                    byte!(25);
+                    did(state, data.trait_ref.def_id);
+                    hash!(token::get_name(data.item_name));
+                }
             }
             true
         });
@@ -6165,17 +6396,11 @@ pub fn construct_parameter_environment<'tcx>(
 
     // map T => T
     let mut types = VecPerParamSpace::empty();
-    for &space in subst::ParamSpace::all().iter() {
-        push_types_from_defs(tcx, &mut types, space,
-                             generics.types.get_slice(space));
-    }
+    push_types_from_defs(tcx, &mut types, generics.types.as_slice());
 
     // map bound 'a => free 'a
     let mut regions = VecPerParamSpace::empty();
-    for &space in subst::ParamSpace::all().iter() {
-        push_region_params(&mut regions, space, free_id,
-                           generics.regions.get_slice(space));
-    }
+    push_region_params(&mut regions, free_id, generics.regions.as_slice());
 
     let free_substs = Substs {
         types: types,
@@ -6212,27 +6437,22 @@ pub fn construct_parameter_environment<'tcx>(
     };
 
     fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
-                          space: subst::ParamSpace,
                           free_id: ast::NodeId,
                           region_params: &[RegionParameterDef])
     {
         for r in region_params.iter() {
-            regions.push(space, ty::free_region_from_def(free_id, r));
+            regions.push(r.space, ty::free_region_from_def(free_id, r));
         }
     }
 
     fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                  types: &mut subst::VecPerParamSpace<Ty<'tcx>>,
-                                  space: subst::ParamSpace,
+                                  types: &mut VecPerParamSpace<Ty<'tcx>>,
                                   defs: &[TypeParameterDef<'tcx>]) {
-        for (i, def) in defs.iter().enumerate() {
-            debug!("construct_parameter_environment(): push_types_from_defs: \
-                    space={} def={} index={}",
-                   space,
-                   def.repr(tcx),
-                   i);
-            let ty = ty::mk_param(tcx, space, i as u32, def.def_id);
-            types.push(space, ty);
+        for def in defs.iter() {
+            debug!("construct_parameter_environment(): push_types_from_defs: def={}",
+                   def.repr(tcx));
+            let ty = ty::mk_param_from_def(tcx, def);
+            types.push(def.space, ty);
         }
     }
 
@@ -6241,7 +6461,10 @@ pub fn construct_parameter_environment<'tcx>(
 
         for predicate in bounds.predicates.iter() {
             match *predicate {
-                Predicate::Trait(..) | Predicate::Equate(..) | Predicate::TypeOutlives(..) => {
+                Predicate::Projection(..) |
+                Predicate::Trait(..) |
+                Predicate::Equate(..) |
+                Predicate::TypeOutlives(..) => {
                     // No region bounds here
                 }
                 Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
@@ -6332,21 +6555,42 @@ impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> {
         self.region_maps.temporary_scope(rvalue_id)
     }
 
-    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
-        self.upvar_borrow_map.borrow()[upvar_id].clone()
+    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
+        Some(self.upvar_borrow_map.borrow()[upvar_id].clone())
     }
 
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
                     -> ast::CaptureClause {
         self.capture_modes.borrow()[closure_expr_id].clone()
     }
+}
 
-    fn unboxed_closures<'a>(&'a self)
-                        -> &'a RefCell<DefIdMap<UnboxedClosure<'tcx>>> {
-        &self.unboxed_closures
+impl<'tcx> UnboxedClosureTyper<'tcx> for ty::ctxt<'tcx> {
+    fn unboxed_closure_kind(&self,
+                            def_id: ast::DefId)
+                            -> ty::UnboxedClosureKind
+    {
+        self.unboxed_closures.borrow()[def_id].kind
+    }
+
+    fn unboxed_closure_type(&self,
+                            def_id: ast::DefId,
+                            substs: &subst::Substs<'tcx>)
+                            -> ty::ClosureTy<'tcx>
+    {
+        self.unboxed_closures.borrow()[def_id].closure_type.subst(self, substs)
+    }
+
+    fn unboxed_closure_upvars(&self,
+                              def_id: ast::DefId,
+                              substs: &Substs<'tcx>)
+                              -> Option<Vec<UnboxedClosureUpvar<'tcx>>>
+    {
+        unboxed_closure_upvars(self, def_id, substs)
     }
 }
 
+
 /// The category of explicit self.
 #[deriving(Clone, Copy, Eq, PartialEq, Show)]
 pub enum ExplicitSelfCategory {
@@ -6368,7 +6612,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
                 accumulator.push(*region)
             }
             ty_trait(ref t) => {
-                accumulator.push_all(t.principal.substs().regions().as_slice());
+                accumulator.push_all(t.principal.0.substs.regions().as_slice());
             }
             ty_enum(_, substs) |
             ty_struct(_, substs) => {
@@ -6395,6 +6639,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
             ty_ptr(_) |
             ty_bare_fn(..) |
             ty_tup(_) |
+            ty_projection(_) |
             ty_param(_) |
             ty_infer(_) |
             ty_open(_) |
@@ -6485,6 +6730,15 @@ pub fn count_late_bound_regions<'tcx, T>(
     skol_map.len()
 }
 
+pub fn binds_late_bound_regions<'tcx, T>(
+    tcx: &ty::ctxt<'tcx>,
+    value: &Binder<T>)
+    -> bool
+    where T : TypeFoldable<'tcx> + Repr<'tcx>
+{
+    count_late_bound_regions(tcx, value) > 0
+}
+
 /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
 /// method lookup and a few other places where precise region relationships are not required.
 pub fn erase_late_bound_regions<'tcx, T>(
@@ -6625,9 +6879,10 @@ impl<'tcx> Repr<'tcx> for ty::Predicate<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         match *self {
             Predicate::Trait(ref a) => a.repr(tcx),
-            Predicate::Equate(ref pair) => format!("Equate({})", pair.repr(tcx)),
-            Predicate::RegionOutlives(ref pair) => format!("Outlives({})", pair.repr(tcx)),
-            Predicate::TypeOutlives(ref pair) => format!("Outlives({})", pair.repr(tcx)),
+            Predicate::Equate(ref pair) => pair.repr(tcx),
+            Predicate::RegionOutlives(ref pair) => pair.repr(tcx),
+            Predicate::TypeOutlives(ref pair) => pair.repr(tcx),
+            Predicate::Projection(ref pair) => pair.repr(tcx),
         }
     }
 }
@@ -6723,6 +6978,11 @@ pub fn can_type_implement_copy<'tcx>(tcx: &ctxt<'tcx>,
     Ok(())
 }
 
+// FIXME(#20298) -- all of these types basically walk various
+// structures to test whether types/regions are reachable with various
+// properties. It should be possible to express them in terms of one
+// common "walker" trait or something.
+
 pub trait RegionEscape {
     fn has_escaping_regions(&self) -> bool {
         self.has_regions_escaping_depth(0)
@@ -6737,16 +6997,64 @@ impl<'tcx> RegionEscape for Ty<'tcx> {
     }
 }
 
+impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.iter_enumerated().any(|(space, _, t)| {
+            if space == subst::FnSpace {
+                t.has_regions_escaping_depth(depth+1)
+            } else {
+                t.has_regions_escaping_depth(depth)
+            }
+        })
+    }
+}
+
+impl<'tcx> RegionEscape for TypeScheme<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.ty.has_regions_escaping_depth(depth) ||
+            self.generics.has_regions_escaping_depth(depth)
+    }
+}
+
 impl RegionEscape for Region {
     fn has_regions_escaping_depth(&self, depth: u32) -> bool {
         self.escapes_depth(depth)
     }
 }
 
+impl<'tcx> RegionEscape for Generics<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.predicates.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for Predicate<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        match *self {
+            Predicate::Trait(ref data) => data.has_regions_escaping_depth(depth),
+            Predicate::Equate(ref data) => data.has_regions_escaping_depth(depth),
+            Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth),
+            Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth),
+            Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth),
+        }
+    }
+}
+
 impl<'tcx> RegionEscape for TraitRef<'tcx> {
     fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) &&
-            self.substs.regions().iter().any(|t| t.has_regions_escaping_depth(depth))
+        self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) ||
+            self.substs.regions.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for subst::RegionSubsts {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        match *self {
+            subst::ErasedRegions => false,
+            subst::NonerasedRegions(ref r) => {
+                r.iter().any(|t| t.has_regions_escaping_depth(depth))
+            }
+        }
     }
 }
 
@@ -6762,8 +7070,283 @@ impl<'tcx> RegionEscape for EquatePredicate<'tcx> {
     }
 }
 
+impl<'tcx> RegionEscape for TraitPredicate<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.trait_ref.has_regions_escaping_depth(depth)
+    }
+}
+
 impl<T:RegionEscape,U:RegionEscape> RegionEscape for OutlivesPredicate<T,U> {
     fn has_regions_escaping_depth(&self, depth: u32) -> bool {
         self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
     }
 }
+
+impl<'tcx> RegionEscape for ProjectionPredicate<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.projection_ty.has_regions_escaping_depth(depth) ||
+            self.ty.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> RegionEscape for ProjectionTy<'tcx> {
+    fn has_regions_escaping_depth(&self, depth: u32) -> bool {
+        self.trait_ref.has_regions_escaping_depth(depth)
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ty::ProjectionPredicate<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("ProjectionPredicate({}, {})",
+                self.projection_ty.repr(tcx),
+                self.ty.repr(tcx))
+    }
+}
+
+pub trait HasProjectionTypes {
+    fn has_projection_types(&self) -> bool;
+}
+
+impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for Vec<T> {
+    fn has_projection_types(&self) -> bool {
+        self.iter().any(|p| p.has_projection_types())
+    }
+}
+
+impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for VecPerParamSpace<T> {
+    fn has_projection_types(&self) -> bool {
+        self.iter().any(|p| p.has_projection_types())
+    }
+}
+
+impl<'tcx> HasProjectionTypes for ClosureTy<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.sig.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for UnboxedClosureUpvar<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.ty.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.predicates.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for Predicate<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        match *self {
+            Predicate::Trait(ref data) => data.has_projection_types(),
+            Predicate::Equate(ref data) => data.has_projection_types(),
+            Predicate::RegionOutlives(ref data) => data.has_projection_types(),
+            Predicate::TypeOutlives(ref data) => data.has_projection_types(),
+            Predicate::Projection(ref data) => data.has_projection_types(),
+        }
+    }
+}
+
+impl<'tcx> HasProjectionTypes for TraitPredicate<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.trait_ref.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for EquatePredicate<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.0.has_projection_types() || self.1.has_projection_types()
+    }
+}
+
+impl HasProjectionTypes for Region {
+    fn has_projection_types(&self) -> bool {
+        false
+    }
+}
+
+impl<T:HasProjectionTypes,U:HasProjectionTypes> HasProjectionTypes for OutlivesPredicate<T,U> {
+    fn has_projection_types(&self) -> bool {
+        self.0.has_projection_types() || self.1.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for ProjectionPredicate<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.projection_ty.has_projection_types() || self.ty.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for ProjectionTy<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.trait_ref.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for Ty<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        ty::type_has_projection(*self)
+    }
+}
+
+impl<'tcx> HasProjectionTypes for TraitRef<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.substs.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for subst::Substs<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.types.iter().any(|t| t.has_projection_types())
+    }
+}
+
+impl<'tcx,T> HasProjectionTypes for Option<T>
+    where T : HasProjectionTypes
+{
+    fn has_projection_types(&self) -> bool {
+        self.iter().any(|t| t.has_projection_types())
+    }
+}
+
+impl<'tcx,T> HasProjectionTypes for Rc<T>
+    where T : HasProjectionTypes
+{
+    fn has_projection_types(&self) -> bool {
+        (**self).has_projection_types()
+    }
+}
+
+impl<'tcx,T> HasProjectionTypes for Box<T>
+    where T : HasProjectionTypes
+{
+    fn has_projection_types(&self) -> bool {
+        (**self).has_projection_types()
+    }
+}
+
+impl<T> HasProjectionTypes for Binder<T>
+    where T : HasProjectionTypes
+{
+    fn has_projection_types(&self) -> bool {
+        self.0.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for FnOutput<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        match *self {
+            FnConverging(t) => t.has_projection_types(),
+            FnDiverging => false,
+        }
+    }
+}
+
+impl<'tcx> HasProjectionTypes for FnSig<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.inputs.iter().any(|t| t.has_projection_types()) ||
+            self.output.has_projection_types()
+    }
+}
+
+impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> {
+    fn has_projection_types(&self) -> bool {
+        self.sig.has_projection_types()
+    }
+}
+
+pub trait ReferencesError {
+    fn references_error(&self) -> bool;
+}
+
+impl<T:ReferencesError> ReferencesError for Binder<T> {
+    fn references_error(&self) -> bool {
+        self.0.references_error()
+    }
+}
+
+impl<T:ReferencesError> ReferencesError for Rc<T> {
+    fn references_error(&self) -> bool {
+        (&*self).references_error()
+    }
+}
+
+impl<'tcx> ReferencesError for TraitPredicate<'tcx> {
+    fn references_error(&self) -> bool {
+        self.trait_ref.references_error()
+    }
+}
+
+impl<'tcx> ReferencesError for ProjectionPredicate<'tcx> {
+    fn references_error(&self) -> bool {
+        self.projection_ty.trait_ref.references_error() || self.ty.references_error()
+    }
+}
+
+impl<'tcx> ReferencesError for TraitRef<'tcx> {
+    fn references_error(&self) -> bool {
+        self.input_types().iter().any(|t| t.references_error())
+    }
+}
+
+impl<'tcx> ReferencesError for Ty<'tcx> {
+    fn references_error(&self) -> bool {
+        type_is_error(*self)
+    }
+}
+
+impl<'tcx> ReferencesError for Predicate<'tcx> {
+    fn references_error(&self) -> bool {
+        match *self {
+            Predicate::Trait(ref data) => data.references_error(),
+            Predicate::Equate(ref data) => data.references_error(),
+            Predicate::RegionOutlives(ref data) => data.references_error(),
+            Predicate::TypeOutlives(ref data) => data.references_error(),
+            Predicate::Projection(ref data) => data.references_error(),
+        }
+    }
+}
+
+impl<A,B> ReferencesError for OutlivesPredicate<A,B>
+    where A : ReferencesError, B : ReferencesError
+{
+    fn references_error(&self) -> bool {
+        self.0.references_error() || self.1.references_error()
+    }
+}
+
+impl<'tcx> ReferencesError for EquatePredicate<'tcx>
+{
+    fn references_error(&self) -> bool {
+        self.0.references_error() || self.1.references_error()
+    }
+}
+
+impl ReferencesError for Region
+{
+    fn references_error(&self) -> bool {
+        false
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ClosureTy<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("ClosureTy({},{},{},{},{},{})",
+                self.unsafety,
+                self.onceness,
+                self.store,
+                self.bounds.repr(tcx),
+                self.sig.repr(tcx),
+                self.abi)
+    }
+}
+
+impl<'tcx> Repr<'tcx> for UnboxedClosureUpvar<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("UnboxedClosureUpvar({},{})",
+                self.def.repr(tcx),
+                self.ty.repr(tcx))
+    }
+}
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 782b464ed96..83d2f6fb0e6 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -121,8 +121,8 @@ pub trait TypeFolder<'tcx> {
         super_fold_trait_store(self, s)
     }
 
-    fn fold_existential_bounds(&mut self, s: ty::ExistentialBounds)
-                               -> ty::ExistentialBounds {
+    fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
+                               -> ty::ExistentialBounds<'tcx> {
         super_fold_existential_bounds(self, s)
     }
 
@@ -170,6 +170,13 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
     }
 }
 
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Box<T> {
+        let content: T = (**self).fold_with(folder);
+        box content
+    }
+}
+
 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
         self.iter().map(|t| t.fold_with(folder)).collect()
@@ -342,9 +349,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds {
-    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds {
-        folder.fold_existential_bounds(*self)
+impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
+        folder.fold_existential_bounds(self)
     }
 }
 
@@ -354,6 +361,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ParamBounds<'tcx> {
             region_bounds: self.region_bounds.fold_with(folder),
             builtin_bounds: self.builtin_bounds.fold_with(folder),
             trait_bounds: self.trait_bounds.fold_with(folder),
+            projection_bounds: self.projection_bounds.fold_with(folder),
         }
     }
 }
@@ -365,7 +373,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
             def_id: self.def_id,
             space: self.space,
             index: self.index,
-            associated_with: self.associated_with,
             bounds: self.bounds.fold_with(folder),
             default: self.default.fold_with(folder),
         }
@@ -405,6 +412,26 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
                 ty::Predicate::RegionOutlives(binder.fold_with(folder)),
             ty::Predicate::TypeOutlives(ref binder) =>
                 ty::Predicate::TypeOutlives(binder.fold_with(folder)),
+            ty::Predicate::Projection(ref binder) =>
+                ty::Predicate::Projection(binder.fold_with(folder)),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionPredicate<'tcx> {
+        ty::ProjectionPredicate {
+            projection_ty: self.projection_ty.fold_with(folder),
+            ty: self.ty.fold_with(folder),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionTy<'tcx> {
+        ty::ProjectionTy {
+            trait_ref: self.trait_ref.fold_with(folder),
+            item_name: self.item_name,
         }
     }
 }
@@ -422,7 +449,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnsizeKind<'tcx> {
         match *self {
             ty::UnsizeLength(len) => ty::UnsizeLength(len),
             ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n),
-            ty::UnsizeVtable(ty::TyTrait{ref principal, bounds}, self_ty) => {
+            ty::UnsizeVtable(ty::TyTrait{ref principal, ref bounds}, self_ty) => {
                 ty::UnsizeVtable(
                     ty::TyTrait {
                         principal: principal.fold_with(folder),
@@ -441,7 +468,7 @@ impl<'tcx,O> TypeFoldable<'tcx> for traits::Obligation<'tcx,O>
         traits::Obligation {
             cause: self.cause.clone(),
             recursion_depth: self.recursion_depth,
-            trait_ref: self.trait_ref.fold_with(folder),
+            predicate: self.predicate.fold_with(folder),
         }
     }
 }
@@ -474,20 +501,12 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
             traits::VtableFnPointer(ref d) => {
                 traits::VtableFnPointer(d.fold_with(folder))
             }
-            traits::VtableParam(ref p) => traits::VtableParam(p.fold_with(folder)),
+            traits::VtableParam => traits::VtableParam,
             traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
         }
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for traits::VtableParamData<'tcx> {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableParamData<'tcx> {
-        traits::VtableParamData {
-            bound: self.bound.fold_with(folder),
-        }
-    }
-}
-
 impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::EquatePredicate<'tcx> {
         ty::EquatePredicate(self.0.fold_with(folder),
@@ -495,6 +514,14 @@ impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitPredicate<'tcx> {
+        ty::TraitPredicate {
+            trait_ref: self.trait_ref.fold_with(folder)
+        }
+    }
+}
+
 impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
     where T : TypeFoldable<'tcx>,
           U : TypeFoldable<'tcx>,
@@ -505,6 +532,16 @@ impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnboxedClosureUpvar<'tcx> {
+        ty::UnboxedClosureUpvar {
+            def: self.def,
+            span: self.span,
+            ty: self.ty.fold_with(folder),
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // "super" routines: these are the default implementations for TypeFolder.
 //
@@ -530,9 +567,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
             let substs = substs.fold_with(this);
             ty::ty_enum(tid, this.tcx().mk_substs(substs))
         }
-        ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
+        ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
             ty::ty_trait(box ty::TyTrait {
-                principal: (*principal).fold_with(this),
+                principal: principal.fold_with(this),
                 bounds: bounds.fold_with(this),
             })
         }
@@ -544,7 +581,7 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
             ty::ty_bare_fn(opt_def_id, this.tcx().mk_bare_fn(bfn))
         }
         ty::ty_closure(ref f) => {
-            ty::ty_closure(box f.fold_with(this))
+            ty::ty_closure(f.fold_with(this))
         }
         ty::ty_rptr(r, ref tm) => {
             let r = r.fold_with(this);
@@ -559,6 +596,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
             let s = substs.fold_with(this);
             ty::ty_unboxed_closure(did, this.tcx().mk_region(r), this.tcx().mk_substs(s))
         }
+        ty::ty_projection(ref data) => {
+            ty::ty_projection(data.fold_with(this))
+        }
         ty::ty_bool | ty::ty_char | ty::ty_str |
         ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
         ty::ty_err | ty::ty_infer(_) |
@@ -655,12 +695,15 @@ pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
     }
 }
 
-pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
-                                                                bounds: ty::ExistentialBounds)
-                                                                -> ty::ExistentialBounds {
+pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
+    this: &mut T,
+    bounds: &ty::ExistentialBounds<'tcx>)
+    -> ty::ExistentialBounds<'tcx>
+{
     ty::ExistentialBounds {
         region_bound: bounds.region_bound.fold_with(this),
         builtin_bounds: bounds.builtin_bounds,
+        projection_bounds: bounds.projection_bounds.fold_with(this),
     }
 }
 
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 7ccb68f2a75..f6f46017f37 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -19,6 +19,7 @@ pub use self::OutputType::*;
 pub use self::DebugInfoLevel::*;
 
 use session::{early_error, Session};
+use session::search_paths::SearchPaths;
 
 use rustc_back::target::Target;
 use lint;
@@ -35,7 +36,6 @@ use syntax::parse::token::InternedString;
 use std::collections::HashMap;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use getopts;
-use std::cell::{RefCell};
 use std::fmt;
 
 use llvm;
@@ -86,7 +86,7 @@ pub struct Options {
     // This was mutable for rustpkg, which updates search paths based on the
     // parsed code. It remains mutable in case its replacements wants to use
     // this.
-    pub addl_lib_search_paths: RefCell<Vec<Path>>,
+    pub search_paths: SearchPaths,
     pub libs: Vec<(String, cstore::NativeLibraryKind)>,
     pub maybe_sysroot: Option<Path>,
     pub target_triple: String,
@@ -198,7 +198,7 @@ pub fn basic_options() -> Options {
         lint_opts: Vec::new(),
         describe_lints: false,
         output_types: Vec::new(),
-        addl_lib_search_paths: RefCell::new(Vec::new()),
+        search_paths: SearchPaths::new(),
         maybe_sysroot: None,
         target_triple: host_triple().to_string(),
         cfg: Vec::new(),
@@ -1011,9 +1011,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         }
     };
 
-    let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
-        Path::new(s[])
-    }).collect();
+    let mut search_paths = SearchPaths::new();
+    for s in matches.opt_strs("L").iter() {
+        search_paths.add_path(s[]);
+    }
 
     let libs = matches.opt_strs("l").into_iter().map(|s| {
         let mut parts = s.rsplitn(1, ':');
@@ -1113,7 +1114,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         lint_opts: lint_opts,
         describe_lints: describe_lints,
         output_types: output_types,
-        addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
+        search_paths: search_paths,
         maybe_sysroot: sysroot_opt,
         target_triple: target,
         cfg: cfg,
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 35c325bd764..86a3a6001f9 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -9,9 +9,10 @@
 // except according to those terms.
 
 
+use lint;
 use metadata::cstore::CStore;
 use metadata::filesearch;
-use lint;
+use session::search_paths::PathKind;
 use util::nodemap::NodeMap;
 
 use syntax::ast::NodeId;
@@ -28,6 +29,7 @@ use std::os;
 use std::cell::{Cell, RefCell};
 
 pub mod config;
+pub mod search_paths;
 
 // Represents the data associated with a compilation
 // session for a single crate.
@@ -212,16 +214,18 @@ impl Session {
                         .expect("missing sysroot and default_sysroot in Session")
         }
     }
-    pub fn target_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
+    pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
         filesearch::FileSearch::new(self.sysroot(),
                                     self.opts.target_triple[],
-                                    &self.opts.addl_lib_search_paths)
+                                    &self.opts.search_paths,
+                                    kind)
     }
-    pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
+    pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
         filesearch::FileSearch::new(
             self.sysroot(),
             config::host_triple(),
-            &self.opts.addl_lib_search_paths)
+            &self.opts.search_paths,
+            kind)
     }
 }
 
diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs
new file mode 100644
index 00000000000..8a6217a49f5
--- /dev/null
+++ b/src/librustc/session/search_paths.rs
@@ -0,0 +1,69 @@
+// 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::slice;
+
+#[deriving(Clone)]
+pub struct SearchPaths {
+    paths: Vec<(PathKind, Path)>,
+}
+
+pub struct Iter<'a> {
+    kind: PathKind,
+    iter: slice::Iter<'a, (PathKind, Path)>,
+}
+
+#[deriving(Eq, PartialEq, Clone, Copy)]
+pub enum PathKind {
+    Native,
+    Crate,
+    Dependency,
+    All,
+}
+
+impl SearchPaths {
+    pub fn new() -> SearchPaths {
+        SearchPaths { paths: Vec::new() }
+    }
+
+    pub fn add_path(&mut self, path: &str) {
+        let (kind, path) = if path.ends_with(":native") {
+            (PathKind::Native, path.slice_to(path.len() - ":native".len()))
+        } else if path.ends_with(":crate") {
+            (PathKind::Crate, path.slice_to(path.len() - ":crate".len()))
+        } else if path.ends_with(":dependency") {
+            (PathKind::Dependency,
+             path.slice_to(path.len() - ":dependency".len()))
+        } else if path.ends_with(":all") {
+            (PathKind::All, path.slice_to(path.len() - ":all".len()))
+        } else {
+            (PathKind::All, path)
+        };
+        self.paths.push((kind, Path::new(path)));
+    }
+
+    pub fn iter(&self, kind: PathKind) -> Iter {
+        Iter { kind: kind, iter: self.paths.iter() }
+    }
+}
+
+impl<'a> Iterator<&'a Path> for Iter<'a> {
+    fn next(&mut self) -> Option<&'a Path> {
+        loop {
+            match self.iter.next() {
+                Some(&(kind, ref p)) if self.kind == PathKind::All ||
+                                        kind == PathKind::All ||
+                                        kind == self.kind => return Some(p),
+                Some(..) => {}
+                None => return None,
+            }
+        }
+    }
+}
diff --git a/src/librustc/util/lev_distance.rs b/src/librustc/util/lev_distance.rs
index 24e98837444..e7c77b12499 100644
--- a/src/librustc/util/lev_distance.rs
+++ b/src/librustc/util/lev_distance.rs
@@ -14,7 +14,7 @@ pub fn lev_distance(me: &str, t: &str) -> uint {
     if me.is_empty() { return t.chars().count(); }
     if t.is_empty() { return me.chars().count(); }
 
-    let mut dcol = Vec::from_fn(t.len() + 1, |x| x);
+    let mut dcol: Vec<_> = range(0, t.len() + 1).collect();
     let mut t_last = 0;
 
     for (i, sc) in me.chars().enumerate() {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 3a383dd5a3b..9639af5ca1c 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -448,6 +448,12 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
                     bound_sep,
                     bound_str)
         }
+        ty::ty_projection(ref data) => {
+            format!("<{} as {}>::{}",
+                    data.trait_ref.self_ty().user_string(cx),
+                    data.trait_ref.user_string(cx),
+                    data.item_name.user_string(cx))
+        }
         ty_str => "str".to_string(),
         ty_unboxed_closure(ref did, _, substs) => {
             let unboxed_closures = cx.unboxed_closures.borrow();
@@ -695,10 +701,9 @@ impl<'tcx> Repr<'tcx> for subst::Substs<'tcx> {
 
 impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for subst::VecPerParamSpace<T> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("[{};{};{};{}]",
+        format!("[{};{};{}]",
                 self.get_slice(subst::TypeSpace).repr(tcx),
                 self.get_slice(subst::SelfSpace).repr(tcx),
-                self.get_slice(subst::AssocSpace).repr(tcx),
                 self.get_slice(subst::FnSpace).repr(tcx))
     }
 }
@@ -733,8 +738,8 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::ExistentialBounds {
-    fn repr(&self, tcx: &ctxt) -> String {
+impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         self.user_string(tcx)
     }
 }
@@ -929,9 +934,9 @@ impl<'tcx> Repr<'tcx> for ast::DefId {
     }
 }
 
-impl<'tcx> Repr<'tcx> for ty::Polytype<'tcx> {
+impl<'tcx> Repr<'tcx> for ty::TypeScheme<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("Polytype {{generics: {}, ty: {}}}",
+        format!("TypeScheme {{generics: {}, ty: {}}}",
                 self.generics.repr(tcx),
                 self.ty.repr(tcx))
     }
@@ -1136,8 +1141,8 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
     }
 }
 
-impl<'tcx> UserString<'tcx> for ty::ExistentialBounds {
-    fn user_string(&self, tcx: &ctxt) -> String {
+impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
+    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
         if self.builtin_bounds.contains(&ty::BoundSend) &&
             self.region_bound == ty::ReStatic
         { // Region bound is implied by builtin bounds:
@@ -1322,17 +1327,8 @@ impl<'tcx> Repr<'tcx> for ty::ExplicitSelfCategory {
 }
 
 impl<'tcx> UserString<'tcx> for ParamTy {
-    fn user_string(&self, tcx: &ctxt) -> String {
-        let id = self.idx;
-        let did = self.def_id;
-        let ident = match tcx.ty_param_defs.borrow().get(&did.node) {
-            Some(def) => token::get_name(def.name).get().to_string(),
-
-            // This can only happen when a type mismatch error happens and
-            // the actual type has more type parameters than the expected one.
-            None => format!("<generic #{}>", id),
-        };
-        ident
+    fn user_string(&self, _tcx: &ctxt) -> String {
+        format!("{}", token::get_name(self.name))
     }
 }
 
@@ -1408,17 +1404,55 @@ impl<'tcx> UserString<'tcx> for ty::EquatePredicate<'tcx> {
     }
 }
 
+impl<'tcx> Repr<'tcx> for ty::TraitPredicate<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("TraitPredicate({})",
+                self.trait_ref.repr(tcx))
+    }
+}
+
+impl<'tcx> UserString<'tcx> for ty::TraitPredicate<'tcx> {
+    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("{} : {}",
+                self.trait_ref.self_ty().user_string(tcx),
+                self.trait_ref.user_string(tcx))
+    }
+}
+
+impl<'tcx> UserString<'tcx> for ty::ProjectionPredicate<'tcx> {
+    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("{} == {}",
+                self.projection_ty.user_string(tcx),
+                self.ty.user_string(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.repr(tcx),
+                self.item_name.repr(tcx))
+    }
+}
+
+impl<'tcx> UserString<'tcx> for ty::ProjectionTy<'tcx> {
+    fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("<{} as {}>::{}",
+                self.trait_ref.self_ty().user_string(tcx),
+                self.trait_ref.user_string(tcx),
+                self.item_name.user_string(tcx))
+    }
+}
+
 impl<'tcx> UserString<'tcx> for ty::Predicate<'tcx> {
     fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
         match *self {
-            ty::Predicate::Trait(ref trait_ref) => {
-                format!("{} : {}",
-                        trait_ref.self_ty().user_string(tcx),
-                        trait_ref.user_string(tcx))
-            }
+            ty::Predicate::Trait(ref data) => data.user_string(tcx),
             ty::Predicate::Equate(ref predicate) => predicate.user_string(tcx),
             ty::Predicate::RegionOutlives(ref predicate) => predicate.user_string(tcx),
             ty::Predicate::TypeOutlives(ref predicate) => predicate.user_string(tcx),
+            ty::Predicate::Projection(ref predicate) => predicate.user_string(tcx),
         }
     }
 }
diff --git a/src/librustc_back/arm.rs b/src/librustc_back/arm.rs
index ea4d5c820f8..7e28cd699a1 100644
--- a/src/librustc_back/arm.rs
+++ b/src/librustc_back/arm.rs
@@ -26,7 +26,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsiOS => {
@@ -34,7 +34,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsWindows => {
@@ -42,7 +42,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsLinux => {
@@ -50,7 +50,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsAndroid => {
@@ -58,7 +58,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsFreebsd | abi::OsDragonfly => {
@@ -66,7 +66,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
         },
 
diff --git a/src/librustc_back/mips.rs b/src/librustc_back/mips.rs
index 322f001c31e..bc7732157ce 100644
--- a/src/librustc_back/mips.rs
+++ b/src/librustc_back/mips.rs
@@ -21,7 +21,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsiOS => {
@@ -29,7 +29,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsWindows => {
@@ -37,7 +37,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsLinux => {
@@ -45,7 +45,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsAndroid => {
@@ -53,7 +53,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsFreebsd | abi::OsDragonfly => {
@@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
         },
 
diff --git a/src/librustc_back/mipsel.rs b/src/librustc_back/mipsel.rs
index e7ce5b0a429..3eea0a0dba4 100644
--- a/src/librustc_back/mipsel.rs
+++ b/src/librustc_back/mipsel.rs
@@ -21,7 +21,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsiOS => {
@@ -29,7 +29,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsWindows => {
@@ -37,7 +37,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsLinux => {
@@ -45,7 +45,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsAndroid => {
@@ -53,7 +53,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
 
           abi::OsFreebsd | abi::OsDragonfly => {
@@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
                 -v64:64:64-v128:64:128\
-                -a0:0:64-n32".to_string()
+                -a:0:64-n32".to_string()
           }
         },
 
diff --git a/src/librustc_back/sha2.rs b/src/librustc_back/sha2.rs
index 074341ccff4..1e55f442fb9 100644
--- a/src/librustc_back/sha2.rs
+++ b/src/librustc_back/sha2.rs
@@ -14,7 +14,7 @@
 
 #![allow(deprecated)] // to_be32
 
-use std::iter::range_step;
+use std::iter::{range_step, repeat};
 use std::num::Int;
 use std::slice::bytes::{MutableByteVector, copy_memory};
 use serialize::hex::ToHex;
@@ -111,7 +111,7 @@ trait FixedBuffer {
 
 /// A FixedBuffer of 64 bytes useful for implementing Sha256 which has a 64 byte blocksize.
 struct FixedBuffer64 {
-    buffer: [u8, ..64],
+    buffer: [u8; 64],
     buffer_idx: uint,
 }
 
@@ -119,7 +119,7 @@ impl FixedBuffer64 {
     /// Create a new FixedBuffer64
     fn new() -> FixedBuffer64 {
         return FixedBuffer64 {
-            buffer: [0u8, ..64],
+            buffer: [0u8; 64],
             buffer_idx: 0
         };
     }
@@ -139,14 +139,14 @@ impl FixedBuffer for FixedBuffer64 {
             let buffer_remaining = size - self.buffer_idx;
             if input.len() >= buffer_remaining {
                     copy_memory(
-                        self.buffer[mut self.buffer_idx..size],
+                        self.buffer.slice_mut(self.buffer_idx, size),
                         input[..buffer_remaining]);
                 self.buffer_idx = 0;
                 func(&self.buffer);
                 i += buffer_remaining;
             } else {
                 copy_memory(
-                    self.buffer[mut self.buffer_idx..self.buffer_idx + input.len()],
+                    self.buffer.slice_mut(self.buffer_idx, self.buffer_idx + input.len()),
                     input);
                 self.buffer_idx += input.len();
                 return;
@@ -165,7 +165,7 @@ impl FixedBuffer for FixedBuffer64 {
         // be empty.
         let input_remaining = input.len() - i;
         copy_memory(
-            self.buffer[mut ..input_remaining],
+            self.buffer.slice_to_mut(input_remaining),
             input[i..]);
         self.buffer_idx += input_remaining;
     }
@@ -176,13 +176,13 @@ impl FixedBuffer for FixedBuffer64 {
 
     fn zero_until(&mut self, idx: uint) {
         assert!(idx >= self.buffer_idx);
-        self.buffer[mut self.buffer_idx..idx].set_memory(0);
+        self.buffer.slice_mut(self.buffer_idx, idx).set_memory(0);
         self.buffer_idx = idx;
     }
 
     fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8] {
         self.buffer_idx += len;
-        return self.buffer[mut self.buffer_idx - len..self.buffer_idx];
+        return self.buffer.slice_mut(self.buffer_idx - len, self.buffer_idx);
     }
 
     fn full_buffer<'s>(&'s mut self) -> &'s [u8] {
@@ -258,7 +258,7 @@ pub trait Digest {
     /// Convenience function that retrieves the result of a digest as a
     /// newly allocated vec of bytes.
     fn result_bytes(&mut self) -> Vec<u8> {
-        let mut buf = Vec::from_elem((self.output_bits()+7)/8, 0u8);
+        let mut buf: Vec<u8> = repeat(0u8).take((self.output_bits()+7)/8).collect();
         self.result(buf.as_mut_slice());
         buf
     }
@@ -284,7 +284,7 @@ struct Engine256State {
 }
 
 impl Engine256State {
-    fn new(h: &[u32, ..8]) -> Engine256State {
+    fn new(h: &[u32; 8]) -> Engine256State {
         return Engine256State {
             h0: h[0],
             h1: h[1],
@@ -297,7 +297,7 @@ impl Engine256State {
         };
     }
 
-    fn reset(&mut self, h: &[u32, ..8]) {
+    fn reset(&mut self, h: &[u32; 8]) {
         self.h0 = h[0];
         self.h1 = h[1];
         self.h2 = h[2];
@@ -342,7 +342,7 @@ impl Engine256State {
         let mut g = self.h6;
         let mut h = self.h7;
 
-        let mut w = [0u32, ..64];
+        let mut w = [0u32; 64];
 
         // Sha-512 and Sha-256 use basically the same calculations which are implemented
         // by these macros. Inlining the calculations seems to result in better generated code.
@@ -362,7 +362,7 @@ impl Engine256State {
              )
         );
 
-        read_u32v_be(w[mut 0..16], data);
+        read_u32v_be(w.slice_mut(0, 16), data);
 
         // Putting the message schedule inside the same loop as the round calculations allows for
         // the compiler to generate better code.
@@ -408,7 +408,7 @@ impl Engine256State {
     }
 }
 
-static K32: [u32, ..64] = [
+static K32: [u32; 64] = [
     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
     0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
@@ -437,7 +437,7 @@ struct Engine256 {
 }
 
 impl Engine256 {
-    fn new(h: &[u32, ..8]) -> Engine256 {
+    fn new(h: &[u32; 8]) -> Engine256 {
         return Engine256 {
             length_bits: 0,
             buffer: FixedBuffer64::new(),
@@ -446,7 +446,7 @@ impl Engine256 {
         }
     }
 
-    fn reset(&mut self, h: &[u32, ..8]) {
+    fn reset(&mut self, h: &[u32; 8]) {
         self.length_bits = 0;
         self.buffer.reset();
         self.state.reset(h);
@@ -498,14 +498,14 @@ impl Digest for Sha256 {
     fn result(&mut self, out: &mut [u8]) {
         self.engine.finish();
 
-        write_u32_be(out[mut 0..4], self.engine.state.h0);
-        write_u32_be(out[mut 4..8], self.engine.state.h1);
-        write_u32_be(out[mut 8..12], self.engine.state.h2);
-        write_u32_be(out[mut 12..16], self.engine.state.h3);
-        write_u32_be(out[mut 16..20], self.engine.state.h4);
-        write_u32_be(out[mut 20..24], self.engine.state.h5);
-        write_u32_be(out[mut 24..28], self.engine.state.h6);
-        write_u32_be(out[mut 28..32], self.engine.state.h7);
+        write_u32_be(out.slice_mut(0, 4), self.engine.state.h0);
+        write_u32_be(out.slice_mut(4, 8), self.engine.state.h1);
+        write_u32_be(out.slice_mut(8, 12), self.engine.state.h2);
+        write_u32_be(out.slice_mut(12, 16), self.engine.state.h3);
+        write_u32_be(out.slice_mut(16, 20), self.engine.state.h4);
+        write_u32_be(out.slice_mut(20, 24), self.engine.state.h5);
+        write_u32_be(out.slice_mut(24, 28), self.engine.state.h6);
+        write_u32_be(out.slice_mut(28, 32), self.engine.state.h7);
     }
 
     fn reset(&mut self) {
@@ -515,7 +515,7 @@ impl Digest for Sha256 {
     fn output_bits(&self) -> uint { 256 }
 }
 
-static H256: [u32, ..8] = [
+static H256: [u32; 8] = [
     0x6a09e667,
     0xbb67ae85,
     0x3c6ef372,
@@ -530,11 +530,12 @@ static H256: [u32, ..8] = [
 mod tests {
     extern crate rand;
 
-    use super::{Digest, Sha256, FixedBuffer};
-    use self::rand::isaac::IsaacRng;
     use self::rand::Rng;
+    use self::rand::isaac::IsaacRng;
     use serialize::hex::FromHex;
+    use std::iter::repeat;
     use std::num::Int;
+    use super::{Digest, Sha256, FixedBuffer};
 
     // A normal addition - no overflow occurs
     #[test]
@@ -612,7 +613,7 @@ mod tests {
     /// correct.
     fn test_digest_1million_random<D: Digest>(digest: &mut D, blocksize: uint, expected: &str) {
         let total_size = 1000000;
-        let buffer = Vec::from_elem(blocksize * 2, 'a' as u8);
+        let buffer: Vec<u8> = repeat('a' as u8).take(blocksize * 2).collect();
         let mut rng = IsaacRng::new_unseeded();
         let mut count = 0;
 
@@ -657,7 +658,7 @@ mod bench {
     #[bench]
     pub fn sha256_10(b: &mut Bencher) {
         let mut sh = Sha256::new();
-        let bytes = [1u8, ..10];
+        let bytes = [1u8; 10];
         b.iter(|| {
             sh.input(&bytes);
         });
@@ -667,7 +668,7 @@ mod bench {
     #[bench]
     pub fn sha256_1k(b: &mut Bencher) {
         let mut sh = Sha256::new();
-        let bytes = [1u8, ..1024];
+        let bytes = [1u8; 1024];
         b.iter(|| {
             sh.input(&bytes);
         });
@@ -677,7 +678,7 @@ mod bench {
     #[bench]
     pub fn sha256_64k(b: &mut Bencher) {
         let mut sh = Sha256::new();
-        let bytes = [1u8, ..65536];
+        let bytes = [1u8; 65536];
         b.iter(|| {
             sh.input(&bytes);
         });
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index c68e9055269..2374e8b340b 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -246,7 +246,6 @@ mod svh_visitor {
         SawExprAssign,
         SawExprAssignOp(ast::BinOp),
         SawExprIndex,
-        SawExprSlice,
         SawExprRange,
         SawExprPath,
         SawExprAddrOf(ast::Mutability),
@@ -280,7 +279,6 @@ mod svh_visitor {
             ExprField(_, id)         => SawExprField(content(id.node)),
             ExprTupField(_, id)      => SawExprTupField(id.node),
             ExprIndex(..)            => SawExprIndex,
-            ExprSlice(..)            => SawExprSlice,
             ExprRange(..)            => SawExprRange,
             ExprPath(..)             => SawExprPath,
             ExprAddrOf(m, _)         => SawExprAddrOf(m),
diff --git a/src/librustc_back/target/arm_apple_ios.rs b/src/librustc_back/target/arm_apple_ios.rs
index 8be98a51775..8bb64eae625 100644
--- a/src/librustc_back/target/arm_apple_ios.rs
+++ b/src/librustc_back/target/arm_apple_ios.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
                       -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                       -f32:32:32-f64:64:64\
                       -v64:64:64-v128:64:128\
-                      -a0:0:64-n32".to_string(),
+                      -a:0:64-n32".to_string(),
         llvm_target: "arm-apple-ios".to_string(),
         target_endian: "little".to_string(),
         target_word_size: "32".to_string(),
diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs
index 97bc747916d..0a5aa56055e 100644
--- a/src/librustc_back/target/arm_linux_androideabi.rs
+++ b/src/librustc_back/target/arm_linux_androideabi.rs
@@ -24,7 +24,7 @@ pub fn target() -> Target {
                       -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                       -f32:32:32-f64:64:64\
                       -v64:64:64-v128:64:128\
-                      -a0:0:64-n32".to_string(),
+                      -a:0:64-n32".to_string(),
         llvm_target: "arm-linux-androideabi".to_string(),
         target_endian: "little".to_string(),
         target_word_size: "32".to_string(),
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
index aecab188264..985af35e145 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
@@ -17,7 +17,7 @@ pub fn target() -> Target {
                       -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                       -f32:32:32-f64:64:64\
                       -v64:64:64-v128:64:128\
-                      -a0:0:64-n32".to_string(),
+                      -a:0:64-n32".to_string(),
         llvm_target: "arm-unknown-linux-gnueabi".to_string(),
         target_endian: "little".to_string(),
         target_word_size: "32".to_string(),
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
index 305862d357a..3cf0c312820 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
@@ -17,7 +17,7 @@ pub fn target() -> Target {
                       -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                       -f32:32:32-f64:64:64\
                       -v64:64:64-v128:64:128\
-                      -a0:0:64-n32".to_string(),
+                      -a:0:64-n32".to_string(),
         llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
         target_endian: "little".to_string(),
         target_word_size: "32".to_string(),
diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs
index fe336601a81..45669bc9585 100644
--- a/src/librustc_back/target/i386_apple_ios.rs
+++ b/src/librustc_back/target/i386_apple_ios.rs
@@ -15,7 +15,7 @@ pub fn target() -> Target {
         data_layout: "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
                       -i32:32:32-i64:32:64\
                       -f32:32:32-f64:32:64-v64:64:64\
-                      -v128:128:128-a0:0:64-f80:128:128\
+                      -v128:128:128-a:0:64-f80:128:128\
                       -n8:16:32".to_string(),
         llvm_target: "i386-apple-ios".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs
index bd3dd3246aa..feef5b98dcb 100644
--- a/src/librustc_back/target/i686_apple_darwin.rs
+++ b/src/librustc_back/target/i686_apple_darwin.rs
@@ -18,7 +18,7 @@ pub fn target() -> Target {
         data_layout: "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
                       -i32:32:32-i64:32:64\
                       -f32:32:32-f64:32:64-v64:64:64\
-                      -v128:128:128-a0:0:64-f80:128:128\
+                      -v128:128:128-a:0:64-f80:128:128\
                       -n8:16:32".to_string(),
         llvm_target: "i686-apple-darwin".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs
index 45e02ecb98c..c8c5ddcbd0d 100644
--- a/src/librustc_back/target/mips_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
                       -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                       -f32:32:32-f64:64:64\
                       -v64:64:64-v128:64:128\
-                      -a0:0:64-n32".to_string(),
+                      -a:0:64-n32".to_string(),
         llvm_target: "mips-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
         target_word_size: "32".to_string(),
diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
index 1ba99b167c3..3571f7b26c0 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
                       -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                       -f32:32:32-f64:64:64\
                       -v64:64:64-v128:64:128\
-                      -a0:0:64-n32".to_string(),
+                      -a:0:64-n32".to_string(),
         llvm_target: "mipsel-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_word_size: "32".to_string(),
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 99a25bebf40..fdc9b72f1e9 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -217,7 +217,7 @@ impl Target {
 
         let handler = diagnostic::default_handler(diagnostic::Auto, None);
 
-        let get_req_field = |name: &str| {
+        let get_req_field = |&: name: &str| {
             match obj.find(name)
                      .map(|s| s.as_string())
                      .and_then(|os| os.map(|s| s.to_string())) {
diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs
index 4e958d73a39..07e6cdfed2c 100644
--- a/src/librustc_back/target/x86_64_apple_darwin.rs
+++ b/src/librustc_back/target/x86_64_apple_darwin.rs
@@ -17,7 +17,7 @@ pub fn target() -> Target {
 
     Target {
         data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                       s0:64:64-f80:128:128-n8:16:32:64".to_string(),
         llvm_target: "x86_64-apple-darwin".to_string(),
         target_endian: "little".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 9247e1da0a5..6ca74eb7fc0 100644
--- a/src/librustc_back/target/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_back/target/x86_64_pc_windows_gnu.rs
@@ -19,7 +19,7 @@ pub fn target() -> Target {
     Target {
         // FIXME: Test this. Copied from linux (#2398)
         data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                       s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-pc-windows-gnu".to_string(),
         target_endian: "little".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 75dbff9428b..bff3eaf6bc8 100644
--- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
 
     Target {
         data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                     f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                     f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                      s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-unknown-dragonfly".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs
index 37801f3bf25..8d5603a3878 100644
--- a/src/librustc_back/target/x86_64_unknown_freebsd.rs
+++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
 
     Target {
         data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                     f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                     f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                      s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-unknown-freebsd".to_string(),
         target_endian: "little".to_string(),
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 ac04e6e14ba..e0a67cd6250 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
@@ -16,7 +16,7 @@ pub fn target() -> Target {
 
     Target {
         data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                       s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
         llvm_target: "x86_64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
diff --git a/src/librustc_back/x86.rs b/src/librustc_back/x86.rs
index 21c4fd42474..52c07165900 100644
--- a/src/librustc_back/x86.rs
+++ b/src/librustc_back/x86.rs
@@ -22,7 +22,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
             "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
                 -i32:32:32-i64:32:64\
                 -f32:32:32-f64:32:64-v64:64:64\
-                -v128:128:128-a0:0:64-f80:128:128\
+                -v128:128:128-a:0:64-f80:128:128\
                 -n8:16:32".to_string()
           }
 
@@ -30,7 +30,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
             "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
                 -i32:32:32-i64:32:64\
                 -f32:32:32-f64:32:64-v64:64:64\
-                -v128:128:128-a0:0:64-f80:128:128\
+                -v128:128:128-a:0:64-f80:128:128\
                 -n8:16:32".to_string()
           }
 
diff --git a/src/librustc_back/x86_64.rs b/src/librustc_back/x86_64.rs
index 88cd6743192..cbb288a533d 100644
--- a/src/librustc_back/x86_64.rs
+++ b/src/librustc_back/x86_64.rs
@@ -19,42 +19,42 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
         data_layout: match target_os {
           abi::OsMacos => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64".to_string()
           }
 
           abi::OsiOS => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64".to_string()
           }
 
           abi::OsWindows => {
             // FIXME: Test this. Copied from Linux (#2398)
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
 
           abi::OsLinux => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
           abi::OsAndroid => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
 
           abi::OsFreebsd => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
           abi::OsDragonfly => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
 
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index fdb13ecabde..2062685f4c8 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -210,7 +210,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     {
         let mut euv = euv::ExprUseVisitor::new(&mut clcx,
                                                bccx.tcx,
-                                               param_env.clone());
+                                               &param_env);
         euv.walk_fn(decl, body);
     }
 }
diff --git a/src/librustc_borrowck/borrowck/doc.rs b/src/librustc_borrowck/borrowck/doc.rs
index c6db5340f0f..ac2ab56b2c5 100644
--- a/src/librustc_borrowck/borrowck/doc.rs
+++ b/src/librustc_borrowck/borrowck/doc.rs
@@ -1152,7 +1152,7 @@
 //! the following:
 //!
 //! ```rust
-//! fn foo(a: [D, ..10], i: uint) -> D {
+//! fn foo(a: [D; 10], i: uint) -> D {
 //!     a[i]
 //! }
 //! ```
@@ -1168,7 +1168,7 @@
 //! would arise is the following:
 //!
 //! ```rust
-//! fn foo(a: [D, ..10], b: [D, ..10], i: uint, t: bool) -> D {
+//! fn foo(a: [D; 10], b: [D; 10], i: uint, t: bool) -> D {
 //!     if t {
 //!         a[i]
 //!     } else {
@@ -1182,7 +1182,7 @@
 //! ```
 //!
 //! There are a number of ways that the trans backend could choose to
-//! compile this (e.g. a `[bool, ..10]` array for each such moved array;
+//! compile this (e.g. a `[bool; 10]` array for each such moved array;
 //! or an `Option<uint>` for each moved array).  From the viewpoint of the
 //! borrow-checker, the important thing is to record what kind of fragment
 //! is implied by the relevant moves.
diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs
index 7609554033c..90da8906a6f 100644
--- a/src/librustc_borrowck/borrowck/fragments.rs
+++ b/src/librustc_borrowck/borrowck/fragments.rs
@@ -25,7 +25,6 @@ use rustc::middle::mem_categorization as mc;
 use rustc::util::ppaux::{Repr, UserString};
 use std::mem;
 use std::rc::Rc;
-use std::slice;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::attr::AttrMetaMethods;
@@ -45,7 +44,7 @@ enum Fragment {
 
 impl Fragment {
     fn loan_path_repr<'tcx>(&self, move_data: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) -> String {
-        let repr = |mpi| move_data.path_loan_path(mpi).repr(tcx);
+        let repr = |&: mpi| move_data.path_loan_path(mpi).repr(tcx);
         match *self {
             Just(mpi) => repr(mpi),
             AllButOneFrom(mpi) => format!("$(allbutone {})", repr(mpi)),
@@ -55,7 +54,7 @@ impl Fragment {
     fn loan_path_user_string<'tcx>(&self,
                                    move_data: &MoveData<'tcx>,
                                    tcx: &ty::ctxt<'tcx>) -> String {
-        let user_string = |mpi| move_data.path_loan_path(mpi).user_string(tcx);
+        let user_string = |&: mpi| move_data.path_loan_path(mpi).user_string(tcx);
         match *self {
             Just(mpi) => user_string(mpi),
             AllButOneFrom(mpi) => format!("$(allbutone {})", user_string(mpi)),
@@ -141,9 +140,9 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>,
 
     if !span_err && !print { return; }
 
-    let instrument_all_paths = |kind, vec_rc: &Vec<MovePathIndex>| {
+    let instrument_all_paths = |&: kind, vec_rc: &Vec<MovePathIndex>| {
         for (i, mpi) in vec_rc.iter().enumerate() {
-            let render = || this.path_loan_path(*mpi).user_string(tcx);
+            let render = |&:| this.path_loan_path(*mpi).user_string(tcx);
             if span_err {
                 tcx.sess.span_err(sp, format!("{}: `{}`", kind, render())[]);
             }
@@ -153,9 +152,9 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>,
         }
     };
 
-    let instrument_all_fragments = |kind, vec_rc: &Vec<Fragment>| {
+    let instrument_all_fragments = |&: kind, vec_rc: &Vec<Fragment>| {
         for (i, f) in vec_rc.iter().enumerate() {
-            let render = || f.loan_path_user_string(this, tcx);
+            let render = |&:| f.loan_path_user_string(this, tcx);
             if span_err {
                 tcx.sess.span_err(sp, format!("{}: `{}`", kind, render())[]);
             }
@@ -188,11 +187,11 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) {
     let mut moved = mem::replace(&mut fragments.moved_leaf_paths, vec![]);
     let mut assigned = mem::replace(&mut fragments.assigned_leaf_paths, vec![]);
 
-    let path_lps = |mpis: &[MovePathIndex]| -> Vec<String> {
+    let path_lps = |&: mpis: &[MovePathIndex]| -> Vec<String> {
         mpis.iter().map(|mpi| this.path_loan_path(*mpi).repr(tcx)).collect()
     };
 
-    let frag_lps = |fs: &[Fragment]| -> Vec<String> {
+    let frag_lps = |&: fs: &[Fragment]| -> Vec<String> {
         fs.iter().map(|f| f.loan_path_repr(this, tcx)).collect()
     };
 
@@ -268,9 +267,9 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) {
     return;
 
     fn non_member(elem: MovePathIndex, set: &[MovePathIndex]) -> bool {
-        match set.binary_search_elem(&elem) {
-            slice::BinarySearchResult::Found(_) => false,
-            slice::BinarySearchResult::NotFound(_) => true,
+        match set.binary_search(&elem) {
+            Ok(_) => false,
+            Err(_) => true,
         }
     }
 }
@@ -345,7 +344,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
                                                                         Rc<LoanPath<'tcx>>)>) {
     let parent_ty = parent_lp.to_type();
 
-    let add_fragment_sibling_local = |field_name, variant_did| {
+    let mut add_fragment_sibling_local = |&mut : field_name, variant_did| {
         add_fragment_sibling_core(
             this, tcx, gathered_fragments, parent_lp.clone(), mc, field_name, origin_lp,
             variant_did);
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index c0e892cdd27..7854c8acb47 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -53,7 +53,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     {
         let mut euv = euv::ExprUseVisitor::new(&mut glcx,
                                                bccx.tcx,
-                                               param_env);
+                                               &param_env);
         euv.walk_fn(decl, body);
     }
 
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index b3fb7123ef3..ad31c52ca34 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -58,7 +58,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                 cmt: mc::cmt<'tcx>) -> RestrictionResult<'tcx> {
         debug!("restrict(cmt={})", cmt.repr(self.bccx.tcx));
 
-        let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
+        let new_lp = |&: v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
 
         match cmt.cat.clone() {
             mc::cat_rvalue(..) => {
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index b57b76d66f7..c27b7b30e13 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -431,7 +431,7 @@ pub fn opt_loan_path<'tcx>(cmt: &mc::cmt<'tcx>) -> Option<Rc<LoanPath<'tcx>>> {
     //! which allows it to share common loan path pieces as it
     //! traverses the CMT.
 
-    let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
+    let new_lp = |&: v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty));
 
     match cmt.cat {
         mc::cat_rvalue(..) |
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index 5d2faa52f1a..547e7d272c6 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -521,15 +521,17 @@ impl<'tcx> MoveData<'tcx> {
         return true;
     }
 
-    // FIXME(#19596) unbox `f`
-    fn each_extending_path(&self, index: MovePathIndex, f: |MovePathIndex| -> bool) -> bool {
-        if !f(index) {
+    // FIXME(#19596) This is a workaround, but there should be better way to do this
+    fn each_extending_path_<F>(&self, index: MovePathIndex, f: &mut F) -> bool where
+        F: FnMut(MovePathIndex) -> bool,
+    {
+        if !(*f)(index) {
             return false;
         }
 
         let mut p = self.path_first_child(index);
         while p != InvalidMovePathIndex {
-            if !self.each_extending_path(p, |x| f(x)) {
+            if !self.each_extending_path_(p, f) {
                 return false;
             }
             p = self.path_next_sibling(p);
@@ -538,6 +540,12 @@ impl<'tcx> MoveData<'tcx> {
         return true;
     }
 
+    fn each_extending_path<F>(&self, index: MovePathIndex, mut f: F) -> bool where
+        F: FnMut(MovePathIndex) -> bool,
+    {
+        self.each_extending_path_(index, &mut f)
+    }
+
     fn each_applicable_move<F>(&self, index0: MovePathIndex, mut f: F) -> bool where
         F: FnMut(MoveIndex) -> bool,
     {
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index e71e9e5dfea..664d470b11b 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -37,4 +37,3 @@ pub use borrowck::FnPartsWithCFG;
 mod borrowck;
 
 pub mod graphviz;
-
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 0ac8d6ba734..91902b90673 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -10,6 +10,7 @@
 
 use rustc::session::Session;
 use rustc::session::config::{mod, Input, OutputFilenames};
+use rustc::session::search_paths::PathKind;
 use rustc::lint;
 use rustc::metadata::creader;
 use rustc::middle::{stability, ty, reachable};
@@ -177,21 +178,6 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     *sess.crate_metadata.borrow_mut() =
         collect_crate_metadata(sess, krate.attrs[]);
 
-    time(time_passes, "gated feature checking", (), |_| {
-        let (features, unknown_features) =
-            syntax::feature_gate::check_crate(&sess.parse_sess.span_diagnostic, &krate);
-
-        for uf in unknown_features.iter() {
-            sess.add_lint(lint::builtin::UNKNOWN_FEATURES,
-                          ast::CRATE_NODE_ID,
-                          *uf,
-                          "unknown feature".to_string());
-        }
-
-        sess.abort_if_errors();
-        *sess.features.borrow_mut() = features;
-    });
-
     time(time_passes, "recursion limit", (), |_| {
         middle::recursion_limit::update_recursion_limit(sess, &krate);
     });
@@ -204,6 +190,23 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     //
     // baz! should not use this definition unless foo is enabled.
 
+    time(time_passes, "gated macro checking", (), |_| {
+        let (features, unknown_features) =
+            syntax::feature_gate::check_crate_macros(sess.codemap(),
+                                                     &sess.parse_sess.span_diagnostic,
+                                                     &krate);
+        for uf in unknown_features.iter() {
+            sess.add_lint(lint::builtin::UNKNOWN_FEATURES,
+                          ast::CRATE_NODE_ID,
+                          *uf,
+                          "unknown feature".to_string());
+        }
+
+        // these need to be set "early" so that expansion sees `quote` if enabled.
+        *sess.features.borrow_mut() = features;
+        sess.abort_if_errors();
+    });
+
     krate = time(time_passes, "configuration 1", krate, |krate|
                  syntax::config::strip_unconfigured_items(sess.diagnostic(), krate));
 
@@ -266,7 +269,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
             let mut _old_path = String::new();
             if cfg!(windows) {
                 _old_path = os::getenv("PATH").unwrap_or(_old_path);
-                let mut new_path = sess.host_filesearch().get_dylib_search_paths();
+                let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
                 new_path.extend(os::split_paths(_old_path[]).into_iter());
                 os::setenv("PATH", os::join_paths(new_path[]).unwrap());
             }
@@ -288,6 +291,14 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
     );
 
+    // Needs to go *after* expansion to be able to check the results of macro expansion.
+    time(time_passes, "complete gated feature checking", (), |_| {
+        syntax::feature_gate::check_crate(sess.codemap(),
+                                          &sess.parse_sess.span_diagnostic,
+                                          &krate);
+        sess.abort_if_errors();
+    });
+
     // JBC: make CFG processing part of expansion to avoid this problem:
 
     // strip again, in case expansion added anything with a #[cfg].
@@ -541,7 +552,7 @@ pub fn phase_6_link_output(sess: &Session,
                            trans: &trans::CrateTranslation,
                            outputs: &OutputFilenames) {
     let old_path = os::getenv("PATH").unwrap_or_else(||String::new());
-    let mut new_path = sess.host_filesearch().get_tools_search_paths();
+    let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
     new_path.extend(os::split_paths(old_path[]).into_iter());
     os::setenv("PATH", os::join_paths(new_path[]).unwrap());
 
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 8b716a8431d..be55da8c59d 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -267,18 +267,20 @@ Available lint options:
         lints
     }
 
-    let (plugin, builtin) = lint_store.get_lints().partitioned(|&(_, p)| p);
+    let (plugin, builtin): (Vec<_>, _) = lint_store.get_lints()
+        .iter().cloned().partition(|&(_, p)| p);
     let plugin = sort_lints(plugin);
     let builtin = sort_lints(builtin);
 
-    let (plugin_groups, builtin_groups) = lint_store.get_lint_groups().partitioned(|&(_, _, p)| p);
+    let (plugin_groups, builtin_groups): (Vec<_>, _) = lint_store.get_lint_groups()
+        .iter().cloned().partition(|&(_, _, p)| p);
     let plugin_groups = sort_lint_groups(plugin_groups);
     let builtin_groups = sort_lint_groups(builtin_groups);
 
     let max_name_len = plugin.iter().chain(builtin.iter())
         .map(|&s| s.name.width(true))
         .max().unwrap_or(0);
-    let padded = |x: &str| {
+    let padded = |&: x: &str| {
         let mut s = repeat(" ").take(max_name_len - x.chars().count())
                                .collect::<String>();
         s.push_str(x);
@@ -289,7 +291,7 @@ Available lint options:
     println!("    {}  {:7.7}  {}", padded("name"), "default", "meaning");
     println!("    {}  {:7.7}  {}", padded("----"), "-------", "-------");
 
-    let print_lints = |lints: Vec<&Lint>| {
+    let print_lints = |&: lints: Vec<&Lint>| {
         for lint in lints.into_iter() {
             let name = lint.name_lower().replace("_", "-");
             println!("    {}  {:7.7}  {}",
@@ -305,7 +307,7 @@ Available lint options:
     let max_name_len = plugin_groups.iter().chain(builtin_groups.iter())
         .map(|&(s, _)| s.width(true))
         .max().unwrap_or(0);
-    let padded = |x: &str| {
+    let padded = |&: x: &str| {
         let mut s = repeat(" ").take(max_name_len - x.chars().count())
                                .collect::<String>();
         s.push_str(x);
@@ -316,7 +318,7 @@ Available lint options:
     println!("    {}  {}", padded("name"), "sub-lints");
     println!("    {}  {}", padded("----"), "---------");
 
-    let print_lint_groups = |lints: Vec<(&'static str, Vec<lint::LintId>)>| {
+    let print_lint_groups = |&: lints: Vec<(&'static str, Vec<lint::LintId>)>| {
         for (name, to) in lints.into_iter() {
             let name = name.chars().map(|x| x.to_lowercase())
                            .collect::<String>().replace("_", "-");
@@ -379,7 +381,7 @@ fn describe_codegen_flags() {
 /// returns None.
 pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
     // Throw away the first argument, the name of the binary
-    let _binary = args.remove(0).unwrap();
+    let _binary = args.remove(0);
 
     if args.is_empty() {
         // user did not write `-v` nor `-Z unstable-options`, so do not
@@ -542,7 +544,7 @@ pub fn monitor<F:FnOnce()+Send>(f: F) {
     match cfg.spawn(move || { std::io::stdio::set_stderr(box w); f() }).join() {
         Ok(()) => { /* fallthrough */ }
         Err(value) => {
-            // Task panicked without emitting a fatal diagnostic
+            // Thread panicked without emitting a fatal diagnostic
             if !value.is::<diagnostic::FatalError>() {
                 let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
 
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index cf99d409ceb..773ea30d401 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -301,7 +301,7 @@ fn gather_flowgraph_variants(sess: &Session) -> Vec<borrowck_dot::Variant> {
     let print_moves   = config::FLOWGRAPH_PRINT_MOVES;
     let print_assigns = config::FLOWGRAPH_PRINT_ASSIGNS;
     let print_all     = config::FLOWGRAPH_PRINT_ALL;
-    let opt = |print_which| sess.debugging_opt(print_which);
+    let opt = |&: print_which| sess.debugging_opt(print_which);
     let mut variants = Vec::new();
     if opt(print_all) || opt(print_loans) {
         variants.push(borrowck_dot::Loans);
@@ -365,7 +365,7 @@ impl UserIdentifiedItem {
     }
 
     fn to_one_node_id(self, user_option: &str, sess: &Session, map: &ast_map::Map) -> ast::NodeId {
-        let fail_because = |is_wrong_because| -> ast::NodeId {
+        let fail_because = |&: is_wrong_because| -> ast::NodeId {
             let message =
                 format!("{} needs NodeId (int) or unique \
                          path suffix (b::c::d); got {}, which {}",
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 941155ac5e7..6329acfb578 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -28,7 +28,7 @@ use rustc_typeck::middle::infer::glb::Glb;
 use rustc_typeck::middle::infer::sub::Sub;
 use rustc_typeck::util::ppaux::{ty_to_string, Repr, UserString};
 use rustc::session::{mod,config};
-use syntax::{abi, ast, ast_map, ast_util};
+use syntax::{abi, ast, ast_map};
 use syntax::codemap;
 use syntax::codemap::{Span, CodeMap, DUMMY_SP};
 use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help};
@@ -145,6 +145,10 @@ fn test_env<F>(source_string: &str,
 }
 
 impl<'a, 'tcx> Env<'a, 'tcx> {
+    pub fn tcx(&self) -> &ty::ctxt<'tcx> {
+        self.infcx.tcx
+    }
+
     pub fn create_region_hierarchy(&self, rh: &RH) {
         for child_rh in rh.sub.iter() {
             self.create_region_hierarchy(child_rh);
@@ -296,7 +300,8 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     }
 
     pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> {
-        ty::mk_param(self.infcx.tcx, space, index, ast_util::local_def(ast::DUMMY_NODE_ID))
+        let name = format!("T{}", index);
+        ty::mk_param(self.infcx.tcx, space, index, token::intern(name[]))
     }
 
     pub fn re_early_bound(&self,
@@ -314,14 +319,16 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     }
 
     pub fn t_rptr(&self, r: ty::Region) -> Ty<'tcx> {
-        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx,
+                        self.infcx.tcx.mk_region(r),
+                        self.tcx().types.int)
     }
 
     pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> {
         let r = self.re_late_bound_with_debruijn(id, ty::DebruijnIndex::new(1));
         ty::mk_imm_rptr(self.infcx.tcx,
                         self.infcx.tcx.mk_region(r),
-                        ty::mk_int())
+                        self.tcx().types.int)
     }
 
     pub fn t_rptr_late_bound_with_debruijn(&self,
@@ -331,12 +338,13 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         let r = self.re_late_bound_with_debruijn(id, debruijn);
         ty::mk_imm_rptr(self.infcx.tcx,
                         self.infcx.tcx.mk_region(r),
-                        ty::mk_int())
+                        self.tcx().types.int)
     }
 
     pub fn t_rptr_scope(&self, id: ast::NodeId) -> Ty<'tcx> {
         let r = ty::ReScope(CodeExtent::from_node_id(id));
-        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r),
+                        self.tcx().types.int)
     }
 
     pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region {
@@ -346,15 +354,19 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
 
     pub fn t_rptr_free(&self, nid: ast::NodeId, id: u32) -> Ty<'tcx> {
         let r = self.re_free(nid, id);
-        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx,
+                        self.infcx.tcx.mk_region(r),
+                        self.tcx().types.int)
     }
 
     pub fn t_rptr_static(&self) -> Ty<'tcx> {
-        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(ty::ReStatic), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx,
+                        self.infcx.tcx.mk_region(ty::ReStatic),
+                        self.tcx().types.int)
     }
 
     pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> {
-        infer::TypeTrace::dummy()
+        infer::TypeTrace::dummy(self.tcx())
     }
 
     pub fn sub(&self) -> Sub<'a, 'tcx> {
@@ -480,8 +492,8 @@ fn sub_free_bound_false() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_free1 = env.t_rptr_free(0, 1);
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        env.check_not_sub(env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                          env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                          env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -496,8 +508,8 @@ fn sub_bound_free_true() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_sub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()));
+        env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int));
     })
 }
 
@@ -512,8 +524,8 @@ fn sub_free_bound_false_infer() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_infer1 = env.infcx.next_ty_var();
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        env.check_not_sub(env.t_fn(&[t_infer1], ty::mk_int()),
-                          env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.int),
+                          env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -531,9 +543,9 @@ fn lub_free_bound_infer() {
         let t_infer1 = env.infcx.next_ty_var();
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_lub(env.t_fn(&[t_infer1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int));
     });
 }
 
@@ -542,9 +554,9 @@ fn lub_bound_bound() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_bound2 = env.t_rptr_late_bound(2);
-        env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -553,9 +565,9 @@ fn lub_bound_free() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int));
     })
 }
 
@@ -564,9 +576,9 @@ fn lub_bound_static() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_static = env.t_rptr_static();
-        env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int));
     })
 }
 
@@ -587,9 +599,9 @@ fn lub_free_free() {
         let t_rptr_free1 = env.t_rptr_free(0, 1);
         let t_rptr_free2 = env.t_rptr_free(0, 2);
         let t_rptr_static = env.t_rptr_static();
-        env.check_lub(env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int));
     })
 }
 
@@ -612,9 +624,9 @@ fn glb_free_free_with_common_scope() {
         let t_rptr_free1 = env.t_rptr_free(0, 1);
         let t_rptr_free2 = env.t_rptr_free(0, 2);
         let t_rptr_scope = env.t_rptr_scope(0);
-        env.check_glb(env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_scope], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_scope], env.tcx().types.int));
     })
 }
 
@@ -623,9 +635,9 @@ fn glb_bound_bound() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_bound2 = env.t_rptr_late_bound(2);
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -634,9 +646,9 @@ fn glb_bound_free() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -648,9 +660,9 @@ fn glb_bound_free_infer() {
 
         // compute GLB(fn(_) -> int, for<'b> fn(&'b int) -> int),
         // which should yield for<'b> fn(&'b int) -> int
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_infer1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_infer1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
 
         // as a side-effect, computing GLB should unify `_` with
         // `&'_ int`
@@ -667,9 +679,9 @@ fn glb_bound_static() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_static = env.t_rptr_static();
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -790,7 +802,6 @@ fn escaping() {
 /// late-bound region.
 #[test]
 fn subst_region_renumber_region() {
-
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let re_bound1 = env.re_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
 
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index 3528b510ea1..296ebcf9cfd 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -1743,7 +1743,8 @@ extern {
                                           isOptimized: bool,
                                           Flags: *const c_char,
                                           RuntimeVer: c_uint,
-                                          SplitName: *const c_char);
+                                          SplitName: *const c_char)
+                                          -> DIDescriptor;
 
     pub fn LLVMDIBuilderCreateFile(Builder: DIBuilderRef,
                                    Filename: *const c_char,
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
new file mode 100644
index 00000000000..8553a209005
--- /dev/null
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -0,0 +1,1283 @@
+// 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.
+
+//! Reduced graph building
+//!
+//! Here we build the "reduced graph": the graph of the module tree without
+//! any imports resolved.
+
+use {DefModifiers, PUBLIC, IMPORTABLE};
+use ImportDirective;
+use ImportDirectiveSubclass::{mod, SingleImport, GlobImport};
+use ImportResolution;
+use Module;
+use ModuleKind::*;
+use Namespace::{TypeNS, ValueNS};
+use NameBindings;
+use ParentLink::{mod, ModuleParentLink, BlockParentLink};
+use Resolver;
+use RibKind::*;
+use Shadowable;
+use TypeNsDef;
+use TypeParameters::HasTypeParameters;
+
+use self::DuplicateCheckingMode::*;
+use self::NamespaceError::*;
+
+use rustc::metadata::csearch;
+use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
+use rustc::middle::def::*;
+use rustc::middle::subst::FnSpace;
+
+use syntax::ast::{Block, Crate};
+use syntax::ast::{DeclItem, DefId};
+use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
+use syntax::ast::{Item, ItemConst, ItemEnum, ItemFn};
+use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
+use syntax::ast::{ItemStruct, ItemTrait, ItemTy};
+use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
+use syntax::ast::{PathListIdent, PathListMod};
+use syntax::ast::{Public, SelfStatic};
+use syntax::ast::StmtDecl;
+use syntax::ast::StructVariantKind;
+use syntax::ast::TupleVariantKind;
+use syntax::ast::TyObjectSum;
+use syntax::ast::{TypeImplItem, UnnamedField};
+use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
+use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
+use syntax::ast::{Visibility};
+use syntax::ast::TyPath;
+use syntax::ast;
+use syntax::ast_util::{mod, PostExpansionMethod, local_def};
+use syntax::attr::AttrMetaMethods;
+use syntax::parse::token::{mod, special_idents};
+use syntax::codemap::{Span, DUMMY_SP};
+use syntax::visit::{mod, Visitor};
+
+use std::mem::replace;
+use std::ops::{Deref, DerefMut};
+use std::rc::Rc;
+
+// Specifies how duplicates should be handled when adding a child item if
+// another item exists with the same name in some namespace.
+#[deriving(Copy, PartialEq)]
+enum DuplicateCheckingMode {
+    ForbidDuplicateModules,
+    ForbidDuplicateTypesAndModules,
+    ForbidDuplicateValues,
+    ForbidDuplicateTypesAndValues,
+    OverwriteDuplicates
+}
+
+#[deriving(Copy, PartialEq)]
+enum NamespaceError {
+    NoError,
+    ModuleError,
+    TypeError,
+    ValueError
+}
+
+fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
+    match ns {
+        NoError                 => "",
+        ModuleError | TypeError => "type or module",
+        ValueError              => "value",
+    }
+}
+
+struct GraphBuilder<'a, 'b:'a, 'tcx:'b> {
+    resolver: &'a mut Resolver<'b, 'tcx>
+}
+
+impl<'a, 'b:'a, 'tcx:'b> Deref<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> {
+    fn deref(&self) -> &Resolver<'b, 'tcx> {
+        &*self.resolver
+    }
+}
+
+impl<'a, 'b:'a, 'tcx:'b> DerefMut<Resolver<'b, 'tcx>> for GraphBuilder<'a, 'b, 'tcx> {
+    fn deref_mut(&mut self) -> &mut Resolver<'b, 'tcx> {
+        &mut *self.resolver
+    }
+}
+
+impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
+    /// Constructs the reduced graph for the entire crate.
+    fn build_reduced_graph(self, krate: &ast::Crate) {
+        let parent = self.graph_root.get_module();
+        let mut visitor = BuildReducedGraphVisitor {
+            builder: self,
+            parent: parent
+        };
+        visit::walk_crate(&mut visitor, krate);
+    }
+
+    /// Adds a new child item to the module definition of the parent node and
+    /// returns its corresponding name bindings as well as the current parent.
+    /// Or, if we're inside a block, creates (or reuses) an anonymous module
+    /// corresponding to the innermost block ID and returns the name bindings
+    /// as well as the newly-created parent.
+    ///
+    /// # Panics
+    ///
+    /// Panics if this node does not have a module definition and we are not inside
+    /// a block.
+    fn add_child(&self,
+                 name: Name,
+                 parent: &Rc<Module>,
+                 duplicate_checking_mode: DuplicateCheckingMode,
+                 // For printing errors
+                 sp: Span)
+                 -> Rc<NameBindings> {
+        // If this is the immediate descendant of a module, then we add the
+        // child name directly. Otherwise, we create or reuse an anonymous
+        // module and add the child to that.
+
+        self.check_for_conflicts_between_external_crates_and_items(&**parent,
+                                                                   name,
+                                                                   sp);
+
+        // Add or reuse the child.
+        let child = parent.children.borrow().get(&name).cloned();
+        match child {
+            None => {
+                let child = Rc::new(NameBindings::new());
+                parent.children.borrow_mut().insert(name, child.clone());
+                child
+            }
+            Some(child) => {
+                // Enforce the duplicate checking mode:
+                //
+                // * If we're requesting duplicate module checking, check that
+                //   there isn't a module in the module with the same name.
+                //
+                // * If we're requesting duplicate type checking, check that
+                //   there isn't a type in the module with the same name.
+                //
+                // * If we're requesting duplicate value checking, check that
+                //   there isn't a value in the module with the same name.
+                //
+                // * If we're requesting duplicate type checking and duplicate
+                //   value checking, check that there isn't a duplicate type
+                //   and a duplicate value with the same name.
+                //
+                // * If no duplicate checking was requested at all, do
+                //   nothing.
+
+                let mut duplicate_type = NoError;
+                let ns = match duplicate_checking_mode {
+                    ForbidDuplicateModules => {
+                        if child.get_module_if_available().is_some() {
+                            duplicate_type = ModuleError;
+                        }
+                        Some(TypeNS)
+                    }
+                    ForbidDuplicateTypesAndModules => {
+                        match child.def_for_namespace(TypeNS) {
+                            None => {}
+                            Some(_) if child.get_module_if_available()
+                                            .map(|m| m.kind.get()) ==
+                                       Some(ImplModuleKind) => {}
+                            Some(_) => duplicate_type = TypeError
+                        }
+                        Some(TypeNS)
+                    }
+                    ForbidDuplicateValues => {
+                        if child.defined_in_namespace(ValueNS) {
+                            duplicate_type = ValueError;
+                        }
+                        Some(ValueNS)
+                    }
+                    ForbidDuplicateTypesAndValues => {
+                        let mut n = None;
+                        match child.def_for_namespace(TypeNS) {
+                            Some(DefMod(_)) | None => {}
+                            Some(_) => {
+                                n = Some(TypeNS);
+                                duplicate_type = TypeError;
+                            }
+                        };
+                        if child.defined_in_namespace(ValueNS) {
+                            duplicate_type = ValueError;
+                            n = Some(ValueNS);
+                        }
+                        n
+                    }
+                    OverwriteDuplicates => None
+                };
+                if duplicate_type != NoError {
+                    // Return an error here by looking up the namespace that
+                    // had the duplicate.
+                    let ns = ns.unwrap();
+                    self.resolve_error(sp,
+                        format!("duplicate definition of {} `{}`",
+                             namespace_error_to_string(duplicate_type),
+                             token::get_name(name))[]);
+                    {
+                        let r = child.span_for_namespace(ns);
+                        for sp in r.iter() {
+                            self.session.span_note(*sp,
+                                 format!("first definition of {} `{}` here",
+                                      namespace_error_to_string(duplicate_type),
+                                      token::get_name(name))[]);
+                        }
+                    }
+                }
+                child
+            }
+        }
+    }
+
+    fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
+        // If the block has view items, we need an anonymous module.
+        if block.view_items.len() > 0 {
+            return true;
+        }
+
+        // Check each statement.
+        for statement in block.stmts.iter() {
+            match statement.node {
+                StmtDecl(ref declaration, _) => {
+                    match declaration.node {
+                        DeclItem(_) => {
+                            return true;
+                        }
+                        _ => {
+                            // Keep searching.
+                        }
+                    }
+                }
+                _ => {
+                    // Keep searching.
+                }
+            }
+        }
+
+        // If we found neither view items nor items, we don't need to create
+        // an anonymous module.
+
+        return false;
+    }
+
+    fn get_parent_link(&mut self, parent: &Rc<Module>, name: Name) -> ParentLink {
+        ModuleParentLink(parent.downgrade(), name)
+    }
+
+    /// Constructs the reduced graph for one item.
+    fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) -> Rc<Module> {
+        let name = item.ident.name;
+        let sp = item.span;
+        let is_public = item.vis == ast::Public;
+        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+
+        match item.node {
+            ItemMod(..) => {
+                let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
+
+                let parent_link = self.get_parent_link(parent, name);
+                let def_id = DefId { krate: 0, node: item.id };
+                name_bindings.define_module(parent_link,
+                                            Some(def_id),
+                                            NormalModuleKind,
+                                            false,
+                                            item.vis == ast::Public,
+                                            sp);
+
+                name_bindings.get_module()
+            }
+
+            ItemForeignMod(..) => parent.clone(),
+
+            // These items live in the value namespace.
+            ItemStatic(_, m, _) => {
+                let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
+                let mutbl = m == ast::MutMutable;
+
+                name_bindings.define_value(DefStatic(local_def(item.id), mutbl), sp, modifiers);
+                parent.clone()
+            }
+            ItemConst(_, _) => {
+                self.add_child(name, parent, ForbidDuplicateValues, sp)
+                    .define_value(DefConst(local_def(item.id)), sp, modifiers);
+                parent.clone()
+            }
+            ItemFn(_, _, _, _, _) => {
+                let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
+
+                let def = DefFn(local_def(item.id), false);
+                name_bindings.define_value(def, sp, modifiers);
+                parent.clone()
+            }
+
+            // These items live in the type namespace.
+            ItemTy(..) => {
+                let name_bindings =
+                    self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
+
+                name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
+                parent.clone()
+            }
+
+            ItemEnum(ref enum_definition, _) => {
+                let name_bindings =
+                    self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
+
+                name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
+
+                let parent_link = self.get_parent_link(parent, name);
+                // We want to make sure the module type is EnumModuleKind
+                // even if there's already an ImplModuleKind module defined,
+                // since that's how we prevent duplicate enum definitions
+                name_bindings.set_module_kind(parent_link,
+                                              Some(local_def(item.id)),
+                                              EnumModuleKind,
+                                              false,
+                                              is_public,
+                                              sp);
+
+                let module = name_bindings.get_module();
+
+                for variant in (*enum_definition).variants.iter() {
+                    self.build_reduced_graph_for_variant(
+                        &**variant,
+                        local_def(item.id),
+                        &module);
+                }
+                parent.clone()
+            }
+
+            // These items live in both the type and value namespaces.
+            ItemStruct(ref struct_def, _) => {
+                // Adding to both Type and Value namespaces or just Type?
+                let (forbid, ctor_id) = match struct_def.ctor_id {
+                    Some(ctor_id)   => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
+                    None            => (ForbidDuplicateTypesAndModules, None)
+                };
+
+                let name_bindings = self.add_child(name, parent, forbid, sp);
+
+                // Define a name in the type namespace.
+                name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
+
+                // If this is a newtype or unit-like struct, define a name
+                // in the value namespace as well
+                if let Some(cid) = ctor_id {
+                    name_bindings.define_value(DefStruct(local_def(cid)), sp, modifiers);
+                }
+
+                // Record the def ID and fields of this struct.
+                let named_fields = struct_def.fields.iter().filter_map(|f| {
+                    match f.node.kind {
+                        NamedField(ident, _) => Some(ident.name),
+                        UnnamedField(_) => None
+                    }
+                }).collect();
+                self.structs.insert(local_def(item.id), named_fields);
+
+                parent.clone()
+            }
+
+            ItemImpl(_, _, None, ref ty, ref impl_items) => {
+                // If this implements an anonymous trait, then add all the
+                // methods within to a new module, if the type was defined
+                // within this module.
+
+                let mod_name = match ty.node {
+                    TyPath(ref path, _) if path.segments.len() == 1 => {
+                        // FIXME(18446) we should distinguish between the name of
+                        // a trait and the name of an impl of that trait.
+                        Some(path.segments.last().unwrap().identifier.name)
+                    }
+                    TyObjectSum(ref lhs_ty, _) => {
+                        match lhs_ty.node {
+                            TyPath(ref path, _) if path.segments.len() == 1 => {
+                                Some(path.segments.last().unwrap().identifier.name)
+                            }
+                            _ => {
+                                None
+                            }
+                        }
+                    }
+                    _ => {
+                        None
+                    }
+                };
+
+                match mod_name {
+                    None => {
+                        self.resolve_error(ty.span,
+                                           "inherent implementations may \
+                                            only be implemented in the same \
+                                            module as the type they are \
+                                            implemented for")
+                    }
+                    Some(mod_name) => {
+                        // Create the module and add all methods.
+                        let parent_opt = parent.children.borrow().get(&mod_name).cloned();
+                        let new_parent = match parent_opt {
+                            // It already exists
+                            Some(ref child) if child.get_module_if_available()
+                                .is_some() &&
+                                (child.get_module().kind.get() == ImplModuleKind ||
+                                 child.get_module().kind.get() == TraitModuleKind) => {
+                                    child.get_module()
+                                }
+                            Some(ref child) if child.get_module_if_available()
+                                .is_some() &&
+                                child.get_module().kind.get() ==
+                                EnumModuleKind => child.get_module(),
+                            // Create the module
+                            _ => {
+                                let name_bindings =
+                                    self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
+
+                                let parent_link = self.get_parent_link(parent, name);
+                                let def_id = local_def(item.id);
+                                let ns = TypeNS;
+                                let is_public =
+                                    !name_bindings.defined_in_namespace(ns) ||
+                                    name_bindings.defined_in_public_namespace(ns);
+
+                                name_bindings.define_module(parent_link,
+                                                            Some(def_id),
+                                                            ImplModuleKind,
+                                                            false,
+                                                            is_public,
+                                                            sp);
+
+                                name_bindings.get_module()
+                            }
+                        };
+
+                        // For each implementation item...
+                        for impl_item in impl_items.iter() {
+                            match *impl_item {
+                                MethodImplItem(ref method) => {
+                                    // Add the method to the module.
+                                    let name = method.pe_ident().name;
+                                    let method_name_bindings =
+                                        self.add_child(name,
+                                                       &new_parent,
+                                                       ForbidDuplicateValues,
+                                                       method.span);
+                                    let def = match method.pe_explicit_self()
+                                        .node {
+                                            SelfStatic => {
+                                                // Static methods become
+                                                // `DefStaticMethod`s.
+                                                DefStaticMethod(local_def(method.id),
+                                                                FromImpl(local_def(item.id)))
+                                            }
+                                            _ => {
+                                                // Non-static methods become
+                                                // `DefMethod`s.
+                                                DefMethod(local_def(method.id),
+                                                          None,
+                                                          FromImpl(local_def(item.id)))
+                                            }
+                                        };
+
+                                    // NB: not IMPORTABLE
+                                    let modifiers = if method.pe_vis() == ast::Public {
+                                        PUBLIC
+                                    } else {
+                                        DefModifiers::empty()
+                                    };
+                                    method_name_bindings.define_value(
+                                        def,
+                                        method.span,
+                                        modifiers);
+                                }
+                                TypeImplItem(ref typedef) => {
+                                    // Add the typedef to the module.
+                                    let name = typedef.ident.name;
+                                    let typedef_name_bindings =
+                                        self.add_child(
+                                            name,
+                                            &new_parent,
+                                            ForbidDuplicateTypesAndModules,
+                                            typedef.span);
+                                    let def = DefAssociatedTy(local_def(
+                                        typedef.id));
+                                    // NB: not IMPORTABLE
+                                    let modifiers = if typedef.vis == ast::Public {
+                                        PUBLIC
+                                    } else {
+                                        DefModifiers::empty()
+                                    };
+                                    typedef_name_bindings.define_type(
+                                        def,
+                                        typedef.span,
+                                        modifiers);
+                                }
+                            }
+                        }
+                    }
+                }
+
+                parent.clone()
+            }
+
+            ItemImpl(_, _, Some(_), _, _) => parent.clone(),
+
+            ItemTrait(_, _, _, ref items) => {
+                let name_bindings =
+                    self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
+
+                // Add all the items within to a new module.
+                let parent_link = self.get_parent_link(parent, name);
+                name_bindings.define_module(parent_link,
+                                            Some(local_def(item.id)),
+                                            TraitModuleKind,
+                                            false,
+                                            item.vis == ast::Public,
+                                            sp);
+                let module_parent = name_bindings.get_module();
+
+                let def_id = local_def(item.id);
+
+                // Add the names of all the items to the trait info.
+                for trait_item in items.iter() {
+                    let (name, kind) = match *trait_item {
+                        ast::RequiredMethod(_) |
+                        ast::ProvidedMethod(_) => {
+                            let ty_m = ast_util::trait_item_to_ty_method(trait_item);
+
+                            let name = ty_m.ident.name;
+
+                            // Add it as a name in the trait module.
+                            let (def, static_flag) = match ty_m.explicit_self
+                                                               .node {
+                                SelfStatic => {
+                                    // Static methods become `DefStaticMethod`s.
+                                    (DefStaticMethod(
+                                            local_def(ty_m.id),
+                                            FromTrait(local_def(item.id))),
+                                     StaticMethodTraitItemKind)
+                                }
+                                _ => {
+                                    // Non-static methods become `DefMethod`s.
+                                    (DefMethod(local_def(ty_m.id),
+                                               Some(local_def(item.id)),
+                                               FromTrait(local_def(item.id))),
+                                     NonstaticMethodTraitItemKind)
+                                }
+                            };
+
+                            let method_name_bindings =
+                                self.add_child(name,
+                                               &module_parent,
+                                               ForbidDuplicateTypesAndValues,
+                                               ty_m.span);
+                            // NB: not IMPORTABLE
+                            method_name_bindings.define_value(def,
+                                                              ty_m.span,
+                                                              PUBLIC);
+
+                            (name, static_flag)
+                        }
+                        ast::TypeTraitItem(ref associated_type) => {
+                            let def = DefAssociatedTy(local_def(
+                                    associated_type.ty_param.id));
+
+                            let name_bindings =
+                                self.add_child(associated_type.ty_param.ident.name,
+                                               &module_parent,
+                                               ForbidDuplicateTypesAndValues,
+                                               associated_type.ty_param.span);
+                            // NB: not IMPORTABLE
+                            name_bindings.define_type(def,
+                                                      associated_type.ty_param.span,
+                                                      PUBLIC);
+
+                            (associated_type.ty_param.ident.name, TypeTraitItemKind)
+                        }
+                    };
+
+                    self.trait_item_map.insert((name, def_id), kind);
+                }
+
+                name_bindings.define_type(DefTrait(def_id), sp, modifiers);
+                parent.clone()
+            }
+            ItemMac(..) => parent.clone()
+        }
+    }
+
+    // Constructs the reduced graph for one variant. Variants exist in the
+    // type and value namespaces.
+    fn build_reduced_graph_for_variant(&mut self,
+                                       variant: &Variant,
+                                       item_id: DefId,
+                                       parent: &Rc<Module>) {
+        let name = variant.node.name.name;
+        let is_exported = match variant.node.kind {
+            TupleVariantKind(_) => false,
+            StructVariantKind(_) => {
+                // Not adding fields for variants as they are not accessed with a self receiver
+                self.structs.insert(local_def(variant.node.id), Vec::new());
+                true
+            }
+        };
+
+        let child = self.add_child(name, parent,
+                                   ForbidDuplicateTypesAndValues,
+                                   variant.span);
+        // variants are always treated as importable to allow them to be glob
+        // used
+        child.define_value(DefVariant(item_id,
+                                      local_def(variant.node.id), is_exported),
+                           variant.span, PUBLIC | IMPORTABLE);
+        child.define_type(DefVariant(item_id,
+                                     local_def(variant.node.id), is_exported),
+                          variant.span, PUBLIC | IMPORTABLE);
+    }
+
+    /// Constructs the reduced graph for one 'view item'. View items consist
+    /// of imports and use directives.
+    fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem, parent: &Rc<Module>) {
+        match view_item.node {
+            ViewItemUse(ref view_path) => {
+                // Extract and intern the module part of the path. For
+                // globs and lists, the path is found directly in the AST;
+                // for simple paths we have to munge the path a little.
+                let module_path = match view_path.node {
+                    ViewPathSimple(_, ref full_path, _) => {
+                        full_path.segments
+                            .init()
+                            .iter().map(|ident| ident.identifier.name)
+                            .collect()
+                    }
+
+                    ViewPathGlob(ref module_ident_path, _) |
+                    ViewPathList(ref module_ident_path, _, _) => {
+                        module_ident_path.segments
+                            .iter().map(|ident| ident.identifier.name).collect()
+                    }
+                };
+
+                // Build up the import directives.
+                let is_public = view_item.vis == ast::Public;
+                let shadowable =
+                    view_item.attrs
+                             .iter()
+                             .any(|attr| {
+                                 attr.name() == token::get_name(
+                                    special_idents::prelude_import.name)
+                             });
+                let shadowable = if shadowable {
+                    Shadowable::Always
+                } else {
+                    Shadowable::Never
+                };
+
+                match view_path.node {
+                    ViewPathSimple(binding, ref full_path, id) => {
+                        let source_name =
+                            full_path.segments.last().unwrap().identifier.name;
+                        if token::get_name(source_name).get() == "mod" {
+                            self.resolve_error(view_path.span,
+                                "`mod` imports are only allowed within a { } list");
+                        }
+
+                        let subclass = SingleImport(binding.name,
+                                                    source_name);
+                        self.build_import_directive(&**parent,
+                                                    module_path,
+                                                    subclass,
+                                                    view_path.span,
+                                                    id,
+                                                    is_public,
+                                                    shadowable);
+                    }
+                    ViewPathList(_, ref source_items, _) => {
+                        // Make sure there's at most one `mod` import in the list.
+                        let mod_spans = source_items.iter().filter_map(|item| match item.node {
+                            PathListMod { .. } => Some(item.span),
+                            _ => None
+                        }).collect::<Vec<Span>>();
+                        if mod_spans.len() > 1 {
+                            self.resolve_error(mod_spans[0],
+                                "`mod` import can only appear once in the list");
+                            for other_span in mod_spans.iter().skip(1) {
+                                self.session.span_note(*other_span,
+                                    "another `mod` import appears here");
+                            }
+                        }
+
+                        for source_item in source_items.iter() {
+                            let (module_path, name) = match source_item.node {
+                                PathListIdent { name, .. } =>
+                                    (module_path.clone(), name.name),
+                                PathListMod { .. } => {
+                                    let name = match module_path.last() {
+                                        Some(name) => *name,
+                                        None => {
+                                            self.resolve_error(source_item.span,
+                                                "`mod` import can only appear in an import list \
+                                                 with a non-empty prefix");
+                                            continue;
+                                        }
+                                    };
+                                    let module_path = module_path.init();
+                                    (module_path.to_vec(), name)
+                                }
+                            };
+                            self.build_import_directive(
+                                &**parent,
+                                module_path,
+                                SingleImport(name, name),
+                                source_item.span,
+                                source_item.node.id(),
+                                is_public,
+                                shadowable);
+                        }
+                    }
+                    ViewPathGlob(_, id) => {
+                        self.build_import_directive(&**parent,
+                                                    module_path,
+                                                    GlobImport,
+                                                    view_path.span,
+                                                    id,
+                                                    is_public,
+                                                    shadowable);
+                    }
+                }
+            }
+
+            ViewItemExternCrate(name, _, node_id) => {
+                // n.b. we don't need to look at the path option here, because cstore already did
+                for &crate_id in self.session.cstore
+                                     .find_extern_mod_stmt_cnum(node_id).iter() {
+                    let def_id = DefId { krate: crate_id, node: 0 };
+                    self.external_exports.insert(def_id);
+                    let parent_link = ModuleParentLink(parent.downgrade(), name.name);
+                    let external_module = Rc::new(Module::new(parent_link,
+                                                              Some(def_id),
+                                                              NormalModuleKind,
+                                                              false,
+                                                              true));
+                    debug!("(build reduced graph for item) found extern `{}`",
+                            self.module_to_string(&*external_module));
+                    self.check_for_conflicts_between_external_crates(
+                        &**parent,
+                        name.name,
+                        view_item.span);
+                    parent.external_module_children.borrow_mut()
+                          .insert(name.name, external_module.clone());
+                    self.build_reduced_graph_for_external_crate(&external_module);
+                }
+            }
+        }
+    }
+
+    /// Constructs the reduced graph for one foreign item.
+    fn build_reduced_graph_for_foreign_item<F>(&mut self,
+                                               foreign_item: &ForeignItem,
+                                               parent: &Rc<Module>,
+                                               f: F) where
+        F: FnOnce(&mut Resolver),
+    {
+        let name = foreign_item.ident.name;
+        let is_public = foreign_item.vis == ast::Public;
+        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+        let name_bindings =
+            self.add_child(name, parent, ForbidDuplicateValues,
+                           foreign_item.span);
+
+        match foreign_item.node {
+            ForeignItemFn(_, ref generics) => {
+                let def = DefFn(local_def(foreign_item.id), false);
+                name_bindings.define_value(def, foreign_item.span, modifiers);
+
+                self.with_type_parameter_rib(
+                    HasTypeParameters(generics,
+                                      FnSpace,
+                                      foreign_item.id,
+                                      NormalRibKind),
+                    f);
+            }
+            ForeignItemStatic(_, m) => {
+                let def = DefStatic(local_def(foreign_item.id), m);
+                name_bindings.define_value(def, foreign_item.span, modifiers);
+
+                f(self.resolver)
+            }
+        }
+    }
+
+    fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
+        if self.block_needs_anonymous_module(block) {
+            let block_id = block.id;
+
+            debug!("(building reduced graph for block) creating a new \
+                    anonymous module for block {}",
+                   block_id);
+
+            let new_module = Rc::new(Module::new(
+                BlockParentLink(parent.downgrade(), block_id),
+                None,
+                AnonymousModuleKind,
+                false,
+                false));
+            parent.anonymous_children.borrow_mut().insert(block_id, new_module.clone());
+            new_module
+        } else {
+            parent.clone()
+        }
+    }
+
+    fn handle_external_def(&mut self,
+                           def: Def,
+                           vis: Visibility,
+                           child_name_bindings: &NameBindings,
+                           final_ident: &str,
+                           name: Name,
+                           new_parent: &Rc<Module>) {
+        debug!("(building reduced graph for \
+                external crate) building external def, priv {}",
+               vis);
+        let is_public = vis == ast::Public;
+        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+        let is_exported = is_public && match new_parent.def_id.get() {
+            None => true,
+            Some(did) => self.external_exports.contains(&did)
+        };
+        if is_exported {
+            self.external_exports.insert(def.def_id());
+        }
+
+        let kind = match def {
+            DefTy(_, true) => EnumModuleKind,
+            DefStruct(..) | DefTy(..) => ImplModuleKind,
+            _ => NormalModuleKind
+        };
+
+        match def {
+          DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
+          DefTy(def_id, _) => {
+            let type_def = child_name_bindings.type_def.borrow().clone();
+            match type_def {
+              Some(TypeNsDef { module_def: Some(module_def), .. }) => {
+                debug!("(building reduced graph for external crate) \
+                        already created module");
+                module_def.def_id.set(Some(def_id));
+              }
+              Some(_) | None => {
+                debug!("(building reduced graph for \
+                        external crate) building module \
+                        {}", final_ident);
+                let parent_link = self.get_parent_link(new_parent, name);
+
+                child_name_bindings.define_module(parent_link,
+                                                  Some(def_id),
+                                                  kind,
+                                                  true,
+                                                  is_public,
+                                                  DUMMY_SP);
+              }
+            }
+          }
+          _ => {}
+        }
+
+        match def {
+          DefMod(_) | DefForeignMod(_) => {}
+          DefVariant(_, variant_id, is_struct) => {
+              debug!("(building reduced graph for external crate) building \
+                      variant {}",
+                      final_ident);
+              // variants are always treated as importable to allow them to be
+              // glob used
+              let modifiers = PUBLIC | IMPORTABLE;
+              if is_struct {
+                  child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+                  // Not adding fields for variants as they are not accessed with a self receiver
+                  self.structs.insert(variant_id, Vec::new());
+              } else {
+                  child_name_bindings.define_value(def, DUMMY_SP, modifiers);
+              }
+          }
+          DefFn(ctor_id, true) => {
+            child_name_bindings.define_value(
+                csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
+                    .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
+          }
+          DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
+            debug!("(building reduced graph for external \
+                    crate) building value (fn/static) {}", final_ident);
+            // impl methods have already been defined with the correct importability modifier
+            let mut modifiers = match *child_name_bindings.value_def.borrow() {
+                Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
+                None => modifiers
+            };
+            if new_parent.kind.get() != NormalModuleKind {
+                modifiers = modifiers & !IMPORTABLE;
+            }
+            child_name_bindings.define_value(def, DUMMY_SP, modifiers);
+          }
+          DefTrait(def_id) => {
+              debug!("(building reduced graph for external \
+                      crate) building type {}", final_ident);
+
+              // If this is a trait, add all the trait item names to the trait
+              // info.
+
+              let trait_item_def_ids =
+                csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
+              for trait_item_def_id in trait_item_def_ids.iter() {
+                  let (trait_item_name, trait_item_kind) =
+                      csearch::get_trait_item_name_and_kind(
+                          &self.session.cstore,
+                          trait_item_def_id.def_id());
+
+                  debug!("(building reduced graph for external crate) ... \
+                          adding trait item '{}'",
+                         token::get_name(trait_item_name));
+
+                  self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
+
+                  if is_exported {
+                      self.external_exports
+                          .insert(trait_item_def_id.def_id());
+                  }
+              }
+
+              child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+
+              // Define a module if necessary.
+              let parent_link = self.get_parent_link(new_parent, name);
+              child_name_bindings.set_module_kind(parent_link,
+                                                  Some(def_id),
+                                                  TraitModuleKind,
+                                                  true,
+                                                  is_public,
+                                                  DUMMY_SP)
+          }
+          DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
+              debug!("(building reduced graph for external \
+                      crate) building type {}", final_ident);
+
+              child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+          }
+          DefStruct(def_id) => {
+            debug!("(building reduced graph for external \
+                    crate) building type and value for {}",
+                   final_ident);
+            child_name_bindings.define_type(def, DUMMY_SP, modifiers);
+            let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
+                f.name
+            }).collect::<Vec<_>>();
+
+            if fields.len() == 0 {
+                child_name_bindings.define_value(def, DUMMY_SP, modifiers);
+            }
+
+            // Record the def ID and fields of this struct.
+            self.structs.insert(def_id, fields);
+          }
+          DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
+          DefUse(..) | DefUpvar(..) | DefRegion(..) |
+          DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
+            panic!("didn't expect `{}`", def);
+          }
+        }
+    }
+
+    /// Builds the reduced graph for a single item in an external crate.
+    fn build_reduced_graph_for_external_crate_def(&mut self,
+                                                  root: &Rc<Module>,
+                                                  def_like: DefLike,
+                                                  name: Name,
+                                                  visibility: Visibility) {
+        match def_like {
+            DlDef(def) => {
+                // Add the new child item, if necessary.
+                match def {
+                    DefForeignMod(def_id) => {
+                        // Foreign modules have no names. Recur and populate
+                        // eagerly.
+                        csearch::each_child_of_item(&self.session.cstore,
+                                                    def_id,
+                                                    |def_like,
+                                                     child_name,
+                                                     vis| {
+                            self.build_reduced_graph_for_external_crate_def(
+                                root,
+                                def_like,
+                                child_name,
+                                vis)
+                        });
+                    }
+                    _ => {
+                        let child_name_bindings =
+                            self.add_child(name,
+                                           root,
+                                           OverwriteDuplicates,
+                                           DUMMY_SP);
+
+                        self.handle_external_def(def,
+                                                 visibility,
+                                                 &*child_name_bindings,
+                                                 token::get_name(name).get(),
+                                                 name,
+                                                 root);
+                    }
+                }
+            }
+            DlImpl(def) => {
+                match csearch::get_type_name_if_impl(&self.session.cstore, def) {
+                    None => {}
+                    Some(final_name) => {
+                        let methods_opt =
+                            csearch::get_methods_if_impl(&self.session.cstore, def);
+                        match methods_opt {
+                            Some(ref methods) if
+                                methods.len() >= 1 => {
+                                debug!("(building reduced graph for \
+                                        external crate) processing \
+                                        static methods for type name {}",
+                                        token::get_name(final_name));
+
+                                let child_name_bindings =
+                                    self.add_child(
+                                        final_name,
+                                        root,
+                                        OverwriteDuplicates,
+                                        DUMMY_SP);
+
+                                // Process the static methods. First,
+                                // create the module.
+                                let type_module;
+                                let type_def = child_name_bindings.type_def.borrow().clone();
+                                match type_def {
+                                    Some(TypeNsDef {
+                                        module_def: Some(module_def),
+                                        ..
+                                    }) => {
+                                        // We already have a module. This
+                                        // is OK.
+                                        type_module = module_def;
+
+                                        // Mark it as an impl module if
+                                        // necessary.
+                                        type_module.kind.set(ImplModuleKind);
+                                    }
+                                    Some(_) | None => {
+                                        let parent_link =
+                                            self.get_parent_link(root, final_name);
+                                        child_name_bindings.define_module(
+                                            parent_link,
+                                            Some(def),
+                                            ImplModuleKind,
+                                            true,
+                                            true,
+                                            DUMMY_SP);
+                                        type_module =
+                                            child_name_bindings.
+                                                get_module();
+                                    }
+                                }
+
+                                // Add each static method to the module.
+                                let new_parent = type_module;
+                                for method_info in methods.iter() {
+                                    let name = method_info.name;
+                                    debug!("(building reduced graph for \
+                                             external crate) creating \
+                                             static method '{}'",
+                                           token::get_name(name));
+
+                                    let method_name_bindings =
+                                        self.add_child(name,
+                                                       &new_parent,
+                                                       OverwriteDuplicates,
+                                                       DUMMY_SP);
+                                    let def = DefFn(method_info.def_id, false);
+
+                                    // NB: not IMPORTABLE
+                                    let modifiers = if visibility == ast::Public {
+                                        PUBLIC
+                                    } else {
+                                        DefModifiers::empty()
+                                    };
+                                    method_name_bindings.define_value(
+                                        def, DUMMY_SP, modifiers);
+                                }
+                            }
+
+                            // Otherwise, do nothing.
+                            Some(_) | None => {}
+                        }
+                    }
+                }
+            }
+            DlField => {
+                debug!("(building reduced graph for external crate) \
+                        ignoring field");
+            }
+        }
+    }
+
+    /// Builds the reduced graph rooted at the given external module.
+    fn populate_external_module(&mut self, module: &Rc<Module>) {
+        debug!("(populating external module) attempting to populate {}",
+               self.module_to_string(&**module));
+
+        let def_id = match module.def_id.get() {
+            None => {
+                debug!("(populating external module) ... no def ID!");
+                return
+            }
+            Some(def_id) => def_id,
+        };
+
+        csearch::each_child_of_item(&self.session.cstore,
+                                    def_id,
+                                    |def_like, child_name, visibility| {
+            debug!("(populating external module) ... found ident: {}",
+                   token::get_name(child_name));
+            self.build_reduced_graph_for_external_crate_def(module,
+                                                            def_like,
+                                                            child_name,
+                                                            visibility)
+        });
+        module.populated.set(true)
+    }
+
+    /// Ensures that the reduced graph rooted at the given external module
+    /// is built, building it if it is not.
+    fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
+        if !module.populated.get() {
+            self.populate_external_module(module)
+        }
+        assert!(module.populated.get())
+    }
+
+    /// Builds the reduced graph rooted at the 'use' directive for an external
+    /// crate.
+    fn build_reduced_graph_for_external_crate(&mut self, root: &Rc<Module>) {
+        csearch::each_top_level_item_of_crate(&self.session.cstore,
+                                              root.def_id
+                                                  .get()
+                                                  .unwrap()
+                                                  .krate,
+                                              |def_like, name, visibility| {
+            self.build_reduced_graph_for_external_crate_def(root, def_like, name, visibility)
+        });
+    }
+
+    /// Creates and adds an import directive to the given module.
+    fn build_import_directive(&mut self,
+                              module_: &Module,
+                              module_path: Vec<Name>,
+                              subclass: ImportDirectiveSubclass,
+                              span: Span,
+                              id: NodeId,
+                              is_public: bool,
+                              shadowable: Shadowable) {
+        module_.imports.borrow_mut().push(ImportDirective::new(module_path,
+                                                               subclass,
+                                                               span,
+                                                               id,
+                                                               is_public,
+                                                               shadowable));
+        self.unresolved_imports += 1;
+        // Bump the reference count on the name. Or, if this is a glob, set
+        // the appropriate flag.
+
+        match subclass {
+            SingleImport(target, _) => {
+                debug!("(building import directive) building import \
+                        directive: {}::{}",
+                       self.names_to_string(module_.imports.borrow().last().unwrap()
+                                                 .module_path[]),
+                       token::get_name(target));
+
+                let mut import_resolutions = module_.import_resolutions
+                                                    .borrow_mut();
+                match import_resolutions.get_mut(&target) {
+                    Some(resolution) => {
+                        debug!("(building import directive) bumping \
+                                reference");
+                        resolution.outstanding_references += 1;
+
+                        // the source of this name is different now
+                        resolution.type_id = id;
+                        resolution.value_id = id;
+                        resolution.is_public = is_public;
+                        return;
+                    }
+                    None => {}
+                }
+                debug!("(building import directive) creating new");
+                let mut resolution = ImportResolution::new(id, is_public);
+                resolution.outstanding_references = 1;
+                import_resolutions.insert(target, resolution);
+            }
+            GlobImport => {
+                // Set the glob flag. This tells us that we don't know the
+                // module's exports ahead of time.
+
+                module_.glob_count.set(module_.glob_count.get() + 1);
+            }
+        }
+    }
+}
+
+struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
+    builder: GraphBuilder<'a, 'b, 'tcx>,
+    parent: Rc<Module>
+}
+
+impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
+        let p = self.builder.build_reduced_graph_for_item(item, &self.parent);
+        let old_parent = replace(&mut self.parent, p);
+        visit::walk_item(self, item);
+        self.parent = old_parent;
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
+        let parent = &self.parent;
+        self.builder.build_reduced_graph_for_foreign_item(foreign_item,
+                                                          parent,
+                                                          |r| {
+            let mut v = BuildReducedGraphVisitor {
+                builder: GraphBuilder { resolver: r },
+                parent: parent.clone()
+            };
+            visit::walk_foreign_item(&mut v, foreign_item);
+        })
+    }
+
+    fn visit_view_item(&mut self, view_item: &ViewItem) {
+        self.builder.build_reduced_graph_for_view_item(view_item, &self.parent);
+    }
+
+    fn visit_block(&mut self, block: &Block) {
+        let np = self.builder.build_reduced_graph_for_block(block, &self.parent);
+        let old_parent = replace(&mut self.parent, np);
+        visit::walk_block(self, block);
+        self.parent = old_parent;
+    }
+}
+
+pub fn build_reduced_graph(resolver: &mut Resolver, krate: &ast::Crate) {
+    GraphBuilder {
+        resolver: resolver
+    }.build_reduced_graph(krate);
+}
+
+pub fn populate_module_if_necessary(resolver: &mut Resolver, module: &Rc<Module>) {
+    GraphBuilder {
+        resolver: resolver
+    }.populate_module_if_necessary(module);
+}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index c168709eec5..10756f21551 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -26,11 +26,9 @@ extern crate rustc;
 
 use self::PatternBindingMode::*;
 use self::Namespace::*;
-use self::NamespaceError::*;
 use self::NamespaceResult::*;
 use self::NameDefinition::*;
 use self::ImportDirectiveSubclass::*;
-use self::ReducedGraphParent::*;
 use self::ResolveResult::*;
 use self::FallbackSuggestion::*;
 use self::TypeParameters::*;
@@ -40,7 +38,6 @@ use self::UseLexicalScopeFlag::*;
 use self::ModulePrefixResult::*;
 use self::NameSearchType::*;
 use self::BareIdentifierPatternResolution::*;
-use self::DuplicateCheckingMode::*;
 use self::ParentLink::*;
 use self::ModuleKind::*;
 use self::TraitReferenceType::*;
@@ -60,46 +57,45 @@ use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
 use rustc::util::lev_distance::lev_distance;
 
 use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
-use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
+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::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics};
+use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
 use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn};
 use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
 use syntax::ast::{ItemStruct, ItemTrait, ItemTy, Local, LOCAL_CRATE};
-use syntax::ast::{MethodImplItem, Mod, Name, NamedField, NodeId};
+use syntax::ast::{MethodImplItem, Mod, Name, NodeId};
 use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
-use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod};
-use syntax::ast::{PolyTraitRef, PrimTy, Public, SelfExplicit, SelfStatic};
-use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
-use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound};
-use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
+use syntax::ast::{PatRange, PatStruct, Path};
+use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit};
+use syntax::ast::{RegionTyParamBound, StructField};
+use syntax::ast::{TraitRef, TraitTyParamBound};
+use syntax::ast::{Ty, TyBool, TyChar, TyClosure, TyF32};
 use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum};
 use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath};
 use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
-use syntax::ast::{TypeImplItem, UnnamedField};
-use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
-use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
-use syntax::ast::{Visibility};
+use syntax::ast::{TypeImplItem};
 use syntax::ast;
 use syntax::ast_map;
-use syntax::ast_util::{mod, PostExpansionMethod, local_def, walk_pat};
+use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
 use syntax::parse::token::{mod, special_names, special_idents};
-use syntax::codemap::{Span, DUMMY_SP, Pos};
+use syntax::codemap::{Span, Pos};
 use syntax::owned_slice::OwnedSlice;
 use syntax::visit::{mod, Visitor};
 
 use std::collections::{HashMap, HashSet};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::cell::{Cell, RefCell};
+use std::fmt;
 use std::mem::replace;
 use std::rc::{Rc, Weak};
 use std::uint;
 
 mod check_unused;
 mod record_exports;
+mod build_reduced_graph;
 
 #[deriving(Copy)]
 struct BindingInfo {
@@ -123,14 +119,6 @@ enum Namespace {
     ValueNS
 }
 
-#[deriving(Copy, PartialEq)]
-enum NamespaceError {
-    NoError,
-    ModuleError,
-    TypeError,
-    ValueError
-}
-
 /// A NamespaceResult represents the result of resolving an import in
 /// a particular namespace. The result is either definitely-resolved,
 /// definitely- unresolved, or unknown.
@@ -191,28 +179,12 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
 }
 
 /// Contains data for specific types of import directives.
-#[deriving(Copy)]
+#[deriving(Copy,Show)]
 enum ImportDirectiveSubclass {
     SingleImport(Name /* target */, Name /* source */),
     GlobImport
 }
 
-/// The context that we thread through while building the reduced graph.
-#[deriving(Clone)]
-enum ReducedGraphParent {
-    ModuleReducedGraphParent(Rc<Module>)
-}
-
-impl ReducedGraphParent {
-    fn module(&self) -> Rc<Module> {
-        match *self {
-            ModuleReducedGraphParent(ref m) => {
-                m.clone()
-            }
-        }
-    }
-}
-
 type ErrorMessage = Option<(Span, String)>;
 
 enum ResolveResult<T> {
@@ -314,17 +286,6 @@ enum BareIdentifierPatternResolution {
     BareIdentifierPatternUnresolved
 }
 
-// Specifies how duplicates should be handled when adding a child item if
-// another item exists with the same name in some namespace.
-#[deriving(Copy, PartialEq)]
-enum DuplicateCheckingMode {
-    ForbidDuplicateModules,
-    ForbidDuplicateTypesAndModules,
-    ForbidDuplicateValues,
-    ForbidDuplicateTypesAndValues,
-    OverwriteDuplicates
-}
-
 /// One local scope.
 #[deriving(Show)]
 struct Rib {
@@ -345,13 +306,11 @@ impl Rib {
 #[deriving(Show,PartialEq,Clone,Copy)]
 enum Shadowable {
     Always,
-    /// Means that the recorded import obeys the glob shadowing rules, i.e., can
-    /// only be shadowed by another glob import.
-    Glob,
     Never
 }
 
 /// One import directive.
+#[deriving(Show)]
 struct ImportDirective {
     module_path: Vec<Name>,
     subclass: ImportDirectiveSubclass,
@@ -381,7 +340,7 @@ impl ImportDirective {
 }
 
 /// The item that an import resolves to.
-#[deriving(Clone)]
+#[deriving(Clone,Show)]
 struct Target {
     target_module: Rc<Module>,
     bindings: Rc<NameBindings>,
@@ -402,6 +361,7 @@ impl Target {
 }
 
 /// An ImportResolution represents a particular `use` directive.
+#[deriving(Show)]
 struct ImportResolution {
     /// Whether this resolution came from a `use` or a `pub use`. Note that this
     /// should *not* be used whenever resolution is being performed, this is
@@ -462,10 +422,26 @@ impl ImportResolution {
 
         target.unwrap().shadowable
     }
+
+    fn set_target_and_id(&mut self,
+                         namespace: Namespace,
+                         target: Option<Target>,
+                         id: NodeId) {
+        match namespace {
+            TypeNS  => {
+                self.type_target = target;
+                self.type_id = id;
+            }
+            ValueNS => {
+                self.value_target = target;
+                self.value_id = id;
+            }
+        }
+    }
 }
 
 /// The link from a module up to its nearest parent node.
-#[deriving(Clone)]
+#[deriving(Clone,Show)]
 enum ParentLink {
     NoParentLink,
     ModuleParentLink(Weak<Module>, Name),
@@ -473,7 +449,7 @@ enum ParentLink {
 }
 
 /// The type of module this is.
-#[deriving(Copy, PartialEq)]
+#[deriving(Copy, PartialEq, Show)]
 enum ModuleKind {
     NormalModuleKind,
     TraitModuleKind,
@@ -555,6 +531,15 @@ impl Module {
     }
 }
 
+impl fmt::Show for Module {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}, kind: {}, {}",
+               self.def_id,
+               self.kind,
+               if self.is_public { "public" } else { "private" } )
+    }
+}
+
 bitflags! {
     #[deriving(Show)]
     flags DefModifiers: u8 {
@@ -564,7 +549,7 @@ bitflags! {
 }
 
 // Records a possibly-private type definition.
-#[deriving(Clone)]
+#[deriving(Clone,Show)]
 struct TypeNsDef {
     modifiers: DefModifiers, // see note in ImportResolution about how to use this
     module_def: Option<Rc<Module>>,
@@ -582,6 +567,7 @@ struct ValueNsDef {
 
 // Records the definitions (at most one for each namespace) that a name is
 // bound to.
+#[deriving(Show)]
 struct NameBindings {
     type_def: RefCell<Option<TypeNsDef>>,   //< Meaning in type namespace.
     value_def: RefCell<Option<ValueNsDef>>, //< Meaning in value namespace.
@@ -852,15 +838,6 @@ impl PrimitiveTypeTable {
     }
 }
 
-
-fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
-    match ns {
-        NoError                 => "",
-        ModuleError | TypeError => "type or module",
-        ValueError              => "value",
-    }
-}
-
 /// The main resolver class.
 struct Resolver<'a, 'tcx:'a> {
     session: &'a Session,
@@ -926,46 +903,6 @@ struct Resolver<'a, 'tcx:'a> {
     used_crates: HashSet<CrateNum>,
 }
 
-struct BuildReducedGraphVisitor<'a, 'b:'a, 'tcx:'b> {
-    resolver: &'a mut Resolver<'b, 'tcx>,
-    parent: ReducedGraphParent
-}
-
-impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
-
-    fn visit_item(&mut self, item: &Item) {
-        let p = self.resolver.build_reduced_graph_for_item(item, self.parent.clone());
-        let old_parent = replace(&mut self.parent, p);
-        visit::walk_item(self, item);
-        self.parent = old_parent;
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        let parent = self.parent.clone();
-        self.resolver.build_reduced_graph_for_foreign_item(foreign_item,
-                                                           parent.clone(),
-                                                           |r| {
-            let mut v = BuildReducedGraphVisitor {
-                resolver: r,
-                parent: parent.clone()
-            };
-            visit::walk_foreign_item(&mut v, foreign_item);
-        })
-    }
-
-    fn visit_view_item(&mut self, view_item: &ViewItem) {
-        self.resolver.build_reduced_graph_for_view_item(view_item, self.parent.clone());
-    }
-
-    fn visit_block(&mut self, block: &Block) {
-        let np = self.resolver.build_reduced_graph_for_block(block, self.parent.clone());
-        let old_parent = replace(&mut self.parent, np);
-        visit::walk_block(self, block);
-        self.parent = old_parent;
-    }
-
-}
-
 #[deriving(PartialEq)]
 enum FallbackChecks {
     Everything,
@@ -1034,1195 +971,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
-    //
-    // Reduced graph building
-    //
-    // Here we build the "reduced graph": the graph of the module tree without
-    // any imports resolved.
-    //
-
-    /// Constructs the reduced graph for the entire crate.
-    fn build_reduced_graph(&mut self, krate: &ast::Crate) {
-        let parent = ModuleReducedGraphParent(self.graph_root.get_module());
-        let mut visitor = BuildReducedGraphVisitor {
-            resolver: self,
-            parent: parent
-        };
-        visit::walk_crate(&mut visitor, krate);
-    }
-
-    /// Adds a new child item to the module definition of the parent node and
-    /// returns its corresponding name bindings as well as the current parent.
-    /// Or, if we're inside a block, creates (or reuses) an anonymous module
-    /// corresponding to the innermost block ID and returns the name bindings
-    /// as well as the newly-created parent.
-    ///
-    /// # Panics
-    ///
-    /// Panics if this node does not have a module definition and we are not inside
-    /// a block.
-    fn add_child(&self,
-                 name: Name,
-                 reduced_graph_parent: ReducedGraphParent,
-                 duplicate_checking_mode: DuplicateCheckingMode,
-                 // For printing errors
-                 sp: Span)
-                 -> Rc<NameBindings> {
-        // If this is the immediate descendant of a module, then we add the
-        // child name directly. Otherwise, we create or reuse an anonymous
-        // module and add the child to that.
-
-        let module_ = reduced_graph_parent.module();
-
-        self.check_for_conflicts_between_external_crates_and_items(&*module_,
-                                                                   name,
-                                                                   sp);
-
-        // Add or reuse the child.
-        let child = module_.children.borrow().get(&name).cloned();
-        match child {
-            None => {
-                let child = Rc::new(NameBindings::new());
-                module_.children.borrow_mut().insert(name, child.clone());
-                child
-            }
-            Some(child) => {
-                // Enforce the duplicate checking mode:
-                //
-                // * If we're requesting duplicate module checking, check that
-                //   there isn't a module in the module with the same name.
-                //
-                // * If we're requesting duplicate type checking, check that
-                //   there isn't a type in the module with the same name.
-                //
-                // * If we're requesting duplicate value checking, check that
-                //   there isn't a value in the module with the same name.
-                //
-                // * If we're requesting duplicate type checking and duplicate
-                //   value checking, check that there isn't a duplicate type
-                //   and a duplicate value with the same name.
-                //
-                // * If no duplicate checking was requested at all, do
-                //   nothing.
-
-                let mut duplicate_type = NoError;
-                let ns = match duplicate_checking_mode {
-                    ForbidDuplicateModules => {
-                        if child.get_module_if_available().is_some() {
-                            duplicate_type = ModuleError;
-                        }
-                        Some(TypeNS)
-                    }
-                    ForbidDuplicateTypesAndModules => {
-                        match child.def_for_namespace(TypeNS) {
-                            None => {}
-                            Some(_) if child.get_module_if_available()
-                                            .map(|m| m.kind.get()) ==
-                                       Some(ImplModuleKind) => {}
-                            Some(_) => duplicate_type = TypeError
-                        }
-                        Some(TypeNS)
-                    }
-                    ForbidDuplicateValues => {
-                        if child.defined_in_namespace(ValueNS) {
-                            duplicate_type = ValueError;
-                        }
-                        Some(ValueNS)
-                    }
-                    ForbidDuplicateTypesAndValues => {
-                        let mut n = None;
-                        match child.def_for_namespace(TypeNS) {
-                            Some(DefMod(_)) | None => {}
-                            Some(_) => {
-                                n = Some(TypeNS);
-                                duplicate_type = TypeError;
-                            }
-                        };
-                        if child.defined_in_namespace(ValueNS) {
-                            duplicate_type = ValueError;
-                            n = Some(ValueNS);
-                        }
-                        n
-                    }
-                    OverwriteDuplicates => None
-                };
-                if duplicate_type != NoError {
-                    // Return an error here by looking up the namespace that
-                    // had the duplicate.
-                    let ns = ns.unwrap();
-                    self.resolve_error(sp,
-                        format!("duplicate definition of {} `{}`",
-                             namespace_error_to_string(duplicate_type),
-                             token::get_name(name))[]);
-                    {
-                        let r = child.span_for_namespace(ns);
-                        for sp in r.iter() {
-                            self.session.span_note(*sp,
-                                 format!("first definition of {} `{}` here",
-                                      namespace_error_to_string(duplicate_type),
-                                      token::get_name(name))[]);
-                        }
-                    }
-                }
-                child
-            }
-        }
-    }
-
-    fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
-        // If the block has view items, we need an anonymous module.
-        if block.view_items.len() > 0 {
-            return true;
-        }
-
-        // Check each statement.
-        for statement in block.stmts.iter() {
-            match statement.node {
-                StmtDecl(ref declaration, _) => {
-                    match declaration.node {
-                        DeclItem(_) => {
-                            return true;
-                        }
-                        _ => {
-                            // Keep searching.
-                        }
-                    }
-                }
-                _ => {
-                    // Keep searching.
-                }
-            }
-        }
-
-        // If we found neither view items nor items, we don't need to create
-        // an anonymous module.
-
-        return false;
-    }
-
-    fn get_parent_link(&mut self, parent: ReducedGraphParent, name: Name)
-                       -> ParentLink {
-        match parent {
-            ModuleReducedGraphParent(module_) => {
-                return ModuleParentLink(module_.downgrade(), name);
-            }
-        }
-    }
-
-    /// Constructs the reduced graph for one item.
-    fn build_reduced_graph_for_item(&mut self,
-                                    item: &Item,
-                                    parent: ReducedGraphParent)
-                                    -> ReducedGraphParent
-    {
-        let name = item.ident.name;
-        let sp = item.span;
-        let is_public = item.vis == ast::Public;
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
-
-        match item.node {
-            ItemMod(..) => {
-                let name_bindings =
-                    self.add_child(name, parent.clone(), ForbidDuplicateModules, sp);
-
-                let parent_link = self.get_parent_link(parent, name);
-                let def_id = DefId { krate: 0, node: item.id };
-                name_bindings.define_module(parent_link,
-                                            Some(def_id),
-                                            NormalModuleKind,
-                                            false,
-                                            item.vis == ast::Public,
-                                            sp);
-
-                ModuleReducedGraphParent(name_bindings.get_module())
-            }
-
-            ItemForeignMod(..) => parent,
-
-            // These items live in the value namespace.
-            ItemStatic(_, m, _) => {
-                let name_bindings =
-                    self.add_child(name, parent.clone(), ForbidDuplicateValues, sp);
-                let mutbl = m == ast::MutMutable;
-
-                name_bindings.define_value
-                    (DefStatic(local_def(item.id), mutbl), sp, modifiers);
-                parent
-            }
-            ItemConst(_, _) => {
-                self.add_child(name, parent.clone(), ForbidDuplicateValues, sp)
-                    .define_value(DefConst(local_def(item.id)),
-                                  sp, modifiers);
-                parent
-            }
-            ItemFn(_, _, _, _, _) => {
-                let name_bindings =
-                    self.add_child(name, parent.clone(), ForbidDuplicateValues, sp);
-
-                let def = DefFn(local_def(item.id), false);
-                name_bindings.define_value(def, sp, modifiers);
-                parent
-            }
-
-            // These items live in the type namespace.
-            ItemTy(..) => {
-                let name_bindings =
-                    self.add_child(name,
-                                   parent.clone(),
-                                   ForbidDuplicateTypesAndModules,
-                                   sp);
-
-                name_bindings.define_type
-                    (DefTy(local_def(item.id), false), sp, modifiers);
-                parent
-            }
-
-            ItemEnum(ref enum_definition, _) => {
-                let name_bindings =
-                    self.add_child(name,
-                                   parent.clone(),
-                                   ForbidDuplicateTypesAndModules,
-                                   sp);
-
-                name_bindings.define_type
-                    (DefTy(local_def(item.id), true), sp, modifiers);
-
-                let parent_link = self.get_parent_link(parent.clone(), name);
-                // We want to make sure the module type is EnumModuleKind
-                // even if there's already an ImplModuleKind module defined,
-                // since that's how we prevent duplicate enum definitions
-                name_bindings.set_module_kind(parent_link,
-                                              Some(local_def(item.id)),
-                                              EnumModuleKind,
-                                              false,
-                                              is_public,
-                                              sp);
-
-                for variant in (*enum_definition).variants.iter() {
-                    self.build_reduced_graph_for_variant(
-                        &**variant,
-                        local_def(item.id),
-                        ModuleReducedGraphParent(name_bindings.get_module()));
-                }
-                parent
-            }
-
-            // These items live in both the type and value namespaces.
-            ItemStruct(ref struct_def, _) => {
-                // Adding to both Type and Value namespaces or just Type?
-                let (forbid, ctor_id) = match struct_def.ctor_id {
-                    Some(ctor_id)   => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
-                    None            => (ForbidDuplicateTypesAndModules, None)
-                };
-
-                let name_bindings = self.add_child(name, parent.clone(), forbid, sp);
-
-                // Define a name in the type namespace.
-                name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
-
-                // If this is a newtype or unit-like struct, define a name
-                // in the value namespace as well
-                match ctor_id {
-                    Some(cid) => {
-                        name_bindings.define_value(DefStruct(local_def(cid)),
-                                                   sp, modifiers);
-                    }
-                    None => {}
-                }
-
-                // Record the def ID and fields of this struct.
-                let named_fields = struct_def.fields.iter().filter_map(|f| {
-                    match f.node.kind {
-                        NamedField(ident, _) => Some(ident.name),
-                        UnnamedField(_) => None
-                    }
-                }).collect();
-                self.structs.insert(local_def(item.id), named_fields);
-
-                parent
-            }
-
-            ItemImpl(_, _, None, ref ty, ref impl_items) => {
-                // If this implements an anonymous trait, then add all the
-                // methods within to a new module, if the type was defined
-                // within this module.
-
-                let mod_name = match ty.node {
-                    TyPath(ref path, _) if path.segments.len() == 1 => {
-                        // FIXME(18446) we should distinguish between the name of
-                        // a trait and the name of an impl of that trait.
-                        Some(path.segments.last().unwrap().identifier.name)
-                    }
-                    TyObjectSum(ref lhs_ty, _) => {
-                        match lhs_ty.node {
-                            TyPath(ref path, _) if path.segments.len() == 1 => {
-                                Some(path.segments.last().unwrap().identifier.name)
-                            }
-                            _ => {
-                                None
-                            }
-                        }
-                    }
-                    _ => {
-                        None
-                    }
-                };
-
-                match mod_name {
-                    None => {
-                        self.resolve_error(ty.span,
-                                           "inherent implementations may \
-                                            only be implemented in the same \
-                                            module as the type they are \
-                                            implemented for")
-                    }
-                    Some(mod_name) => {
-                        // Create the module and add all methods.
-                        let parent_opt = parent.module().children.borrow()
-                            .get(&mod_name).cloned();
-                        let new_parent = match parent_opt {
-                            // It already exists
-                            Some(ref child) if child.get_module_if_available()
-                                .is_some() &&
-                                (child.get_module().kind.get() == ImplModuleKind ||
-                                 child.get_module().kind.get() == TraitModuleKind) => {
-                                    ModuleReducedGraphParent(child.get_module())
-                                }
-                            Some(ref child) if child.get_module_if_available()
-                                .is_some() &&
-                                child.get_module().kind.get() ==
-                                EnumModuleKind => {
-                                    ModuleReducedGraphParent(child.get_module())
-                                }
-                            // Create the module
-                            _ => {
-                                let name_bindings =
-                                    self.add_child(mod_name,
-                                                   parent.clone(),
-                                                   ForbidDuplicateModules,
-                                                   sp);
-
-                                let parent_link =
-                                    self.get_parent_link(parent.clone(), name);
-                                let def_id = local_def(item.id);
-                                let ns = TypeNS;
-                                let is_public =
-                                    !name_bindings.defined_in_namespace(ns) ||
-                                    name_bindings.defined_in_public_namespace(ns);
-
-                                name_bindings.define_module(parent_link,
-                                                            Some(def_id),
-                                                            ImplModuleKind,
-                                                            false,
-                                                            is_public,
-                                                            sp);
-
-                                ModuleReducedGraphParent(
-                                    name_bindings.get_module())
-                            }
-                        };
-
-                        // For each implementation item...
-                        for impl_item in impl_items.iter() {
-                            match *impl_item {
-                                MethodImplItem(ref method) => {
-                                    // Add the method to the module.
-                                    let name = method.pe_ident().name;
-                                    let method_name_bindings =
-                                        self.add_child(name,
-                                                       new_parent.clone(),
-                                                       ForbidDuplicateValues,
-                                                       method.span);
-                                    let def = match method.pe_explicit_self()
-                                        .node {
-                                            SelfStatic => {
-                                                // Static methods become
-                                                // `DefStaticMethod`s.
-                                                DefStaticMethod(local_def(method.id),
-                                                                FromImpl(local_def(item.id)))
-                                            }
-                                            _ => {
-                                                // Non-static methods become
-                                                // `DefMethod`s.
-                                                DefMethod(local_def(method.id),
-                                                          None,
-                                                          FromImpl(local_def(item.id)))
-                                            }
-                                        };
-
-                                    // NB: not IMPORTABLE
-                                    let modifiers = if method.pe_vis() == ast::Public {
-                                        PUBLIC
-                                    } else {
-                                        DefModifiers::empty()
-                                    };
-                                    method_name_bindings.define_value(
-                                        def,
-                                        method.span,
-                                        modifiers);
-                                }
-                                TypeImplItem(ref typedef) => {
-                                    // Add the typedef to the module.
-                                    let name = typedef.ident.name;
-                                    let typedef_name_bindings =
-                                        self.add_child(
-                                            name,
-                                            new_parent.clone(),
-                                            ForbidDuplicateTypesAndModules,
-                                            typedef.span);
-                                    let def = DefAssociatedTy(local_def(
-                                        typedef.id));
-                                    // NB: not IMPORTABLE
-                                    let modifiers = if typedef.vis == ast::Public {
-                                        PUBLIC
-                                    } else {
-                                        DefModifiers::empty()
-                                    };
-                                    typedef_name_bindings.define_type(
-                                        def,
-                                        typedef.span,
-                                        modifiers);
-                                }
-                            }
-                        }
-                    }
-                }
-
-                parent
-            }
-
-            ItemImpl(_, _, Some(_), _, _) => parent,
-
-            ItemTrait(_, _, _, _, ref items) => {
-                let name_bindings =
-                    self.add_child(name,
-                                   parent.clone(),
-                                   ForbidDuplicateTypesAndModules,
-                                   sp);
-
-                // Add all the items within to a new module.
-                let parent_link = self.get_parent_link(parent.clone(), name);
-                name_bindings.define_module(parent_link,
-                                            Some(local_def(item.id)),
-                                            TraitModuleKind,
-                                            false,
-                                            item.vis == ast::Public,
-                                            sp);
-                let module_parent = ModuleReducedGraphParent(name_bindings.
-                                                             get_module());
-
-                let def_id = local_def(item.id);
-
-                // Add the names of all the items to the trait info.
-                for trait_item in items.iter() {
-                    let (name, kind) = match *trait_item {
-                        ast::RequiredMethod(_) |
-                        ast::ProvidedMethod(_) => {
-                            let ty_m = ast_util::trait_item_to_ty_method(trait_item);
-
-                            let name = ty_m.ident.name;
-
-                            // Add it as a name in the trait module.
-                            let (def, static_flag) = match ty_m.explicit_self
-                                                               .node {
-                                SelfStatic => {
-                                    // Static methods become `DefStaticMethod`s.
-                                    (DefStaticMethod(
-                                            local_def(ty_m.id),
-                                            FromTrait(local_def(item.id))),
-                                     StaticMethodTraitItemKind)
-                                }
-                                _ => {
-                                    // Non-static methods become `DefMethod`s.
-                                    (DefMethod(local_def(ty_m.id),
-                                               Some(local_def(item.id)),
-                                               FromTrait(local_def(item.id))),
-                                     NonstaticMethodTraitItemKind)
-                                }
-                            };
-
-                            let method_name_bindings =
-                                self.add_child(name,
-                                               module_parent.clone(),
-                                               ForbidDuplicateTypesAndValues,
-                                               ty_m.span);
-                            // NB: not IMPORTABLE
-                            method_name_bindings.define_value(def,
-                                                              ty_m.span,
-                                                              PUBLIC);
-
-                            (name, static_flag)
-                        }
-                        ast::TypeTraitItem(ref associated_type) => {
-                            let def = DefAssociatedTy(local_def(
-                                    associated_type.ty_param.id));
-
-                            let name_bindings =
-                                self.add_child(associated_type.ty_param.ident.name,
-                                               module_parent.clone(),
-                                               ForbidDuplicateTypesAndValues,
-                                               associated_type.ty_param.span);
-                            // NB: not IMPORTABLE
-                            name_bindings.define_type(def,
-                                                      associated_type.ty_param.span,
-                                                      PUBLIC);
-
-                            (associated_type.ty_param.ident.name, TypeTraitItemKind)
-                        }
-                    };
-
-                    self.trait_item_map.insert((name, def_id), kind);
-                }
-
-                name_bindings.define_type(DefTrait(def_id), sp, modifiers);
-                parent
-            }
-            ItemMac(..) => parent
-        }
-    }
-
-    // Constructs the reduced graph for one variant. Variants exist in the
-    // type and value namespaces.
-    fn build_reduced_graph_for_variant(&mut self,
-                                       variant: &Variant,
-                                       item_id: DefId,
-                                       parent: ReducedGraphParent) {
-        let name = variant.node.name.name;
-        let is_exported = match variant.node.kind {
-            TupleVariantKind(_) => false,
-            StructVariantKind(_) => {
-                // Not adding fields for variants as they are not accessed with a self receiver
-                self.structs.insert(local_def(variant.node.id), Vec::new());
-                true
-            }
-        };
-
-        let child = self.add_child(name, parent,
-                                   ForbidDuplicateTypesAndValues,
-                                   variant.span);
-        // variants are always treated as importable to allow them to be glob
-        // used
-        child.define_value(DefVariant(item_id,
-                                      local_def(variant.node.id), is_exported),
-                           variant.span, PUBLIC | IMPORTABLE);
-        child.define_type(DefVariant(item_id,
-                                     local_def(variant.node.id), is_exported),
-                          variant.span, PUBLIC | IMPORTABLE);
-    }
-
-    /// Constructs the reduced graph for one 'view item'. View items consist
-    /// of imports and use directives.
-    fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem,
-                                         parent: ReducedGraphParent) {
-        match view_item.node {
-            ViewItemUse(ref view_path) => {
-                // Extract and intern the module part of the path. For
-                // globs and lists, the path is found directly in the AST;
-                // for simple paths we have to munge the path a little.
-                let module_path = match view_path.node {
-                    ViewPathSimple(_, ref full_path, _) => {
-                        full_path.segments
-                            .init()
-                            .iter().map(|ident| ident.identifier.name)
-                            .collect()
-                    }
-
-                    ViewPathGlob(ref module_ident_path, _) |
-                    ViewPathList(ref module_ident_path, _, _) => {
-                        module_ident_path.segments
-                            .iter().map(|ident| ident.identifier.name).collect()
-                    }
-                };
-
-                // Build up the import directives.
-                let module_ = parent.module();
-                let is_public = view_item.vis == ast::Public;
-                let shadowable =
-                    view_item.attrs
-                             .iter()
-                             .any(|attr| {
-                                 attr.name() == token::get_name(
-                                    special_idents::prelude_import.name)
-                             });
-                let shadowable = if shadowable {
-                    Shadowable::Always
-                } else {
-                    Shadowable::Never
-                };
-
-                match view_path.node {
-                    ViewPathSimple(binding, ref full_path, id) => {
-                        let source_name =
-                            full_path.segments.last().unwrap().identifier.name;
-                        if token::get_name(source_name).get() == "mod" {
-                            self.resolve_error(view_path.span,
-                                "`mod` imports are only allowed within a { } list");
-                        }
-
-                        let subclass = SingleImport(binding.name,
-                                                    source_name);
-                        self.build_import_directive(&*module_,
-                                                    module_path,
-                                                    subclass,
-                                                    view_path.span,
-                                                    id,
-                                                    is_public,
-                                                    shadowable);
-                    }
-                    ViewPathList(_, ref source_items, _) => {
-                        // Make sure there's at most one `mod` import in the list.
-                        let mod_spans = source_items.iter().filter_map(|item| match item.node {
-                            PathListMod { .. } => Some(item.span),
-                            _ => None
-                        }).collect::<Vec<Span>>();
-                        if mod_spans.len() > 1 {
-                            self.resolve_error(mod_spans[0],
-                                "`mod` import can only appear once in the list");
-                            for other_span in mod_spans.iter().skip(1) {
-                                self.session.span_note(*other_span,
-                                    "another `mod` import appears here");
-                            }
-                        }
-
-                        for source_item in source_items.iter() {
-                            let (module_path, name) = match source_item.node {
-                                PathListIdent { name, .. } =>
-                                    (module_path.clone(), name.name),
-                                PathListMod { .. } => {
-                                    let name = match module_path.last() {
-                                        Some(name) => *name,
-                                        None => {
-                                            self.resolve_error(source_item.span,
-                                                "`mod` import can only appear in an import list \
-                                                 with a non-empty prefix");
-                                            continue;
-                                        }
-                                    };
-                                    let module_path = module_path.init();
-                                    (module_path.to_vec(), name)
-                                }
-                            };
-                            self.build_import_directive(
-                                &*module_,
-                                module_path,
-                                SingleImport(name, name),
-                                source_item.span,
-                                source_item.node.id(),
-                                is_public,
-                                shadowable);
-                        }
-                    }
-                    ViewPathGlob(_, id) => {
-                        self.build_import_directive(&*module_,
-                                                    module_path,
-                                                    GlobImport,
-                                                    view_path.span,
-                                                    id,
-                                                    is_public,
-                                                    if shadowable == Shadowable::Never {
-                                                        Shadowable::Glob
-                                                    } else {
-                                                        shadowable
-                                                    });
-                    }
-                }
-            }
-
-            ViewItemExternCrate(name, _, node_id) => {
-                // n.b. we don't need to look at the path option here, because cstore already did
-                for &crate_id in self.session.cstore
-                                     .find_extern_mod_stmt_cnum(node_id).iter() {
-                    let def_id = DefId { krate: crate_id, node: 0 };
-                    self.external_exports.insert(def_id);
-                    let parent_link =
-                        ModuleParentLink(parent.module().downgrade(), name.name);
-                    let external_module = Rc::new(Module::new(parent_link,
-                                                              Some(def_id),
-                                                              NormalModuleKind,
-                                                              false,
-                                                              true));
-                    debug!("(build reduced graph for item) found extern `{}`",
-                            self.module_to_string(&*external_module));
-                    self.check_for_conflicts_between_external_crates(
-                        &*parent.module(),
-                        name.name,
-                        view_item.span);
-                    parent.module().external_module_children.borrow_mut()
-                                   .insert(name.name, external_module.clone());
-                    self.build_reduced_graph_for_external_crate(external_module);
-                }
-            }
-        }
-    }
-
-    /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item<F>(&mut self,
-                                               foreign_item: &ForeignItem,
-                                               parent: ReducedGraphParent,
-                                               f: F) where
-        F: FnOnce(&mut Resolver),
-    {
-        let name = foreign_item.ident.name;
-        let is_public = foreign_item.vis == ast::Public;
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
-        let name_bindings =
-            self.add_child(name, parent, ForbidDuplicateValues,
-                           foreign_item.span);
-
-        match foreign_item.node {
-            ForeignItemFn(_, ref generics) => {
-                let def = DefFn(local_def(foreign_item.id), false);
-                name_bindings.define_value(def, foreign_item.span, modifiers);
-
-                self.with_type_parameter_rib(
-                    HasTypeParameters(generics,
-                                      FnSpace,
-                                      foreign_item.id,
-                                      NormalRibKind),
-                    f);
-            }
-            ForeignItemStatic(_, m) => {
-                let def = DefStatic(local_def(foreign_item.id), m);
-                name_bindings.define_value(def, foreign_item.span, modifiers);
-
-                f(self)
-            }
-        }
-    }
-
-    fn build_reduced_graph_for_block(&mut self,
-                                         block: &Block,
-                                         parent: ReducedGraphParent)
-                                            -> ReducedGraphParent
-    {
-        if self.block_needs_anonymous_module(block) {
-            let block_id = block.id;
-
-            debug!("(building reduced graph for block) creating a new \
-                    anonymous module for block {}",
-                   block_id);
-
-            let parent_module = parent.module();
-            let new_module = Rc::new(Module::new(
-                BlockParentLink(parent_module.downgrade(), block_id),
-                None,
-                AnonymousModuleKind,
-                false,
-                false));
-            parent_module.anonymous_children.borrow_mut()
-                         .insert(block_id, new_module.clone());
-            ModuleReducedGraphParent(new_module)
-        } else {
-            parent
-        }
-    }
-
-    fn handle_external_def(&mut self,
-                           def: Def,
-                           vis: Visibility,
-                           child_name_bindings: &NameBindings,
-                           final_ident: &str,
-                           name: Name,
-                           new_parent: ReducedGraphParent) {
-        debug!("(building reduced graph for \
-                external crate) building external def, priv {}",
-               vis);
-        let is_public = vis == ast::Public;
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
-        let is_exported = is_public && match new_parent {
-            ModuleReducedGraphParent(ref module) => {
-                match module.def_id.get() {
-                    None => true,
-                    Some(did) => self.external_exports.contains(&did)
-                }
-            }
-        };
-        if is_exported {
-            self.external_exports.insert(def.def_id());
-        }
-
-        let kind = match def {
-            DefTy(_, true) => EnumModuleKind,
-            DefStruct(..) | DefTy(..) => ImplModuleKind,
-            _ => NormalModuleKind
-        };
-
-        match def {
-          DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
-          DefTy(def_id, _) => {
-            let type_def = child_name_bindings.type_def.borrow().clone();
-            match type_def {
-              Some(TypeNsDef { module_def: Some(module_def), .. }) => {
-                debug!("(building reduced graph for external crate) \
-                        already created module");
-                module_def.def_id.set(Some(def_id));
-              }
-              Some(_) | None => {
-                debug!("(building reduced graph for \
-                        external crate) building module \
-                        {}", final_ident);
-                let parent_link = self.get_parent_link(new_parent.clone(), name);
-
-                child_name_bindings.define_module(parent_link,
-                                                  Some(def_id),
-                                                  kind,
-                                                  true,
-                                                  is_public,
-                                                  DUMMY_SP);
-              }
-            }
-          }
-          _ => {}
-        }
-
-        match def {
-          DefMod(_) | DefForeignMod(_) => {}
-          DefVariant(_, variant_id, is_struct) => {
-              debug!("(building reduced graph for external crate) building \
-                      variant {}",
-                      final_ident);
-              // variants are always treated as importable to allow them to be
-              // glob used
-              let modifiers = PUBLIC | IMPORTABLE;
-              if is_struct {
-                  child_name_bindings.define_type(def, DUMMY_SP, modifiers);
-                  // Not adding fields for variants as they are not accessed with a self receiver
-                  self.structs.insert(variant_id, Vec::new());
-              } else {
-                  child_name_bindings.define_value(def, DUMMY_SP, modifiers);
-              }
-          }
-          DefFn(ctor_id, true) => {
-            child_name_bindings.define_value(
-                csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
-                    .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
-          }
-          DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
-            debug!("(building reduced graph for external \
-                    crate) building value (fn/static) {}", final_ident);
-            // impl methods have already been defined with the correct importability modifier
-            let mut modifiers = match *child_name_bindings.value_def.borrow() {
-                Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
-                None => modifiers
-            };
-            if new_parent.module().kind.get() != NormalModuleKind {
-                modifiers = modifiers & !IMPORTABLE;
-            }
-            child_name_bindings.define_value(def, DUMMY_SP, modifiers);
-          }
-          DefTrait(def_id) => {
-              debug!("(building reduced graph for external \
-                      crate) building type {}", final_ident);
-
-              // If this is a trait, add all the trait item names to the trait
-              // info.
-
-              let trait_item_def_ids =
-                csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
-              for trait_item_def_id in trait_item_def_ids.iter() {
-                  let (trait_item_name, trait_item_kind) =
-                      csearch::get_trait_item_name_and_kind(
-                          &self.session.cstore,
-                          trait_item_def_id.def_id());
-
-                  debug!("(building reduced graph for external crate) ... \
-                          adding trait item '{}'",
-                         token::get_name(trait_item_name));
-
-                  self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
-
-                  if is_exported {
-                      self.external_exports
-                          .insert(trait_item_def_id.def_id());
-                  }
-              }
-
-              child_name_bindings.define_type(def, DUMMY_SP, modifiers);
-
-              // Define a module if necessary.
-              let parent_link = self.get_parent_link(new_parent, name);
-              child_name_bindings.set_module_kind(parent_link,
-                                                  Some(def_id),
-                                                  TraitModuleKind,
-                                                  true,
-                                                  is_public,
-                                                  DUMMY_SP)
-          }
-          DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
-              debug!("(building reduced graph for external \
-                      crate) building type {}", final_ident);
-
-              child_name_bindings.define_type(def, DUMMY_SP, modifiers);
-          }
-          DefStruct(def_id) => {
-            debug!("(building reduced graph for external \
-                    crate) building type and value for {}",
-                   final_ident);
-            child_name_bindings.define_type(def, DUMMY_SP, modifiers);
-            let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
-                f.name
-            }).collect::<Vec<_>>();
-
-            if fields.len() == 0 {
-                child_name_bindings.define_value(def, DUMMY_SP, modifiers);
-            }
-
-            // Record the def ID and fields of this struct.
-            self.structs.insert(def_id, fields);
-          }
-          DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
-          DefUse(..) | DefUpvar(..) | DefRegion(..) |
-          DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
-            panic!("didn't expect `{}`", def);
-          }
-        }
-    }
-
-    /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_def(&mut self,
-                                                  root: Rc<Module>,
-                                                  def_like: DefLike,
-                                                  name: Name,
-                                                  visibility: Visibility) {
-        match def_like {
-            DlDef(def) => {
-                // Add the new child item, if necessary.
-                match def {
-                    DefForeignMod(def_id) => {
-                        // Foreign modules have no names. Recur and populate
-                        // eagerly.
-                        csearch::each_child_of_item(&self.session.cstore,
-                                                    def_id,
-                                                    |def_like,
-                                                     child_name,
-                                                     vis| {
-                            self.build_reduced_graph_for_external_crate_def(
-                                root.clone(),
-                                def_like,
-                                child_name,
-                                vis)
-                        });
-                    }
-                    _ => {
-                        let child_name_bindings =
-                            self.add_child(name,
-                                           ModuleReducedGraphParent(root.clone()),
-                                           OverwriteDuplicates,
-                                           DUMMY_SP);
-
-                        self.handle_external_def(def,
-                                                 visibility,
-                                                 &*child_name_bindings,
-                                                 token::get_name(name).get(),
-                                                 name,
-                                                 ModuleReducedGraphParent(root));
-                    }
-                }
-            }
-            DlImpl(def) => {
-                match csearch::get_type_name_if_impl(&self.session.cstore, def) {
-                    None => {}
-                    Some(final_name) => {
-                        let methods_opt =
-                            csearch::get_methods_if_impl(&self.session.cstore, def);
-                        match methods_opt {
-                            Some(ref methods) if
-                                methods.len() >= 1 => {
-                                debug!("(building reduced graph for \
-                                        external crate) processing \
-                                        static methods for type name {}",
-                                        token::get_name(final_name));
-
-                                let child_name_bindings =
-                                    self.add_child(
-                                        final_name,
-                                        ModuleReducedGraphParent(root.clone()),
-                                        OverwriteDuplicates,
-                                        DUMMY_SP);
-
-                                // Process the static methods. First,
-                                // create the module.
-                                let type_module;
-                                let type_def = child_name_bindings.type_def.borrow().clone();
-                                match type_def {
-                                    Some(TypeNsDef {
-                                        module_def: Some(module_def),
-                                        ..
-                                    }) => {
-                                        // We already have a module. This
-                                        // is OK.
-                                        type_module = module_def;
-
-                                        // Mark it as an impl module if
-                                        // necessary.
-                                        type_module.kind.set(ImplModuleKind);
-                                    }
-                                    Some(_) | None => {
-                                        let parent_link =
-                                            self.get_parent_link(ModuleReducedGraphParent(root),
-                                                                 final_name);
-                                        child_name_bindings.define_module(
-                                            parent_link,
-                                            Some(def),
-                                            ImplModuleKind,
-                                            true,
-                                            true,
-                                            DUMMY_SP);
-                                        type_module =
-                                            child_name_bindings.
-                                                get_module();
-                                    }
-                                }
-
-                                // Add each static method to the module.
-                                let new_parent =
-                                    ModuleReducedGraphParent(type_module);
-                                for method_info in methods.iter() {
-                                    let name = method_info.name;
-                                    debug!("(building reduced graph for \
-                                             external crate) creating \
-                                             static method '{}'",
-                                           token::get_name(name));
-
-                                    let method_name_bindings =
-                                        self.add_child(name,
-                                                       new_parent.clone(),
-                                                       OverwriteDuplicates,
-                                                       DUMMY_SP);
-                                    let def = DefFn(method_info.def_id, false);
-
-                                    // NB: not IMPORTABLE
-                                    let modifiers = if visibility == ast::Public {
-                                        PUBLIC
-                                    } else {
-                                        DefModifiers::empty()
-                                    };
-                                    method_name_bindings.define_value(
-                                        def, DUMMY_SP, modifiers);
-                                }
-                            }
-
-                            // Otherwise, do nothing.
-                            Some(_) | None => {}
-                        }
-                    }
-                }
-            }
-            DlField => {
-                debug!("(building reduced graph for external crate) \
-                        ignoring field");
-            }
-        }
-    }
-
-    /// Builds the reduced graph rooted at the given external module.
-    fn populate_external_module(&mut self, module: Rc<Module>) {
-        debug!("(populating external module) attempting to populate {}",
-               self.module_to_string(&*module));
-
-        let def_id = match module.def_id.get() {
-            None => {
-                debug!("(populating external module) ... no def ID!");
-                return
-            }
-            Some(def_id) => def_id,
-        };
-
-        csearch::each_child_of_item(&self.session.cstore,
-                                    def_id,
-                                    |def_like, child_name, visibility| {
-            debug!("(populating external module) ... found ident: {}",
-                   token::get_name(child_name));
-            self.build_reduced_graph_for_external_crate_def(module.clone(),
-                                                            def_like,
-                                                            child_name,
-                                                            visibility)
-        });
-        module.populated.set(true)
-    }
-
-    /// Ensures that the reduced graph rooted at the given external module
-    /// is built, building it if it is not.
-    fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
-        if !module.populated.get() {
-            self.populate_external_module(module.clone())
-        }
-        assert!(module.populated.get())
-    }
-
-    /// Builds the reduced graph rooted at the 'use' directive for an external
-    /// crate.
-    fn build_reduced_graph_for_external_crate(&mut self, root: Rc<Module>) {
-        csearch::each_top_level_item_of_crate(&self.session.cstore,
-                                              root.def_id
-                                                  .get()
-                                                  .unwrap()
-                                                  .krate,
-                                              |def_like, name, visibility| {
-            self.build_reduced_graph_for_external_crate_def(root.clone(),
-                                                            def_like,
-                                                            name,
-                                                            visibility)
-        });
-    }
-
-    /// Creates and adds an import directive to the given module.
-    fn build_import_directive(&mut self,
-                              module_: &Module,
-                              module_path: Vec<Name>,
-                              subclass: ImportDirectiveSubclass,
-                              span: Span,
-                              id: NodeId,
-                              is_public: bool,
-                              shadowable: Shadowable) {
-        module_.imports.borrow_mut().push(ImportDirective::new(module_path,
-                                                               subclass,
-                                                               span,
-                                                               id,
-                                                               is_public,
-                                                               shadowable));
-        self.unresolved_imports += 1;
-        // Bump the reference count on the name. Or, if this is a glob, set
-        // the appropriate flag.
-
-        match subclass {
-            SingleImport(target, _) => {
-                debug!("(building import directive) building import \
-                        directive: {}::{}",
-                       self.names_to_string(module_.imports.borrow().last().unwrap()
-                                                 .module_path[]),
-                       token::get_name(target));
-
-                let mut import_resolutions = module_.import_resolutions
-                                                    .borrow_mut();
-                match import_resolutions.get_mut(&target) {
-                    Some(resolution) => {
-                        debug!("(building import directive) bumping \
-                                reference");
-                        resolution.outstanding_references += 1;
-
-                        // the source of this name is different now
-                        resolution.type_id = id;
-                        resolution.value_id = id;
-                        resolution.is_public = is_public;
-                        return;
-                    }
-                    None => {}
-                }
-                debug!("(building import directive) creating new");
-                let mut resolution = ImportResolution::new(id, is_public);
-                resolution.outstanding_references = 1;
-                import_resolutions.insert(target, resolution);
-            }
-            GlobImport => {
-                // Set the glob flag. This tells us that we don't know the
-                // module's exports ahead of time.
-
-                module_.glob_count.set(module_.glob_count.get() + 1);
-            }
-        }
-    }
-
     // Import resolution
     //
     // This is a fixed-point algorithm. We resolve imports until our efforts
@@ -2267,7 +1015,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         self.resolve_imports_for_module(module_.clone());
         self.current_module = orig_module;
 
-        self.populate_module_if_necessary(&module_);
+        build_reduced_graph::populate_module_if_necessary(self, &module_);
         for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
                 None => {
@@ -2533,7 +1281,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut type_result = UnknownResult;
 
         // Search for direct children of the containing module.
-        self.populate_module_if_necessary(&containing_module);
+        build_reduced_graph::populate_module_if_necessary(self, &containing_module);
 
         match containing_module.children.borrow().get(&source) {
             None => {
@@ -2712,64 +1460,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // We've successfully resolved the import. Write the results in.
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
         let import_resolution = &mut (*import_resolutions)[target];
+        {
+            let mut check_and_write_import = |&mut: namespace, result: &_, used_public: &mut bool| {
+                let namespace_name = match namespace {
+                    TypeNS => "type",
+                    ValueNS => "value",
+                };
 
-        match value_result {
-            BoundResult(ref target_module, ref name_bindings) => {
-                debug!("(resolving single import) found value target: {}",
-                       { name_bindings.value_def.borrow().clone().unwrap().def });
-                self.check_for_conflicting_import(
-                    &import_resolution.value_target,
-                    directive.span,
-                    target,
-                    ValueNS);
-
-                self.check_that_import_is_importable(
-                    &**name_bindings,
-                    directive.span,
-                    target,
-                    ValueNS);
-
-                import_resolution.value_target =
-                    Some(Target::new(target_module.clone(),
-                                     name_bindings.clone(),
-                                     directive.shadowable));
-                import_resolution.value_id = directive.id;
-                import_resolution.is_public = directive.is_public;
-                value_used_public = name_bindings.defined_in_public_namespace(ValueNS);
-            }
-            UnboundResult => { /* Continue. */ }
-            UnknownResult => {
-                panic!("value result should be known at this point");
-            }
-        }
-        match type_result {
-            BoundResult(ref target_module, ref name_bindings) => {
-                debug!("(resolving single import) found type target: {}",
-                       { name_bindings.type_def.borrow().clone().unwrap().type_def });
-                self.check_for_conflicting_import(
-                    &import_resolution.type_target,
-                    directive.span,
-                    target,
-                    TypeNS);
-
-                self.check_that_import_is_importable(
-                    &**name_bindings,
-                    directive.span,
-                    target,
-                    TypeNS);
-
-                import_resolution.type_target =
-                    Some(Target::new(target_module.clone(),
-                                     name_bindings.clone(),
-                                     directive.shadowable));
-                import_resolution.type_id = directive.id;
-                import_resolution.is_public = directive.is_public;
-                type_used_public = name_bindings.defined_in_public_namespace(TypeNS);
-            }
-            UnboundResult => { /* Continue. */ }
-            UnknownResult => {
-                panic!("type result should be known at this point");
-            }
+                match *result {
+                    BoundResult(ref target_module, ref name_bindings) => {
+                        debug!("(resolving single import) found {} target: {}",
+                               namespace_name,
+                               name_bindings.def_for_namespace(namespace));
+                        self.check_for_conflicting_import(
+                            &import_resolution.target_for_namespace(namespace),
+                            directive.span,
+                            target,
+                            namespace);
+
+                        self.check_that_import_is_importable(
+                            &**name_bindings,
+                            directive.span,
+                            target,
+                            namespace);
+
+                        let target = Some(Target::new(target_module.clone(),
+                                                      name_bindings.clone(),
+                                                      directive.shadowable));
+                        import_resolution.set_target_and_id(namespace, target, directive.id);
+                        import_resolution.is_public = directive.is_public;
+                        *used_public = name_bindings.defined_in_public_namespace(namespace);
+                    }
+                    UnboundResult => { /* Continue. */ }
+                    UnknownResult => {
+                        panic!("{} result should be known at this point", namespace_name);
+                    }
+                }
+            };
+            check_and_write_import(ValueNS, &value_result, &mut value_used_public);
+            check_and_write_import(TypeNS, &type_result, &mut type_used_public);
         }
 
         self.check_for_conflicts_between_imports_and_items(
@@ -2825,7 +1554,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     // Resolves a glob import. Note that this function cannot fail; it either
     // succeeds or bails out (as importing * from an empty module or a module
-    // that exports nothing is valid).
+    // that exports nothing is valid). containing_module is the module we are
+    // actually importing, i.e., `foo` in `use foo::*`.
     fn resolve_glob_import(&mut self,
                            module_: &Module,
                            containing_module: Rc<Module>,
@@ -2851,12 +1581,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         assert_eq!(containing_module.glob_count.get(), 0);
 
         // Add all resolved imports from the containing module.
-        let import_resolutions = containing_module.import_resolutions
-                                                  .borrow();
+        let import_resolutions = containing_module.import_resolutions.borrow();
         for (ident, target_import_resolution) in import_resolutions.iter() {
             debug!("(resolving glob import) writing module resolution \
                     {} into `{}`",
-                   target_import_resolution.type_target.is_none(),
+                   token::get_name(*ident),
                    self.module_to_string(module_));
 
             if !target_import_resolution.is_public {
@@ -2876,8 +1605,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             // Continue.
                         }
                         Some(ref value_target) => {
-                            dest_import_resolution.value_target =
-                                Some(value_target.clone());
+                            self.check_for_conflicting_import(&dest_import_resolution.value_target,
+                                                              import_directive.span,
+                                                              *ident,
+                                                              ValueNS);
+                            dest_import_resolution.value_target = Some(value_target.clone());
                         }
                     }
                     match target_import_resolution.type_target {
@@ -2885,8 +1617,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             // Continue.
                         }
                         Some(ref type_target) => {
-                            dest_import_resolution.type_target =
-                                Some(type_target.clone());
+                            self.check_for_conflicting_import(&dest_import_resolution.type_target,
+                                                              import_directive.span,
+                                                              *ident,
+                                                              TypeNS);
+                            dest_import_resolution.type_target = Some(type_target.clone());
                         }
                     }
                     dest_import_resolution.is_public = is_public;
@@ -2906,10 +1641,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         // Add all children from the containing module.
-        self.populate_module_if_necessary(&containing_module);
+        build_reduced_graph::populate_module_if_necessary(self, &containing_module);
 
-        for (&name, name_bindings) in containing_module.children
-                                                       .borrow().iter() {
+        for (&name, name_bindings) in containing_module.children.borrow().iter() {
             self.merge_import_resolution(module_,
                                          containing_module.clone(),
                                          import_directive,
@@ -2919,8 +1653,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         // Add external module children from the containing module.
-        for (&name, module) in containing_module.external_module_children
-                                                .borrow().iter() {
+        for (&name, module) in containing_module.external_module_children.borrow().iter() {
             let name_bindings =
                 Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
             self.merge_import_resolution(module_,
@@ -2965,41 +1698,39 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         debug!("(resolving glob import) writing resolution `{}` in `{}` \
                to `{}`",
-               token::get_name(name).get().to_string(),
+               token::get_name(name).get(),
                self.module_to_string(&*containing_module),
                self.module_to_string(module_));
 
         // Merge the child item into the import resolution.
-        if name_bindings.defined_in_namespace_with(ValueNS, IMPORTABLE | PUBLIC) {
-            debug!("(resolving glob import) ... for value target");
-            if dest_import_resolution.shadowable(ValueNS) == Shadowable::Never {
-                let msg = format!("a value named `{}` has already been imported \
-                                   in this module",
-                                  token::get_name(name).get());
-                self.session.span_err(import_directive.span, msg.as_slice());
-            } else {
-                dest_import_resolution.value_target =
-                    Some(Target::new(containing_module.clone(),
-                                     name_bindings.clone(),
-                                     import_directive.shadowable));
-                dest_import_resolution.value_id = id;
-            }
-        }
-        if name_bindings.defined_in_namespace_with(TypeNS, IMPORTABLE | PUBLIC) {
-            debug!("(resolving glob import) ... for type target");
-            if dest_import_resolution.shadowable(TypeNS) == Shadowable::Never {
-                let msg = format!("a type named `{}` has already been imported \
-                                   in this module",
-                                  token::get_name(name).get());
-                self.session.span_err(import_directive.span, msg.as_slice());
-            } else {
-                dest_import_resolution.type_target =
-                    Some(Target::new(containing_module,
-                                     name_bindings.clone(),
-                                     import_directive.shadowable));
-                dest_import_resolution.type_id = id;
-            }
+        {
+            let mut merge_child_item = |&mut : namespace| {
+                if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) {
+                    let namespace_name = match namespace {
+                        TypeNS => "type",
+                        ValueNS => "value",
+                    };
+                    debug!("(resolving glob import) ... for {} target", namespace_name);
+                    if dest_import_resolution.shadowable(namespace) == Shadowable::Never {
+                        let msg = format!("a {} named `{}` has already been imported \
+                                           in this module",
+                                          namespace_name,
+                                          token::get_name(name).get());
+                        self.session.span_err(import_directive.span, msg.as_slice());
+                    } else {
+                        let target = Target::new(containing_module.clone(),
+                                                 name_bindings.clone(),
+                                                 import_directive.shadowable);
+                        dest_import_resolution.set_target_and_id(namespace,
+                                                                 Some(target),
+                                                                 id);
+                    }
+                }
+            };
+            merge_child_item(ValueNS);
+            merge_child_item(TypeNS);
         }
+
         dest_import_resolution.is_public = is_public;
 
         self.check_for_conflicts_between_imports_and_items(
@@ -3019,6 +1750,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             return
         }
 
+        debug!("check_for_conflicting_import: {}; target exists: {}",
+               token::get_name(name).get(),
+               target.is_some());
+
         match *target {
             Some(ref target) if target.shadowable != Shadowable::Always => {
                 let msg = format!("a {} named `{}` has already been imported \
@@ -3426,7 +2161,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         // The current module node is handled specially. First, check for
         // its immediate children.
-        self.populate_module_if_necessary(&module_);
+        build_reduced_graph::populate_module_if_necessary(self, &module_);
 
         match module_.children.borrow().get(&name) {
             Some(name_bindings)
@@ -3691,7 +2426,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                self.module_to_string(&*module_));
 
         // First, check the direct children of the module.
-        self.populate_module_if_necessary(&module_);
+        build_reduced_graph::populate_module_if_necessary(self, &module_);
 
         match module_.children.borrow().get(&name) {
             Some(name_bindings)
@@ -3787,7 +2522,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         // Descend into children and anonymous children.
-        self.populate_module_if_necessary(&module_);
+        build_reduced_graph::populate_module_if_necessary(self, &module_);
 
         for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
@@ -3834,7 +2569,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 // Nothing to do.
             }
             Some(name) => {
-                self.populate_module_if_necessary(&orig_module);
+                build_reduced_graph::populate_module_if_necessary(self, &orig_module);
 
                 match orig_module.children.borrow().get(&name) {
                     None => {
@@ -3910,7 +2645,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             // If the def is a ty param, and came from the parent
                             // item, it's ok
                             match def {
-                                DefTyParam(_, did, _) if {
+                                DefTyParam(_, _, did, _) if {
                                     self.def_map.borrow().get(&did.node).cloned()
                                         == Some(DefTyParamBinder(item_id))
                                 } => {} // ok
@@ -3963,7 +2698,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             // If the def is a ty param, and came from the parent
                             // item, it's ok
                             match def {
-                                DefTyParam(_, did, _) if {
+                                DefTyParam(_, _, did, _) if {
                                     self.def_map.borrow().get(&did.node).cloned()
                                         == Some(DefTyParamBinder(item_id))
                                 } => {} // ok
@@ -4008,6 +2743,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
     }
 
+    /// Searches the current set of local scopes and
+    /// applies translations for closures.
     fn search_ribs(&self,
                    ribs: &[Rib],
                    name: Name,
@@ -4029,6 +2766,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         None
     }
 
+    /// Searches the current set of local scopes for labels.
+    /// Stops after meeting a closure.
+    fn search_label(&self, name: Name) -> Option<DefLike> {
+        for rib in self.label_ribs.iter().rev() {
+            match rib.kind {
+                NormalRibKind => {
+                    // Continue
+                }
+                _ => {
+                    // Do not resolve labels across function boundary
+                    return None
+                }
+            }
+            let result = rib.bindings.get(&name).cloned();
+            if result.is_some() {
+                return result
+            }
+        }
+        None
+    }
+
     fn resolve_crate(&mut self, krate: &ast::Crate) {
         debug!("(resolving crate) starting");
 
@@ -4093,7 +2851,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                             impl_items[]);
             }
 
-            ItemTrait(_, ref generics, ref unbound, ref bounds, ref trait_items) => {
+            ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
                 // Create a new rib for the self type.
                 let mut self_type_rib = Rib::new(ItemRibKind);
 
@@ -4114,13 +2872,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     this.resolve_type_parameter_bounds(item.id, bounds,
                                                        TraitDerivation);
 
-                    match *unbound {
-                        Some(ref tpb) => {
-                            this.resolve_trait_reference(item.id, tpb, TraitDerivation);
-                        }
-                        None => {}
-                    }
-
                     for trait_item in (*trait_items).iter() {
                         // Create a new rib for the trait_item-specific type
                         // parameters.
@@ -4253,8 +3004,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     seen_bindings.insert(name);
 
                     let def_like = DlDef(DefTyParam(space,
+                                                    index as u32,
                                                     local_def(type_parameter.id),
-                                                    index as u32));
+                                                    name));
                     // Associate this type parameter with
                     // the item that bound it
                     self.record_def(type_parameter.id,
@@ -4368,12 +3120,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             self.resolve_type_parameter_bound(type_parameter.id, bound,
                                               TraitBoundingTypeParameter);
         }
-        match &type_parameter.unbound {
-            &Some(ref unbound) =>
-                self.resolve_trait_reference(
-                    type_parameter.id, unbound, TraitBoundingTypeParameter),
-            &None => {}
-        }
         match type_parameter.default {
             Some(ref ty) => self.resolve_type(&**ty),
             None => {}
@@ -4395,7 +3141,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                     type_parameter_bound: &TyParamBound,
                                     reference_type: TraitReferenceType) {
         match *type_parameter_bound {
-            TraitTyParamBound(ref tref) => {
+            TraitTyParamBound(ref tref, _) => {
                 self.resolve_poly_trait_reference(id, tref, reference_type)
             }
             RegionTyParamBound(..) => {}
@@ -4821,9 +3567,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             Some(def) => {
                                 debug!("(resolving type) resolved `{}` to \
                                         type {}",
-                                       token::get_ident(path.segments
-                                                            .last().unwrap()
-                                                            .identifier),
+                                       token::get_ident(path.segments.last().unwrap() .identifier),
                                        def);
                                 result_def = Some(def);
                             }
@@ -5014,19 +3758,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             self.resolve_error(path.span,
                                 format!("`{}` is not an enum variant, struct or const",
                                     token::get_ident(
-                                        path.segments
-                                            .last()
-                                            .unwrap()
-                                            .identifier))[]);
+                                        path.segments.last().unwrap().identifier))[]);
                         }
                         None => {
                             self.resolve_error(path.span,
                                 format!("unresolved enum variant, struct or const `{}`",
                                     token::get_ident(
-                                        path.segments
-                                            .last()
-                                            .unwrap()
-                                            .identifier))[]);
+                                        path.segments.last().unwrap().identifier))[]);
                         }
                     }
 
@@ -5155,7 +3893,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                           path.span) {
                 Some((def, last_private)) => {
                     match def {
-                        DefTyParam(_, did, _) => {
+                        DefTyParam(_, _, did, _) => {
                             let def = DefAssociatedPath(TyParamProvenance::FromParam(did),
                                                         path.segments.last()
                                                             .unwrap().identifier);
@@ -5180,9 +3918,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         // Try to find a path to an item in a module.
         let unqualified_def =
-                self.resolve_identifier(path.segments
-                                            .last().unwrap()
-                                            .identifier,
+                self.resolve_identifier(path.segments.last().unwrap().identifier,
                                         namespace,
                                         check_ribs,
                                         path.span);
@@ -5236,7 +3972,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                             namespace: Namespace)
                                             -> NameDefinition {
         // First, search children.
-        self.populate_module_if_necessary(&containing_module);
+        build_reduced_graph::populate_module_if_necessary(self, &containing_module);
 
         match containing_module.children.borrow().get(&name) {
             Some(child_name_bindings) => {
@@ -5848,8 +4584,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
                 let renamed = mtwt::resolve(label);
-                match self.search_ribs(self.label_ribs[],
-                                       renamed, expr.span) {
+                match self.search_label(renamed) {
                     None => {
                         self.resolve_error(
                             expr.span,
@@ -5925,7 +4660,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
 
             // Look for trait children.
-            self.populate_module_if_necessary(&search_module);
+            build_reduced_graph::populate_module_if_necessary(self, &search_module);
 
             {
                 for (_, child_names) in search_module.children.borrow().iter() {
@@ -6053,7 +4788,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         debug!("Dump of module `{}`:", self.module_to_string(&*module_));
 
         debug!("Children:");
-        self.populate_module_if_necessary(&module_);
+        build_reduced_graph::populate_module_if_necessary(self, &module_);
         for (&name, _) in module_.children.borrow().iter() {
             debug!("* {}", token::get_name(name));
         }
@@ -6110,7 +4845,7 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
                                -> CrateMap {
     let mut resolver = Resolver::new(session, ast_map, krate.span, make_glob_map);
 
-    resolver.build_reduced_graph(krate);
+    build_reduced_graph::build_reduced_graph(&mut resolver, krate);
     session.abort_if_errors();
 
     resolver.resolve_imports();
diff --git a/src/librustc_resolve/record_exports.rs b/src/librustc_resolve/record_exports.rs
index c6618f10e0e..4f314291da6 100644
--- a/src/librustc_resolve/record_exports.rs
+++ b/src/librustc_resolve/record_exports.rs
@@ -21,6 +21,8 @@
 use {Module, NameBindings, Resolver};
 use Namespace::{mod, TypeNS, ValueNS};
 
+use build_reduced_graph;
+
 use rustc::middle::def::Export;
 use syntax::ast;
 use syntax::parse::token;
@@ -74,7 +76,7 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
         }
 
         self.record_exports_for_module(&*module_);
-        self.populate_module_if_necessary(&module_);
+        build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
 
         for (_, child_name_bindings) in module_.children.borrow().iter() {
             match child_name_bindings.get_module_if_available() {
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index ec61d3a6953..93ff9f53ec1 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -16,9 +16,11 @@ use super::svh::Svh;
 use session::config;
 use session::config::NoDebugInfo;
 use session::config::{OutputFilenames, Input, OutputTypeBitcode, OutputTypeExe, OutputTypeObject};
+use session::search_paths::PathKind;
 use session::Session;
 use metadata::common::LinkMeta;
 use metadata::{encoder, cstore, filesearch, csearch, creader};
+use metadata::filesearch::FileDoesntMatch;
 use trans::{CrateContext, CrateTranslation, gensym_name};
 use middle::ty::{mod, Ty};
 use util::common::time;
@@ -125,7 +127,7 @@ pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: uint =
 pub fn find_crate_name(sess: Option<&Session>,
                        attrs: &[ast::Attribute],
                        input: &Input) -> String {
-    let validate = |s: String, span: Option<Span>| {
+    let validate = |&: s: String, span: Option<Span>| {
         creader::validate_crate_name(sess, s[], span);
         s
     };
@@ -504,10 +506,11 @@ fn link_binary_output(sess: &Session,
 }
 
 fn archive_search_paths(sess: &Session) -> Vec<Path> {
-    let mut rustpath = filesearch::rust_path();
-    rustpath.push(sess.target_filesearch().get_lib_path());
-    let mut search: Vec<Path> = sess.opts.addl_lib_search_paths.borrow().clone();
-    search.push_all(rustpath[]);
+    let mut search = Vec::new();
+    sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path| {
+        search.push(path.clone());
+        FileDoesntMatch
+    });
     return search;
 }
 
@@ -832,7 +835,7 @@ fn link_args(cmd: &mut Command,
 
     // The default library location, we need this to find the runtime.
     // The location of crates will be determined as needed.
-    let lib_path = sess.target_filesearch().get_lib_path();
+    let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
 
     // target descriptor
     let t = &sess.target.target;
@@ -1040,14 +1043,10 @@ 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) {
-    for path in sess.opts.addl_lib_search_paths.borrow().iter() {
-        cmd.arg("-L").arg(path);
-    }
-
-    let rustpath = filesearch::rust_path();
-    for path in rustpath.iter() {
+    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path| {
         cmd.arg("-L").arg(path);
-    }
+        FileDoesntMatch
+    });
 
     // Some platforms take hints about whether a library is static or dynamic.
     // For those that support this, we ensure we pass the option if the library
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 55e6dfaebcd..f6a44a878ef 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -23,6 +23,7 @@ use syntax::diagnostic;
 use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
 
 use std::c_str::{ToCStr, CString};
+use std::comm::channel;
 use std::io::Command;
 use std::io::fs;
 use std::iter::Unfold;
@@ -99,7 +100,7 @@ impl SharedEmitter {
     }
 
     fn dump(&mut self, handler: &Handler) {
-        let mut buffer = self.buffer.lock();
+        let mut buffer = self.buffer.lock().unwrap();
         for diag in buffer.iter() {
             match diag.code {
                 Some(ref code) => {
@@ -124,7 +125,7 @@ impl Emitter for SharedEmitter {
             msg: &str, code: Option<&str>, lvl: Level) {
         assert!(cmsp.is_none(), "SharedEmitter doesn't support spans");
 
-        self.buffer.lock().push(Diagnostic {
+        self.buffer.lock().unwrap().push(Diagnostic {
             msg: msg.to_string(),
             code: code.map(|s| s.to_string()),
             lvl: lvl,
@@ -432,7 +433,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
 
             // If we're verifying or linting, add them to the function pass
             // manager.
-            let addpass = |pass: &str| {
+            let addpass = |&: pass: &str| {
                 pass.with_c_str(|s| llvm::LLVMRustAddPass(fpm, s))
             };
             if !config.no_verify { assert!(addpass("verify")); }
@@ -653,7 +654,7 @@ pub fn run_passes(sess: &Session,
 
     // Produce final compile outputs.
 
-    let copy_if_one_unit = |ext: &str, output_type: config::OutputType, keep_numbered: bool| {
+    let copy_if_one_unit = |&: ext: &str, output_type: config::OutputType, keep_numbered: bool| {
         // Three cases:
         if sess.opts.cg.codegen_units == 1 {
             // 1) Only one codegen unit.  In this case it's no difficulty
@@ -678,7 +679,7 @@ pub fn run_passes(sess: &Session,
         }
     };
 
-    let link_obj = |output_path: &Path| {
+    let link_obj = |&: output_path: &Path| {
         // Running `ld -r` on a single input is kind of pointless.
         if sess.opts.cg.codegen_units == 1 {
             fs::copy(&crate_output.with_extension("0.o"),
@@ -916,7 +917,7 @@ fn run_work_multithreaded(sess: &Session,
 
             loop {
                 // Avoid holding the lock for the entire duration of the match.
-                let maybe_work = work_items_arc.lock().pop();
+                let maybe_work = work_items_arc.lock().unwrap().pop();
                 match maybe_work {
                     Some(work) => {
                         execute_work_item(&cgcx, work);
@@ -994,7 +995,7 @@ unsafe fn configure_llvm(sess: &Session) {
     let mut llvm_c_strs = Vec::new();
     let mut llvm_args = Vec::new();
     {
-        let add = |arg: &str| {
+        let mut add = |&mut : arg: &str| {
             let s = arg.to_c_str();
             llvm_args.push(s.as_ptr());
             llvm_c_strs.push(s);
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index e105a1f6a95..b877a771bbc 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -636,7 +636,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                         item.id);
 
                     for field in struct_def.fields.iter() {
-                        self.process_struct_field_def(field, enum_name[], variant.node.id);
+                        self.process_struct_field_def(field, qualname[], variant.node.id);
                         self.visit_ty(&*field.node.ty);
                     }
                 }
@@ -710,7 +710,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         // super-traits
         for super_bound in trait_refs.iter() {
             let trait_ref = match *super_bound {
-                ast::TraitTyParamBound(ref trait_ref) => {
+                ast::TraitTyParamBound(ref trait_ref, _) => {
                     trait_ref
                 }
                 ast::RegionTyParamBound(..) => {
@@ -763,37 +763,38 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
     }
 
     fn process_path(&mut self,
-                    ex: &ast::Expr,
-                    path: &ast::Path) {
+                    id: NodeId,
+                    span: Span,
+                    path: &ast::Path,
+                    ref_kind: Option<recorder::Row>) {
         if generated_code(path.span) {
             return
         }
 
         let def_map = self.analysis.ty_cx.def_map.borrow();
-        if !def_map.contains_key(&ex.id) {
-            self.sess.span_bug(ex.span,
-                               format!("def_map has no key for {} in visit_expr",
-                                       ex.id)[]);
+        if !def_map.contains_key(&id) {
+            self.sess.span_bug(span,
+                               format!("def_map has no key for {} in visit_expr", id)[]);
         }
-        let def = &(*def_map)[ex.id];
-        let sub_span = self.span.span_for_last_ident(ex.span);
+        let def = &(*def_map)[id];
+        let sub_span = self.span.span_for_last_ident(span);
         match *def {
             def::DefUpvar(..) |
             def::DefLocal(..) |
             def::DefStatic(..) |
             def::DefConst(..) |
-            def::DefVariant(..) => self.fmt.ref_str(recorder::VarRef,
-                                                    ex.span,
+            def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
+                                                    span,
                                                     sub_span,
                                                     def.def_id(),
                                                     self.cur_scope),
             def::DefStruct(def_id) => self.fmt.ref_str(recorder::StructRef,
-                                                       ex.span,
+                                                       span,
                                                        sub_span,
                                                        def_id,
-                                                        self.cur_scope),
+                                                       self.cur_scope),
             def::DefStaticMethod(declid, provenence) => {
-                let sub_span = self.span.sub_span_for_meth_name(ex.span);
+                let sub_span = self.span.sub_span_for_meth_name(span);
                 let defid = if declid.krate == ast::LOCAL_CRATE {
                     let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
                                                     declid);
@@ -828,34 +829,31 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                 } else {
                     None
                 };
-                self.fmt.meth_call_str(ex.span,
+                self.fmt.meth_call_str(span,
                                        sub_span,
                                        defid,
                                        Some(declid),
                                        self.cur_scope);
             },
-            def::DefFn(def_id, _) => self.fmt.fn_call_str(ex.span,
-                                                             sub_span,
-                                                             def_id,
-                                                             self.cur_scope),
-            _ => self.sess.span_bug(ex.span,
+            def::DefFn(def_id, _) => self.fmt.fn_call_str(span,
+                                                          sub_span,
+                                                          def_id,
+                                                          self.cur_scope),
+            _ => self.sess.span_bug(span,
                                     format!("Unexpected def kind while looking up path in '{}'",
-                                            self.span.snippet(ex.span))[]),
+                                            self.span.snippet(span))[]),
         }
         // modules or types in the path prefix
         match *def {
-            def::DefStaticMethod(..) => {
-                self.write_sub_path_trait_truncated(path);
-            },
+            def::DefStaticMethod(..) => self.write_sub_path_trait_truncated(path),
             def::DefLocal(_) |
             def::DefStatic(_,_) |
             def::DefConst(..) |
             def::DefStruct(_) |
+            def::DefVariant(..) |
             def::DefFn(..) => self.write_sub_paths_truncated(path),
             _ => {},
         }
-
-        visit::walk_path(self, path);
     }
 
     fn process_struct_lit(&mut self,
@@ -982,18 +980,19 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                     }
                 };
                 for &Spanned { node: ref field, span } in fields.iter() {
-                    self.visit_pat(&*field.pat);
+                    let sub_span = self.span.span_for_first_ident(span);
                     let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
                     for f in fields.iter() {
                         if f.name == field.ident.name {
                             self.fmt.ref_str(recorder::VarRef,
-                                             p.span,
-                                             Some(span),
+                                             span,
+                                             sub_span,
                                              f.id,
                                              self.cur_scope);
                             break;
                         }
                     }
+                    self.visit_pat(&*field.pat);
                 }
             }
             ast::PatEnum(ref path, _) => {
@@ -1052,7 +1051,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                                   &**typ,
                                   impl_items)
             }
-            ast::ItemTrait(_, ref generics, _, ref trait_refs, ref methods) =>
+            ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) =>
                 self.process_trait(item, generics, trait_refs, methods),
             ast::ItemMod(ref m) => self.process_mod(item, m),
             ast::ItemTy(ref ty, ref ty_params) => {
@@ -1076,7 +1075,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
     fn visit_generics(&mut self, generics: &ast::Generics) {
         for param in generics.ty_params.iter() {
             for bound in param.bounds.iter() {
-                if let ast::TraitTyParamBound(ref trait_ref) = *bound {
+                if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
                     self.process_trait_ref(&trait_ref.trait_ref, None);
                 }
             }
@@ -1162,8 +1161,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
         }
 
         match i.node {
-            ast::ViewItemUse(ref path) => {
-                match path.node {
+            ast::ViewItemUse(ref item) => {
+                match item.node {
                     ast::ViewPathSimple(ident, ref path, id) => {
                         let sub_span = self.span.span_for_last_ident(path.span);
                         let mod_id = match self.lookup_type_ref(id) {
@@ -1184,7 +1183,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                         // 'use' always introduces an alias, if there is not an explicit
                         // one, there is an implicit one.
                         let sub_span =
-                            match self.span.sub_span_before_token(path.span, token::Eq) {
+                            match self.span.sub_span_after_keyword(item.span, keywords::As) {
                                 Some(sub_span) => Some(sub_span),
                                 None => sub_span,
                             };
@@ -1307,7 +1306,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                 // because just walking the callee path does what we want.
                 visit::walk_expr(self, ex);
             },
-            ast::ExprPath(ref path) => self.process_path(ex, path),
+            ast::ExprPath(ref path) => {
+                self.process_path(ex.id, ex.span, path, None);
+                visit::walk_path(self, path);
+            }
             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),
@@ -1404,46 +1406,50 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
     fn visit_arm(&mut self, arm: &ast::Arm) {
         assert!(self.collected_paths.len() == 0 && !self.collecting);
         self.collecting = true;
-
         for pattern in arm.pats.iter() {
             // collect paths from the arm's patterns
             self.visit_pat(&**pattern);
         }
-        self.collecting = false;
+
+        // This is to get around borrow checking, because we need mut self to call process_path.
+        let mut paths_to_process = vec![];
         // process collected paths
         for &(id, ref p, ref immut, ref_kind) in self.collected_paths.iter() {
-            let value = if *immut {
-                self.span.snippet(p.span).to_string()
-            } else {
-                "<mutable>".to_string()
-            };
-            let sub_span = self.span.span_for_first_ident(p.span);
             let def_map = self.analysis.ty_cx.def_map.borrow();
             if !def_map.contains_key(&id) {
                 self.sess.span_bug(p.span,
-                                   format!("def_map has no key for {} in visit_arm",
-                                           id)[]);
+                                   format!("def_map has no key for {} in visit_arm", id)[]);
             }
             let def = &(*def_map)[id];
             match *def {
-                def::DefLocal(id)  => self.fmt.variable_str(p.span,
-                                                            sub_span,
-                                                            id,
-                                                            path_to_string(p)[],
-                                                            value[],
-                                                            ""),
-                def::DefVariant(_,id,_) => self.fmt.ref_str(ref_kind,
-                                                            p.span,
-                                                            sub_span,
-                                                            id,
-                                                            self.cur_scope),
-                // FIXME(nrc) what is this doing here?
+                def::DefLocal(id)  => {
+                    let value = if *immut {
+                        self.span.snippet(p.span).to_string()
+                    } else {
+                        "<mutable>".to_string()
+                    };
+
+                    assert!(p.segments.len() == 1, "qualified path for local variable def in arm");
+                    self.fmt.variable_str(p.span,
+                                          Some(p.span),
+                                          id,
+                                          path_to_string(p)[],
+                                          value[],
+                                          "")
+                }
+                def::DefVariant(..) => {
+                    paths_to_process.push((id, p.span, p.clone(), Some(ref_kind)))
+                }
+                // FIXME(nrc) what are these doing here?
                 def::DefStatic(_, _) => {}
                 def::DefConst(..) => {}
-                _ => error!("unexpected definition kind when processing collected paths: {}",
-                            *def)
+                _ => error!("unexpected definition kind when processing collected paths: {}", *def)
             }
         }
+        for &(id, span, ref path, ref_kind) in paths_to_process.iter() {
+            self.process_path(id, span, path, ref_kind);
+        }
+        self.collecting = false;
         self.collected_paths.clear();
         visit::walk_expr_opt(self, &arm.guard);
         self.visit_expr(&*arm.body);
diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs
index b2dd9218f17..f62073e54e6 100644
--- a/src/librustc_trans/save/recorder.rs
+++ b/src/librustc_trans/save/recorder.rs
@@ -61,7 +61,7 @@ macro_rules! svec {
     })
 }
 
-#[deriving(Copy)]
+#[deriving(Copy,Show)]
 pub enum Row {
     Variable,
     Enum,
diff --git a/src/librustc_trans/save/span_utils.rs b/src/librustc_trans/save/span_utils.rs
index e9d862d3781..244d0476832 100644
--- a/src/librustc_trans/save/span_utils.rs
+++ b/src/librustc_trans/save/span_utils.rs
@@ -294,8 +294,8 @@ impl<'a> SpanUtils<'a> {
     }
 
     pub fn sub_span_after_keyword(&self,
-                              span: Span,
-                              keyword: keywords::Keyword) -> Option<Span> {
+                                  span: Span,
+                                  keyword: keywords::Keyword) -> Option<Span> {
         let mut toks = self.retokenise_span(span);
         loop {
             let ts = toks.real_token();
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index a798d09872c..fc68d1d3258 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -410,15 +410,15 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }).collect()
 }
 
-type EnterPatterns<'a, 'p> = |&[&'p ast::Pat]|: 'a -> Option<Vec<&'p ast::Pat>>;
-
-fn enter_match<'a, 'b, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                       dm: &DefMap,
-                                       m: &[Match<'a, 'p, 'blk, 'tcx>],
-                                       col: uint,
-                                       val: ValueRef,
-                                       e: EnterPatterns<'b, 'p>)
-                                       -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
+fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
+                                          dm: &DefMap,
+                                          m: &[Match<'a, 'p, 'blk, 'tcx>],
+                                          col: uint,
+                                          val: ValueRef,
+                                          mut e: F)
+                                          -> Vec<Match<'a, 'p, 'blk, 'tcx>> where
+    F: FnMut(&[&'p ast::Pat]) -> Option<Vec<&'p ast::Pat>>,
+{
     debug!("enter_match(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -606,9 +606,9 @@ fn extract_variant_args<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     val: ValueRef)
                                     -> ExtractedBlock<'blk, 'tcx> {
     let _icx = push_ctxt("match::extract_variant_args");
-    let args = Vec::from_fn(adt::num_args(repr, disr_val), |i| {
+    let args = range(0, adt::num_args(repr, disr_val)).map(|i| {
         adt::trans_field_ptr(bcx, repr, val, disr_val, i)
-    });
+    }).collect();
 
     ExtractedBlock { vals: args, bcx: bcx }
 }
@@ -748,7 +748,7 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option<uint> {
         }
     }
 
-    let column_score: |&[Match], uint| -> uint = |m, col| {
+    let column_score = |&: m: &[Match], col: uint| -> uint {
         let total_score = m.iter()
             .map(|row| row.pats[col])
             .map(|pat| pat_score(def_map, pat))
@@ -1122,7 +1122,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                     let t = if kind == Compare {
                         left_ty
                     } else {
-                        ty::mk_uint() // vector length
+                        tcx.types.uint // vector length
                     };
                     let Result { bcx: after_cx, val: matches } = {
                         match opt.trans(bcx) {
@@ -1263,7 +1263,7 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool
     };
     {
         let param_env = ty::empty_parameter_environment();
-        let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx, param_env);
+        let mut visitor = euv::ExprUseVisitor::new(&mut rc, bcx, &param_env);
         visitor.walk_expr(body);
     }
     rc.reassigned
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 595d252a0b1..24a3bb42c90 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -163,12 +163,12 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }).collect::<Vec<_>>();
             let packed = ty::lookup_packed(cx.tcx(), def_id);
             let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
-            if dtor { ftys.push(ty::mk_bool()); }
+            if dtor { ftys.push(cx.tcx().types.bool); }
 
             Univariant(mk_struct(cx, ftys[], packed, t), dtor)
         }
         ty::ty_unboxed_closure(def_id, _, substs) => {
-            let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs);
+            let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs).unwrap();
             let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
             Univariant(mk_struct(cx, upvar_types[], false, t), false)
         }
@@ -183,7 +183,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 // Uninhabitable; represent as unit
                 // (Typechecking will reject discriminant-sizing attrs.)
                 assert_eq!(hint, attr::ReprAny);
-                let ftys = if dtor { vec!(ty::mk_bool()) } else { vec!() };
+                let ftys = if dtor { vec!(cx.tcx().types.bool) } else { vec!() };
                 return Univariant(mk_struct(cx, ftys[], false, t),
                                   dtor);
             }
@@ -215,7 +215,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 // (Typechecking will reject discriminant-sizing attrs.)
                 assert_eq!(hint, attr::ReprAny);
                 let mut ftys = cases[0].tys.clone();
-                if dtor { ftys.push(ty::mk_bool()); }
+                if dtor { ftys.push(cx.tcx().types.bool); }
                 return Univariant(mk_struct(cx, ftys[], false, t),
                                   dtor);
             }
@@ -261,9 +261,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // Create the set of structs that represent each variant
             // Use the minimum integer type we figured out above
             let fields : Vec<_> = cases.iter().map(|c| {
-                let mut ftys = vec!(ty_of_inttype(min_ity));
+                let mut ftys = vec!(ty_of_inttype(cx.tcx(), min_ity));
                 ftys.push_all(c.tys.as_slice());
-                if dtor { ftys.push(ty::mk_bool()); }
+                if dtor { ftys.push(cx.tcx().types.bool); }
                 mk_struct(cx, ftys.as_slice(), false, t)
             }).collect();
 
@@ -314,9 +314,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             };
 
             let fields : Vec<_> = cases.iter().map(|c| {
-                let mut ftys = vec!(ty_of_inttype(ity));
+                let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity));
                 ftys.push_all(c.tys[]);
-                if dtor { ftys.push(ty::mk_bool()); }
+                if dtor { ftys.push(cx.tcx().types.bool); }
                 mk_struct(cx, ftys[], false, t)
             }).collect();
 
@@ -343,7 +343,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
                                     mut path: DiscrField) -> Option<DiscrField> {
     match ty.sty {
         // Fat &T/&mut T/Box<T> i.e. T is [T], str, or Trait
-        ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) if !ty::type_is_sized(tcx, ty) => {
+        ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) if !type_is_sized(tcx, ty) => {
             path.push(FAT_PTR_ADDR);
             Some(path)
         },
@@ -447,12 +447,12 @@ fn mk_struct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                        tys: &[Ty<'tcx>], packed: bool,
                        scapegoat: Ty<'tcx>)
                        -> Struct<'tcx> {
-    let sized = tys.iter().all(|&ty| ty::type_is_sized(cx.tcx(), ty));
+    let sized = tys.iter().all(|&ty| type_is_sized(cx.tcx(), ty));
     let lltys : Vec<Type> = if sized {
         tys.iter()
            .map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
     } else {
-        tys.iter().filter(|&ty| ty::type_is_sized(cx.tcx(), *ty))
+        tys.iter().filter(|&ty| type_is_sized(cx.tcx(), *ty))
            .map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
     };
 
@@ -553,11 +553,10 @@ fn bounds_usable(cx: &CrateContext, ity: IntType, bounds: &IntBounds) -> bool {
     }
 }
 
-// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
-pub fn ty_of_inttype<'tcx>(ity: IntType) -> Ty<'tcx> {
+pub fn ty_of_inttype<'tcx>(tcx: &ty::ctxt<'tcx>, ity: IntType) -> Ty<'tcx> {
     match ity {
-        attr::SignedInt(t) => ty::mk_mach_int(t),
-        attr::UnsignedInt(t) => ty::mk_mach_uint(t)
+        attr::SignedInt(t) => ty::mk_mach_int(tcx, t),
+        attr::UnsignedInt(t) => ty::mk_mach_uint(tcx, t)
     }
 }
 
@@ -704,7 +703,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
                              sizing: bool, dst: bool) -> Vec<Type> {
     if sizing {
-        st.fields.iter().filter(|&ty| !dst || ty::type_is_sized(cx.tcx(), *ty))
+        st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty))
             .map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
     } else {
         st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect()
@@ -995,8 +994,10 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
 /// Access the struct drop flag, if present.
 pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, val: ValueRef)
-                                       -> datum::DatumBlock<'blk, 'tcx, datum::Expr> {
-    let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), ty::mk_bool());
+                                       -> datum::DatumBlock<'blk, 'tcx, datum::Expr>
+{
+    let tcx = bcx.tcx();
+    let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.types.bool);
     match *r {
         Univariant(ref st, true) => {
             let flag_ptr = GEPi(bcx, val, &[0, st.fields.len() - 1]);
@@ -1006,7 +1007,7 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx
             let fcx = bcx.fcx;
             let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
             let scratch = unpack_datum!(bcx, datum::lvalue_scratch_datum(
-                bcx, ty::mk_bool(), "drop_flag", false,
+                bcx, tcx.types.bool, "drop_flag", false,
                 cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| bcx
             ));
             bcx = fold_variants(bcx, r, val, |variant_cx, st, value| {
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index dd5809730d6..18155d75680 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -43,7 +43,7 @@ use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::subst;
 use middle::weak_lang_items;
 use middle::subst::{Subst, Substs};
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, Ty, UnboxedClosureTyper};
 use session::config::{mod, NoDebugInfo, FullDebugInfo};
 use session::Session;
 use trans::_match;
@@ -55,7 +55,7 @@ use trans::cleanup::CleanupMethods;
 use trans::cleanup;
 use trans::closure;
 use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral};
-use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_uint, C_undef};
+use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
 use trans::common::{CrateContext, ExternMap, FunctionContext};
 use trans::common::{NodeInfo, Result};
 use trans::common::{node_id_type, return_type_is_void};
@@ -73,7 +73,7 @@ use trans::glue;
 use trans::inline;
 use trans::intrinsic;
 use trans::machine;
-use trans::machine::{llsize_of, llsize_of_real, llalign_of_min};
+use trans::machine::{llsize_of, llsize_of_real};
 use trans::meth;
 use trans::monomorphize;
 use trans::tvec;
@@ -257,12 +257,12 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
 }
 
 pub fn self_type_for_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                     closure_id: ast::DefId,
-                                     fn_ty: Ty<'tcx>)
-                                     -> Ty<'tcx> {
-    let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
-    let unboxed_closure = &(*unboxed_closures)[closure_id];
-    match unboxed_closure.kind {
+                                               closure_id: ast::DefId,
+                                               fn_ty: Ty<'tcx>)
+                                               -> Ty<'tcx>
+{
+    let unboxed_closure_kind = ccx.tcx().unboxed_closure_kind(closure_id);
+    match unboxed_closure_kind {
         ty::FnUnboxedClosureKind => {
             ty::mk_imm_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty)
         }
@@ -281,6 +281,8 @@ pub fn kind_for_unboxed_closure(ccx: &CrateContext, closure_id: ast::DefId)
 
 pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                               fn_ty: Ty<'tcx>, name: &str) -> ValueRef {
+    let fn_ty = monomorphize::normalize_associated_type(ccx.tcx(), &fn_ty);
+
     let (inputs, output, abi, env) = match fn_ty.sty {
         ty::ty_bare_fn(_, ref f) => {
             (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, None)
@@ -289,13 +291,15 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, Some(Type::i8p(ccx)))
         }
         ty::ty_unboxed_closure(closure_did, _, substs) => {
-            let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
-            let unboxed_closure = &(*unboxed_closures)[closure_did];
-            let function_type = unboxed_closure.closure_type.clone();
+            let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
+            let function_type = typer.unboxed_closure_type(closure_did, substs);
             let self_type = self_type_for_unboxed_closure(ccx, closure_did, fn_ty);
             let llenvironment_type = type_of_explicit_arg(ccx, self_type);
-            (function_type.sig.0.inputs.iter().map(|t| t.subst(ccx.tcx(), substs)).collect(),
-             function_type.sig.0.output.subst(ccx.tcx(), substs),
+            debug!("decl_rust_fn: function_type={} self_type={}",
+                   function_type.repr(ccx.tcx()),
+                   self_type.repr(ccx.tcx()));
+            (function_type.sig.0.inputs,
+             function_type.sig.0.output,
              RustCall,
              Some(llenvironment_type))
         }
@@ -394,30 +398,6 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
 }
 
-pub fn malloc_raw_dyn_proc<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>)
-                                       -> Result<'blk, 'tcx> {
-    let _icx = push_ctxt("malloc_raw_dyn_proc");
-    let ccx = bcx.ccx();
-
-    // Grab the TypeRef type of ptr_ty.
-    let ptr_ty = ty::mk_uniq(bcx.tcx(), t);
-    let ptr_llty = type_of(ccx, ptr_ty);
-
-    let llty = type_of(bcx.ccx(), t);
-    let size = llsize_of(bcx.ccx(), llty);
-    let llalign = C_uint(ccx, llalign_of_min(bcx.ccx(), llty));
-
-    // Allocate space and store the destructor pointer:
-    let Result {bcx, val: llbox} = malloc_raw_dyn(bcx, ptr_llty, t, size, llalign);
-    let dtor_ptr = GEPi(bcx, llbox, &[0u, abi::BOX_FIELD_DROP_GLUE]);
-    let drop_glue_field_ty = type_of(ccx, ty::mk_nil_ptr(bcx.tcx()));
-    let drop_glue = PointerCast(bcx, glue::get_drop_glue(ccx, ty::mk_uniq(bcx.tcx(), t)),
-                                drop_glue_field_ty);
-    Store(bcx, drop_glue, dtor_ptr);
-
-    Result::new(bcx, llbox)
-}
-
 // Type descriptor and type glue stuff
 
 pub fn get_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -576,12 +556,12 @@ pub fn compare_scalar_types<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                         t: Ty<'tcx>,
                                         op: ast::BinOp)
                                         -> Result<'blk, 'tcx> {
-    let f = |a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op));
+    let f = |&: a| Result::new(cx, compare_scalar_values(cx, lhs, rhs, a, op));
 
     match t.sty {
         ty::ty_tup(ref tys) if tys.is_empty() => f(nil_type),
         ty::ty_bool | ty::ty_uint(_) | ty::ty_char => f(unsigned_int),
-        ty::ty_ptr(mt) if ty::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int),
+        ty::ty_ptr(mt) if common::type_is_sized(cx.tcx(), mt.ty) => f(unsigned_int),
         ty::ty_int(_) => f(signed_int),
         ty::ty_float(_) => f(floating_point),
             // Should never get here, because t is scalar.
@@ -719,7 +699,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         return cx;
     }
 
-    let (data_ptr, info) = if ty::type_is_sized(cx.tcx(), t) {
+    let (data_ptr, info) = if common::type_is_sized(cx.tcx(), t) {
         (av, None)
     } else {
         let data = GEPi(cx, av, &[0, abi::FAT_PTR_ADDR]);
@@ -736,7 +716,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                   let field_ty = field_ty.mt.ty;
                   let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, discr, i);
 
-                  let val = if ty::type_is_sized(cx.tcx(), field_ty) {
+                  let val = if common::type_is_sized(cx.tcx(), field_ty) {
                       llfld_a
                   } else {
                       let boxed_ty = ty::mk_open(cx.tcx(), field_ty);
@@ -751,7 +731,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
       }
       ty::ty_unboxed_closure(def_id, _, substs) => {
           let repr = adt::represent_type(cx.ccx(), t);
-          let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs);
+          let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs).unwrap();
           for (i, upvar) in upvars.iter().enumerate() {
               let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
               cx = f(cx, llupvar, upvar.ty);
@@ -786,7 +766,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                     substs, f);
               }
               (_match::Switch, Some(lldiscrim_a)) => {
-                  cx = f(cx, lldiscrim_a, ty::mk_int());
+                  cx = f(cx, lldiscrim_a, cx.tcx().types.int);
                   let unr_cx = fcx.new_temp_block("enum-iter-unr");
                   Unreachable(unr_cx);
                   let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
@@ -983,23 +963,14 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                           llfn: ValueRef,
                           llargs: &[ValueRef],
                           fn_ty: Ty<'tcx>,
-                          call_info: Option<NodeInfo>,
-                          // FIXME(15064) is_lang_item is a horrible hack, please remove it
-                          // at the soonest opportunity.
-                          is_lang_item: bool)
+                          call_info: Option<NodeInfo>)
                           -> (ValueRef, Block<'blk, 'tcx>) {
     let _icx = push_ctxt("invoke_");
     if bcx.unreachable.get() {
         return (C_null(Type::i8(bcx.ccx())), bcx);
     }
 
-    // FIXME(15064) Lang item methods may (in the reflect case) not have proper
-    // types, so doing an attribute lookup will fail.
-    let attributes = if is_lang_item {
-        llvm::AttrBuilder::new()
-    } else {
-        get_fn_llvm_attributes(bcx.ccx(), fn_ty)
-    };
+    let attributes = get_fn_llvm_attributes(bcx.ccx(), fn_ty);
 
     match bcx.opt_node_id {
         None => {
@@ -1462,7 +1433,8 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
 
     let uses_outptr = match output_type {
         ty::FnConverging(output_type) => {
-            let substd_output_type = output_type.subst(ccx.tcx(), param_substs);
+            let substd_output_type =
+                monomorphize::apply_param_substs(ccx.tcx(), param_substs, &output_type);
             type_of::return_uses_outptr(ccx, substd_output_type)
         }
         ty::FnDiverging => false
@@ -1521,7 +1493,7 @@ pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>,
     if let ty::FnConverging(output_type) = output {
         // This shouldn't need to recompute the return type,
         // as new_fn_ctxt did it already.
-        let substd_output_type = output_type.subst(fcx.ccx.tcx(), fcx.param_substs);
+        let substd_output_type = fcx.monomorphize(&output_type);
         if !return_type_is_void(fcx.ccx, substd_output_type) {
             // If the function returns nil/bot, there is no real return
             // value, so do not set `llretslotptr`.
@@ -1554,8 +1526,7 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
 }
 
 // work around bizarre resolve errors
-pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
-pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
+type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
 
 // create_datums_for_fn_args: creates rvalue datums for each of the
 // incoming function arguments. These will later be stored into
@@ -1742,7 +1713,7 @@ pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>,
 
     // This shouldn't need to recompute the return type,
     // as new_fn_ctxt did it already.
-    let substd_retty = retty.subst(fcx.ccx.tcx(), fcx.param_substs);
+    let substd_retty = fcx.monomorphize(&retty);
     build_return_block(fcx, ret_cx, substd_retty);
 
     debuginfo::clear_source_location(fcx);
@@ -1775,7 +1746,7 @@ pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
                 retptr.erase_from_parent();
             }
 
-            let retval = if retty == ty::FnConverging(ty::mk_bool()) {
+            let retval = if retty == ty::FnConverging(fcx.ccx.tcx().types.bool) {
                 Trunc(ret_cx, retval, Type::i1(fcx.ccx))
             } else {
                 retval
@@ -2084,7 +2055,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
                                                      param_substs: &Substs<'tcx>,
                                                      llfndecl: ValueRef) {
     let ctor_ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
-    let ctor_ty = ctor_ty.subst(ccx.tcx(), param_substs);
+    let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);
 
     let result_ty = match ctor_ty.sty {
         ty::ty_bare_fn(_, ref bft) => bft.sig.0.output,
@@ -2467,11 +2438,9 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
         ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
         ty::ty_bare_fn(_, ref f) => (f.sig.clone(), f.abi, false),
         ty::ty_unboxed_closure(closure_did, _, substs) => {
-            let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
-            let ref function_type = (*unboxed_closures)[closure_did]
-                                                    .closure_type;
-
-            (function_type.sig.subst(ccx.tcx(), substs), RustCall, true)
+            let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
+            let function_type = typer.unboxed_closure_type(closure_did, substs);
+            (function_type.sig, RustCall, true)
         }
         _ => ccx.sess().bug("expected closure or function.")
     };
@@ -2532,7 +2501,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
             match ret_ty.sty {
                 // `~` pointer return values never alias because ownership
                 // is transferred
-                ty::ty_uniq(it) if !ty::type_is_sized(ccx.tcx(), it) => {}
+                ty::ty_uniq(it) if !common::type_is_sized(ccx.tcx(), it) => {}
                 ty::ty_uniq(_) => {
                     attrs.ret(llvm::NoAliasAttribute);
                 }
@@ -2543,7 +2512,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
             match ret_ty.sty {
                 // These are not really pointers but pairs, (pointer, len)
                 ty::ty_uniq(it) |
-                ty::ty_rptr(_, ty::mt { ty: it, .. }) if !ty::type_is_sized(ccx.tcx(), it) => {}
+                ty::ty_rptr(_, ty::mt { ty: it, .. }) if !common::type_is_sized(ccx.tcx(), it) => {}
                 ty::ty_uniq(inner) | ty::ty_rptr(_, ty::mt { ty: inner, .. }) => {
                     let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, inner));
                     attrs.ret(llvm::DereferenceableAttribute(llret_sz));
@@ -2683,6 +2652,8 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
 
+            debuginfo::insert_reference_to_gdb_debug_scripts_section_global(ccx);
+
             let (start_fn, args) = if use_start_lang_item {
                 let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) {
                     Ok(id) => id,
@@ -2774,10 +2745,11 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
     }
 
     let item = ccx.tcx().map.get(id);
+    debug!("get_item_val: id={} item={}", id, item);
     let val = match item {
         ast_map::NodeItem(i) => {
             let ty = ty::node_id_to_type(ccx.tcx(), i.id);
-            let sym = || exported_name(ccx, id, ty, i.attrs[]);
+            let sym = |&:| exported_name(ccx, id, ty, i.attrs[]);
 
             let v = match i.node {
                 ast::ItemStatic(_, _, ref expr) => {
@@ -3041,14 +3013,14 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
     unsafe {
         let mut declared = HashSet::new();
 
-        let iter_globals = |llmod| {
+        let iter_globals = |&: llmod| {
             ValueIter {
                 cur: llvm::LLVMGetFirstGlobal(llmod),
                 step: llvm::LLVMGetNextGlobal,
             }
         };
 
-        let iter_functions = |llmod| {
+        let iter_functions = |&: llmod| {
             ValueIter {
                 cur: llvm::LLVMGetFirstFunction(llmod),
                 step: llvm::LLVMGetNextFunction,
diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs
index e7d4128eb4e..97f0b92a290 100644
--- a/src/librustc_trans/trans/builder.rs
+++ b/src/librustc_trans/trans/builder.rs
@@ -501,7 +501,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!("Store {} -> {}",
                self.ccx.tn().val_to_string(val),
                self.ccx.tn().val_to_string(ptr));
-        assert!(self.llbuilder.is_not_null());
+        assert!(!self.llbuilder.is_null());
         self.count_insn("store");
         unsafe {
             llvm::LLVMBuildStore(self.llbuilder, val, ptr);
@@ -512,7 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!("Store {} -> {}",
                self.ccx.tn().val_to_string(val),
                self.ccx.tn().val_to_string(ptr));
-        assert!(self.llbuilder.is_not_null());
+        assert!(!self.llbuilder.is_null());
         self.count_insn("store.volatile");
         unsafe {
             let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
@@ -547,7 +547,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // Small vector optimization. This should catch 100% of the cases that
         // we care about.
         if ixs.len() < 16 {
-            let mut small_vec = [ C_i32(self.ccx, 0), ..16 ];
+            let mut small_vec = [ C_i32(self.ccx, 0); 16 ];
             for (small_vec_e, &ix) in small_vec.iter_mut().zip(ixs.iter()) {
                 *small_vec_e = C_i32(self.ccx, ix as i32);
             }
diff --git a/src/librustc_trans/trans/cabi_x86_64.rs b/src/librustc_trans/trans/cabi_x86_64.rs
index 9b678a4f3ae..fffdc9c97ab 100644
--- a/src/librustc_trans/trans/cabi_x86_64.rs
+++ b/src/librustc_trans/trans/cabi_x86_64.rs
@@ -23,6 +23,7 @@ use trans::context::CrateContext;
 use trans::type_::Type;
 
 use std::cmp;
+use std::iter::repeat;
 
 #[deriving(Clone, Copy, PartialEq)]
 enum RegClass {
@@ -286,7 +287,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
     }
 
     let words = (ty_size(ty) + 7) / 8;
-    let mut cls = Vec::from_elem(words, NoClass);
+    let mut cls: Vec<_> = repeat(NoClass).take(words).collect();
     if words > 4 {
         all_mem(cls.as_mut_slice());
         return cls;
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index e3fe749b490..169e52bcfe5 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -514,8 +514,9 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
         return val;
     }
 
-    // Polytype of the function item (may have type params)
-    let fn_tpt = ty::lookup_item_type(tcx, def_id);
+    // Type scheme of the function item (may have type params)
+    let fn_type_scheme = ty::lookup_item_type(tcx, def_id);
+    let fn_type = monomorphize::normalize_associated_type(tcx, &fn_type_scheme.ty);
 
     // Find the actual function pointer.
     let mut val = {
@@ -524,7 +525,7 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
             get_item_val(ccx, def_id.node)
         } else {
             // External reference.
-            trans_external_path(ccx, def_id, fn_tpt.ty)
+            trans_external_path(ccx, def_id, fn_type)
         }
     };
 
@@ -551,7 +552,7 @@ pub fn trans_fn_ref_with_substs<'blk, 'tcx>(
     // This can occur on either a crate-local or crate-external
     // reference. It also occurs when testing libcore and in some
     // other weird situations. Annoying.
-    let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty);
+    let llty = type_of::type_of_fn_from_ty(ccx, fn_type);
     let llptrty = llty.ptr_to();
     if val_ty(val) != llptrty {
         debug!("trans_fn_ref_with_vtables(): casting pointer!");
@@ -722,7 +723,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             };
             if !is_rust_fn ||
               type_of::return_uses_outptr(ccx, ret_ty) ||
-              ty::type_needs_drop(bcx.tcx(), ret_ty) {
+              type_needs_drop(bcx.tcx(), ret_ty) {
                 // Push the out-pointer if we use an out-pointer for this
                 // return type, otherwise push "undef".
                 if type_is_zero_size(ccx, ret_ty) {
@@ -779,8 +780,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
                                       llfn,
                                       llargs[],
                                       callee_ty,
-                                      call_info,
-                                      dest.is_none());
+                                      call_info);
         bcx = b;
         llresult = llret;
 
diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs
index c1bb21c496a..8ac427dd061 100644
--- a/src/librustc_trans/trans/cleanup.rs
+++ b/src/librustc_trans/trans/cleanup.rs
@@ -24,7 +24,8 @@ use trans::common;
 use trans::common::{Block, FunctionContext, ExprId, NodeInfo};
 use trans::debuginfo;
 use trans::glue;
-use middle::region;
+// Temporary due to slicing syntax hacks (KILLME)
+//use middle::region;
 use trans::type_::Type;
 use middle::ty::{mod, Ty};
 use std::fmt;
@@ -62,7 +63,7 @@ pub const EXIT_MAX: uint = 2;
 pub enum CleanupScopeKind<'blk, 'tcx: 'blk> {
     CustomScopeKind,
     AstScopeKind(ast::NodeId),
-    LoopScopeKind(ast::NodeId, [Block<'blk, 'tcx>, ..EXIT_MAX])
+    LoopScopeKind(ast::NodeId, [Block<'blk, 'tcx>; EXIT_MAX])
 }
 
 impl<'blk, 'tcx: 'blk> fmt::Show for CleanupScopeKind<'blk, 'tcx> {
@@ -128,7 +129,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
         // excluding id's that correspond to closure bodies only). For
         // now we just say that if there is already an AST scope on the stack,
         // this new AST scope had better be its immediate child.
-        let top_scope = self.top_ast_scope();
+        // Temporarily removed due to slicing syntax hacks (KILLME).
+        /*let top_scope = self.top_ast_scope();
         if top_scope.is_some() {
             assert_eq!(self.ccx
                            .tcx()
@@ -136,7 +138,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
                            .opt_encl_scope(region::CodeExtent::from_node_id(debug_loc.id))
                            .map(|s|s.node_id()),
                        top_scope);
-        }
+        }*/
 
         self.push_scope(CleanupScope::new(AstScopeKind(debug_loc.id),
                                           Some(debug_loc)));
@@ -144,7 +146,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
 
     fn push_loop_cleanup_scope(&self,
                                id: ast::NodeId,
-                               exits: [Block<'blk, 'tcx>, ..EXIT_MAX]) {
+                               exits: [Block<'blk, 'tcx>; EXIT_MAX]) {
         debug!("push_loop_cleanup_scope({})",
                self.ccx.tcx().map.node_to_string(id));
         assert_eq!(Some(id), self.top_ast_scope());
@@ -277,10 +279,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
                          cleanup_scope: ScopeId,
                          val: ValueRef,
                          ty: Ty<'tcx>) {
-        if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
+        if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = box DropValue {
             is_immediate: false,
-            must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
+            must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
             val: val,
             ty: ty,
             zero: false
@@ -299,10 +301,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
                                   cleanup_scope: ScopeId,
                                   val: ValueRef,
                                   ty: Ty<'tcx>) {
-        if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
+        if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = box DropValue {
             is_immediate: false,
-            must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
+            must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
             val: val,
             ty: ty,
             zero: true
@@ -323,10 +325,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
                                val: ValueRef,
                                ty: Ty<'tcx>) {
 
-        if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
+        if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = box DropValue {
             is_immediate: true,
-            must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
+            must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
             val: val,
             ty: ty,
             zero: false
@@ -734,7 +736,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
                         let f = base::decl_cdecl_fn(self.ccx,
                                                     "rust_eh_personality",
                                                     fty,
-                                                    ty::mk_i32());
+                                                    self.ccx.tcx().types.i32);
                         *personality = Some(f);
                         f
                     }
@@ -1056,7 +1058,7 @@ pub trait CleanupMethods<'blk, 'tcx> {
     fn push_ast_cleanup_scope(&self, id: NodeInfo);
     fn push_loop_cleanup_scope(&self,
                                id: ast::NodeId,
-                               exits: [Block<'blk, 'tcx>, ..EXIT_MAX]);
+                               exits: [Block<'blk, 'tcx>; EXIT_MAX]);
     fn push_custom_cleanup_scope(&self) -> CustomScopeIndex;
     fn push_custom_cleanup_scope_with_debug_loc(&self,
                                                 debug_loc: NodeInfo)
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index 0ae9de8c891..93a5b54fde3 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -22,11 +22,11 @@ use trans::common::*;
 use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
 use trans::debuginfo;
 use trans::expr;
-use trans::monomorphize::MonoId;
+use trans::monomorphize::{mod, MonoId};
 use trans::type_of::*;
 use trans::type_::Type;
-use middle::ty::{mod, Ty};
-use middle::subst::{Subst, Substs};
+use middle::ty::{mod, Ty, UnboxedClosureTyper};
+use middle::subst::{Substs};
 use session::config::FullDebugInfo;
 use util::ppaux::Repr;
 use util::ppaux::ty_to_string;
@@ -133,28 +133,8 @@ pub fn mk_closure_tys<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
-    let ptr = ty::mk_imm_ptr(tcx, ty::mk_i8());
-    ty::mk_tup(tcx, vec!(ty::mk_uint(), ty::mk_nil_ptr(tcx), ptr, ptr, t))
-}
-
-fn allocate_cbox<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                             store: ty::TraitStore,
-                             cdata_ty: Ty<'tcx>)
-                             -> Result<'blk, 'tcx> {
-    let _icx = push_ctxt("closure::allocate_cbox");
-    let tcx = bcx.tcx();
-
-    // Allocate and initialize the box:
-    let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
-    match store {
-        ty::UniqTraitStore => {
-            malloc_raw_dyn_proc(bcx, cbox_ty)
-        }
-        ty::RegionTraitStore(..) => {
-            let llbox = alloc_ty(bcx, cbox_ty, "__closure");
-            Result::new(bcx, llbox)
-        }
-    }
+    let ptr = ty::mk_imm_ptr(tcx, tcx.types.i8);
+    ty::mk_tup(tcx, vec!(tcx.types.uint, ty::mk_nil_ptr(tcx), ptr, ptr, t))
 }
 
 pub struct ClosureResult<'blk, 'tcx: 'blk> {
@@ -168,8 +148,7 @@ pub struct ClosureResult<'blk, 'tcx: 'blk> {
 // heap allocated closure that copies the upvars into environment.
 // Otherwise, it is stack allocated and copies pointers to the upvars.
 pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                     bound_values: Vec<EnvValue<'tcx>> ,
-                                     store: ty::TraitStore)
+                                     bound_values: Vec<EnvValue<'tcx>>)
                                      -> ClosureResult<'blk, 'tcx> {
     let _icx = push_ctxt("closure::store_environment");
     let ccx = bcx.ccx();
@@ -193,7 +172,7 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     // allocate closure in the heap
-    let Result {bcx, val: llbox} = allocate_cbox(bcx, store, cdata_ty);
+    let llbox = alloc_ty(bcx, cbox_ty, "__closure");
 
     let llbox = PointerCast(bcx, llbox, llboxptr_ty);
     debug!("tuplify_box_ty = {}", ty_to_string(tcx, cbox_ty));
@@ -227,8 +206,7 @@ pub fn store_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 // collects the upvars and packages them up for store_environment.
 fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>,
                              freevar_mode: ast::CaptureClause,
-                             freevars: &Vec<ty::Freevar>,
-                             store: ty::TraitStore)
+                             freevars: &Vec<ty::Freevar>)
                              -> ClosureResult<'blk, 'tcx> {
     let _icx = push_ctxt("closure::build_closure");
 
@@ -242,7 +220,7 @@ fn build_closure<'blk, 'tcx>(bcx0: Block<'blk, 'tcx>,
         env_vals.push(EnvValue {action: freevar_mode, datum: datum});
     }
 
-    store_environment(bcx, env_vals, store)
+    store_environment(bcx, env_vals)
 }
 
 // Given an enclosing block context, a new function context, a closure type,
@@ -456,7 +434,7 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         llbox,
         cdata_ty,
         bcx
-    } = build_closure(bcx, freevar_mode, &freevars, store);
+    } = build_closure(bcx, freevar_mode, &freevars);
 
     trans_closure(ccx,
                   decl,
@@ -486,7 +464,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
     }
 
     let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
-    let function_type = function_type.subst(bcx.tcx(), substs);
+    let function_type = monomorphize::apply_param_substs(bcx.tcx(), substs, &function_type);
 
     // Normalize type so differences in regions and typedefs don't cause
     // duplicate declarations
@@ -533,7 +511,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
                              body: &ast::Block,
                              id: ast::NodeId,
                              dest: expr::Dest)
-                             -> Block<'blk, 'tcx> {
+                             -> Block<'blk, 'tcx>
+{
     let _icx = push_ctxt("closure::trans_unboxed_closure");
 
     debug!("trans_unboxed_closure()");
@@ -544,9 +523,13 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
         closure_id,
         bcx.fcx.param_substs).unwrap();
 
-    let function_type = (*bcx.tcx().unboxed_closures.borrow())[closure_id]
-                                                              .closure_type
-                                                              .clone();
+    // Get the type of this closure. Use the current `param_substs` as
+    // the closure substitutions. This makes sense because the closure
+    // takes the same set of type arguments as the enclosing fn, and
+    // this function (`trans_unboxed_closure`) is invoked at the point
+    // of the closure expression.
+    let typer = NormalizingUnboxedClosureTyper::new(bcx.tcx());
+    let function_type = typer.unboxed_closure_type(closure_id, bcx.fcx.param_substs);
     let function_type = ty::mk_closure(bcx.tcx(), function_type);
 
     let freevars: Vec<ty::Freevar> =
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 1f61fed3998..aa882240880 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -24,28 +24,27 @@ use middle::infer;
 use middle::lang_items::LangItem;
 use middle::mem_categorization as mc;
 use middle::region;
-use middle::subst;
-use middle::subst::{Subst, Substs};
+use middle::subst::{mod, Subst, Substs};
 use trans::base;
 use trans::build;
 use trans::cleanup;
 use trans::datum;
 use trans::debuginfo;
 use trans::machine;
+use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
 use middle::traits;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, HasProjectionTypes, Ty};
 use middle::ty_fold;
-use middle::ty_fold::TypeFoldable;
+use middle::ty_fold::{TypeFolder, TypeFoldable};
 use util::ppaux::Repr;
-use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
+use util::nodemap::{FnvHashMap, NodeMap};
 
 use arena::TypedArena;
 use libc::{c_uint, c_char};
 use std::c_str::ToCStr;
 use std::cell::{Cell, RefCell};
-use std::rc::Rc;
 use std::vec::Vec;
 use syntax::ast::Ident;
 use syntax::ast;
@@ -53,9 +52,110 @@ use syntax::ast_map::{PathElem, PathName};
 use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
+use util::common::memoized;
+use util::nodemap::FnvHashSet;
 
 pub use trans::context::CrateContext;
 
+// Is the type's representation size known at compile time?
+pub fn type_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
+    ty::type_contents(cx, ty).is_sized(cx)
+}
+
+pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.sty {
+        ty::ty_open(_) => true,
+        _ => type_is_sized(cx, ty),
+    }
+}
+
+pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.sty {
+        ty::ty_ptr(ty::mt{ty, ..}) |
+        ty::ty_rptr(_, ty::mt{ty, ..}) |
+        ty::ty_uniq(ty) => {
+            !type_is_sized(cx, ty)
+        }
+        _ => {
+            false
+        }
+    }
+}
+
+// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized.
+// 'Smallest' here means component of the static representation of the type; not
+// the size of an object at runtime.
+pub fn unsized_part_of_type<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+    match ty.sty {
+        ty::ty_str | ty::ty_trait(..) | ty::ty_vec(..) => ty,
+        ty::ty_struct(def_id, substs) => {
+            let unsized_fields: Vec<_> =
+                ty::struct_fields(cx, def_id, substs)
+                .iter()
+                .map(|f| f.mt.ty)
+                .filter(|ty| !type_is_sized(cx, *ty))
+                .collect();
+
+            // Exactly one of the fields must be unsized.
+            assert!(unsized_fields.len() == 1);
+
+            unsized_part_of_type(cx, unsized_fields[0])
+        }
+        _ => {
+            assert!(type_is_sized(cx, ty),
+                    "unsized_part_of_type failed even though ty is unsized");
+            panic!("called unsized_part_of_type with sized ty");
+        }
+    }
+}
+
+// Some things don't need cleanups during unwinding because the
+// task can free them all at once later. Currently only things
+// that only contain scalars and shared boxes can avoid unwind
+// cleanups.
+pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
+    return memoized(ccx.needs_unwind_cleanup_cache(), ty, |ty| {
+        type_needs_unwind_cleanup_(ccx.tcx(), ty, &mut FnvHashSet::new())
+    });
+
+    fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                        ty: Ty<'tcx>,
+                                        tycache: &mut FnvHashSet<Ty<'tcx>>)
+                                        -> bool
+    {
+        // Prevent infinite recursion
+        if !tycache.insert(ty) {
+            return false;
+        }
+
+        let mut needs_unwind_cleanup = false;
+        ty::maybe_walk_ty(ty, |ty| {
+            needs_unwind_cleanup |= match ty.sty {
+                ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) |
+                ty::ty_float(_) | ty::ty_tup(_) | ty::ty_ptr(_) => false,
+
+                ty::ty_enum(did, substs) =>
+                    ty::enum_variants(tcx, did).iter().any(|v|
+                        v.args.iter().any(|&aty| {
+                            let t = aty.subst(tcx, substs);
+                            type_needs_unwind_cleanup_(tcx, t, tycache)
+                        })
+                    ),
+
+                _ => true
+            };
+            !needs_unwind_cleanup
+        });
+        needs_unwind_cleanup
+    }
+}
+
+pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
+                             ty: Ty<'tcx>)
+                             -> bool {
+    ty::type_contents(cx, ty).needs_drop(cx)
+}
+
 fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                        ty: Ty<'tcx>) -> bool {
     match ty.sty {
@@ -79,10 +179,10 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
         ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
         type_is_newtype_immediate(ccx, ty) ||
         ty::type_is_simd(tcx, ty);
-    if simple && !ty::type_is_fat_ptr(tcx, ty) {
+    if simple && !type_is_fat_ptr(tcx, ty) {
         return true;
     }
-    if !ty::type_is_sized(tcx, ty) {
+    if !type_is_sized(tcx, ty) {
         return false;
     }
     match ty.sty {
@@ -190,8 +290,8 @@ pub fn validate_substs(substs: &Substs) {
 }
 
 // work around bizarre resolve errors
-pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
-pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
+type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
+type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
 
 // Function context.  Every LLVM function we create will have one of
 // these.
@@ -364,6 +464,14 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
         }
         return out;
     }
+
+    pub fn monomorphize<T>(&self, value: &T) -> T
+        where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+    {
+        monomorphize::apply_param_substs(self.ccx.tcx(),
+                                         self.param_substs,
+                                         value)
+    }
 }
 
 // Basic block context.  We create a block context for each basic block
@@ -456,6 +564,14 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
     pub fn to_str(&self) -> String {
         format!("[block {:p}]", self)
     }
+
+    pub fn monomorphize<T>(&self, value: &T) -> T
+        where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+    {
+        monomorphize::apply_param_substs(self.tcx(),
+                                         self.fcx.param_substs,
+                                         value)
+    }
 }
 
 impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
@@ -501,13 +617,8 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
         self.tcx().region_maps.temporary_scope(rvalue_id)
     }
 
-    fn unboxed_closures<'a>(&'a self)
-                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
-        &self.tcx().unboxed_closures
-    }
-
-    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
-        self.tcx().upvar_borrow_map.borrow()[upvar_id].clone()
+    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
+        Some(self.tcx().upvar_borrow_map.borrow()[upvar_id].clone())
     }
 
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
@@ -516,6 +627,34 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
     }
 }
 
+impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
+    fn unboxed_closure_kind(&self,
+                            def_id: ast::DefId)
+                            -> ty::UnboxedClosureKind
+    {
+        let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+        typer.unboxed_closure_kind(def_id)
+    }
+
+    fn unboxed_closure_type(&self,
+                            def_id: ast::DefId,
+                            substs: &subst::Substs<'tcx>)
+                            -> ty::ClosureTy<'tcx>
+    {
+        let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+        typer.unboxed_closure_type(def_id, substs)
+    }
+
+    fn unboxed_closure_upvars(&self,
+                              def_id: ast::DefId,
+                              substs: &Substs<'tcx>)
+                              -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
+    {
+        let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+        typer.unboxed_closure_upvars(def_id, substs)
+    }
+}
+
 pub struct Result<'blk, 'tcx: 'blk> {
     pub bcx: Block<'blk, 'tcx>,
     pub val: ValueRef
@@ -758,7 +897,7 @@ pub fn is_null(val: ValueRef) -> bool {
 }
 
 pub fn monomorphize_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
-    t.subst(bcx.tcx(), bcx.fcx.param_substs)
+    bcx.fcx.monomorphize(&t)
 }
 
 pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty<'tcx> {
@@ -780,7 +919,7 @@ pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) ->
 /// guarantee to us that all nested obligations *could be* resolved if we wanted to.
 pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                     span: Span,
-                                    trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+                                    trait_ref: ty::PolyTraitRef<'tcx>)
                                     -> traits::Vtable<'tcx, ()>
 {
     let tcx = ccx.tcx();
@@ -808,9 +947,10 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
-    let mut selcx = traits::SelectionContext::new(&infcx, &param_env, tcx);
+    let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
+    let mut selcx = traits::SelectionContext::new(&infcx, &param_env, &typer);
     let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
-                                             trait_ref.clone());
+                                             trait_ref.to_poly_trait_predicate());
     let selection = match selcx.select(&obligation) {
         Ok(Some(selection)) => selection,
         Ok(None) => {
@@ -838,28 +978,89 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     // Currently, we use a fulfillment context to completely resolve
     // all nested obligations. This is because they can inform the
-    // inference of the impl's type parameters. However, in principle,
-    // we only need to do this until the impl's type parameters are
-    // fully bound. It could be a slight optimization to stop
-    // iterating early.
+    // inference of the impl's type parameters.
     let mut fulfill_cx = traits::FulfillmentContext::new();
     let vtable = selection.map_move_nested(|predicate| {
-        fulfill_cx.register_predicate(infcx.tcx, predicate);
+        fulfill_cx.register_predicate_obligation(&infcx, predicate);
     });
-    match fulfill_cx.select_all_or_error(&infcx, &param_env, tcx) {
+    let vtable = drain_fulfillment_cx(span, &infcx, &param_env, &mut fulfill_cx, &vtable);
+
+    info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
+    ccx.trait_cache().borrow_mut().insert(trait_ref,
+                                          vtable.clone());
+
+    vtable
+}
+
+pub struct NormalizingUnboxedClosureTyper<'a,'tcx:'a> {
+    tcx: &'a ty::ctxt<'tcx>
+}
+
+impl<'a,'tcx> NormalizingUnboxedClosureTyper<'a,'tcx> {
+    pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingUnboxedClosureTyper<'a,'tcx> {
+        NormalizingUnboxedClosureTyper { tcx: tcx }
+    }
+}
+
+impl<'a,'tcx> ty::UnboxedClosureTyper<'tcx> for NormalizingUnboxedClosureTyper<'a,'tcx> {
+    fn unboxed_closure_kind(&self,
+                            def_id: ast::DefId)
+                            -> ty::UnboxedClosureKind
+    {
+        self.tcx.unboxed_closure_kind(def_id)
+    }
+
+    fn unboxed_closure_type(&self,
+                            def_id: ast::DefId,
+                            substs: &subst::Substs<'tcx>)
+                            -> ty::ClosureTy<'tcx>
+    {
+        // the substitutions in `substs` are already monomorphized,
+        // but we still must normalize associated types
+        let closure_ty = self.tcx.unboxed_closure_type(def_id, substs);
+        monomorphize::normalize_associated_type(self.tcx, &closure_ty)
+    }
+
+    fn unboxed_closure_upvars(&self,
+                              def_id: ast::DefId,
+                              substs: &Substs<'tcx>)
+                              -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
+    {
+        // the substitutions in `substs` are already monomorphized,
+        // but we still must normalize associated types
+        let result = ty::unboxed_closure_upvars(self.tcx, def_id, substs);
+        monomorphize::normalize_associated_type(self.tcx, &result)
+    }
+}
+
+pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
+                                       infcx: &infer::InferCtxt<'a,'tcx>,
+                                       param_env: &ty::ParameterEnvironment<'tcx>,
+                                       fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                                       result: &T)
+                                       -> T
+    where T : TypeFoldable<'tcx> + Repr<'tcx>
+{
+    debug!("drain_fulfillment_cx(result={})",
+           result.repr(infcx.tcx));
+
+    // In principle, we only need to do this so long as `result`
+    // contains unbound type parameters. It could be a slight
+    // optimization to stop iterating early.
+    let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
+    match fulfill_cx.select_all_or_error(infcx, param_env, &typer) {
         Ok(()) => { }
         Err(errors) => {
             if errors.iter().all(|e| e.is_overflow()) {
                 // See Ok(None) case above.
-                ccx.sess().span_fatal(
+                infcx.tcx.sess.span_fatal(
                     span,
                     "reached the recursion limit during monomorphization");
             } else {
-                tcx.sess.span_bug(
+                infcx.tcx.sess.span_bug(
                     span,
-                    format!("Encountered errors `{}` fulfilling `{}` during trans",
-                            errors.repr(tcx),
-                            trait_ref.repr(tcx))[]);
+                    format!("Encountered errors `{}` fulfilling during trans",
+                            errors.repr(infcx.tcx))[]);
             }
         }
     }
@@ -869,13 +1070,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // sort of overkill because we do not expect there to be any
     // unbound type variables, hence no `TyFresh` types should ever be
     // inserted.
-    let vtable = vtable.fold_with(&mut infcx.freshener());
-
-    info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
-    ccx.trait_cache().borrow_mut().insert(trait_ref,
-                                          vtable.clone());
-
-    vtable
+    result.fold_with(&mut infcx.freshener())
 }
 
 // Key used to lookup values supplied for type parameters in an expr.
@@ -890,7 +1085,8 @@ pub enum ExprOrMethodCall {
 
 pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                   node: ExprOrMethodCall)
-                                  -> subst::Substs<'tcx> {
+                                  -> subst::Substs<'tcx>
+{
     let tcx = bcx.tcx();
 
     let substs = match node {
@@ -911,7 +1107,7 @@ pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     let substs = substs.erase_regions();
-    substs.subst(tcx, bcx.fcx.param_substs)
+    bcx.monomorphize(&substs)
 }
 
 pub fn langcall(bcx: Block,
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index bc386dc96a4..347ec100ae7 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -25,6 +25,7 @@ use middle::ty::{mod, Ty};
 use util::ppaux::{Repr, ty_to_string};
 
 use std::c_str::ToCStr;
+use std::iter::repeat;
 use libc::c_uint;
 use syntax::{ast, ast_util};
 use syntax::ptr::P;
@@ -138,7 +139,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, v: ValueRef,
         Some(ref mt) => {
             match t.sty {
                 ty::ty_ptr(mt) | ty::ty_rptr(_, mt) => {
-                    if ty::type_is_sized(cx.tcx(), mt.ty) {
+                    if type_is_sized(cx.tcx(), mt.ty) {
                         (const_deref_ptr(cx, v), mt.ty)
                     } else {
                         // Derefing a fat pointer does not change the representation,
@@ -304,7 +305,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr)
 // the bool returned is whether this expression can be inlined into other crates
 // if it's assigned to a static.
 fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
-    let map_list = |exprs: &[P<ast::Expr>]| {
+    let map_list = |&: exprs: &[P<ast::Expr>]| {
         exprs.iter().map(|e| const_expr(cx, &**e).0)
              .fold(Vec::new(), |mut l, val| { l.push(val); l })
     };
@@ -608,7 +609,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
                 const_eval::const_uint(i) => i as uint,
                 _ => cx.sess().span_bug(count.span, "count must be integral const expression.")
             };
-            let vs = Vec::from_elem(n, const_expr(cx, &**elem).0);
+            let vs: Vec<_> = repeat(const_expr(cx, &**elem).0).take(n).collect();
             if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
                 C_struct(cx, vs[], false)
             } else {
diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs
index 2c71dd831fb..9ceb0c63990 100644
--- a/src/librustc_trans/trans/context.rs
+++ b/src/librustc_trans/trans/context.rs
@@ -84,6 +84,7 @@ pub struct LocalCrateContext<'tcx> {
     tn: TypeNames,
     externs: RefCell<ExternMap>,
     item_vals: RefCell<NodeMap<ValueRef>>,
+    needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
     fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
     drop_glues: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
     tydescs: RefCell<FnvHashMap<Ty<'tcx>, Rc<tydesc_info<'tcx>>>>,
@@ -99,7 +100,7 @@ pub struct LocalCrateContext<'tcx> {
     monomorphized: RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>>,
     monomorphizing: RefCell<DefIdMap<uint>>,
     /// Cache generated vtables
-    vtables: RefCell<FnvHashMap<(Ty<'tcx>, Rc<ty::PolyTraitRef<'tcx>>), ValueRef>>,
+    vtables: RefCell<FnvHashMap<(Ty<'tcx>, ty::PolyTraitRef<'tcx>), ValueRef>>,
     /// Cache of constant strings,
     const_cstr_cache: RefCell<FnvHashMap<InternedString, ValueRef>>,
 
@@ -150,7 +151,7 @@ pub struct LocalCrateContext<'tcx> {
     /// contexts around the same size.
     n_llvm_insns: Cell<uint>,
 
-    trait_cache: RefCell<FnvHashMap<Rc<ty::PolyTraitRef<'tcx>>,
+    trait_cache: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>,
                                     traits::Vtable<'tcx, ()>>>,
 }
 
@@ -389,6 +390,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
                 tn: TypeNames::new(),
                 externs: RefCell::new(FnvHashMap::new()),
                 item_vals: RefCell::new(NodeMap::new()),
+                needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()),
                 fn_pointer_shims: RefCell::new(FnvHashMap::new()),
                 drop_glues: RefCell::new(FnvHashMap::new()),
                 tydescs: RefCell::new(FnvHashMap::new()),
@@ -569,6 +571,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         &self.shared.link_meta
     }
 
+    pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, bool>> {
+        &self.local.needs_unwind_cleanup_cache
+    }
+
     pub fn fn_pointer_shims(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
         &self.local.fn_pointer_shims
     }
@@ -601,7 +607,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         &self.local.monomorphizing
     }
 
-    pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<(Ty<'tcx>, Rc<ty::PolyTraitRef<'tcx>>),
+    pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<(Ty<'tcx>, ty::PolyTraitRef<'tcx>),
                                                             ValueRef>> {
         &self.local.vtables
     }
@@ -699,7 +705,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         self.local.n_llvm_insns.set(self.local.n_llvm_insns.get() + 1);
     }
 
-    pub fn trait_cache(&self) -> &RefCell<FnvHashMap<Rc<ty::PolyTraitRef<'tcx>>,
+    pub fn trait_cache(&self) -> &RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>,
                                                      traits::Vtable<'tcx, ()>>> {
         &self.local.trait_cache
     }
diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs
index 3b24ded6717..768de89d593 100644
--- a/src/librustc_trans/trans/controlflow.rs
+++ b/src/librustc_trans/trans/controlflow.rs
@@ -87,7 +87,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
                                    -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_stmt_semi");
     let ty = expr_ty(cx, e);
-    if ty::type_needs_drop(cx.tcx(), ty) {
+    if type_needs_drop(cx.tcx(), ty) {
         expr::trans_to_lvalue(cx, e, "stmt").bcx
     } else {
         expr::trans_into(cx, e, expr::Ignore)
diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs
index 9ab4e92b511..83bf06383a8 100644
--- a/src/librustc_trans/trans/datum.rs
+++ b/src/librustc_trans/trans/datum.rs
@@ -218,7 +218,7 @@ impl KindOps for Lvalue {
                               val: ValueRef,
                               ty: Ty<'tcx>)
                               -> Block<'blk, 'tcx> {
-        if ty::type_needs_drop(bcx.tcx(), ty) {
+        if type_needs_drop(bcx.tcx(), ty) {
             // cancel cleanup of affine values by zeroing out
             let () = zero_mem(bcx, val, ty);
             bcx
@@ -398,7 +398,7 @@ impl<'tcx> Datum<'tcx, Expr> {
                                  -> DatumBlock<'blk, 'tcx, Lvalue> {
         debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx()));
 
-        assert!(ty::lltype_is_sized(bcx.tcx(), self.ty),
+        assert!(lltype_is_sized(bcx.tcx(), self.ty),
                 "Trying to convert unsized value to lval");
         self.match_kind(
             |l| DatumBlock::new(bcx, l),
@@ -456,7 +456,7 @@ impl<'tcx> Datum<'tcx, Lvalue> {
         F: FnOnce(ValueRef) -> ValueRef,
     {
         let val = match self.ty.sty {
-            _ if ty::type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
+            _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
             ty::ty_open(_) => {
                 let base = Load(bcx, expr::get_dataptr(bcx, self.val));
                 gep(base)
@@ -567,7 +567,7 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> {
     /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is
     /// naturally passed around by value, and not by reference.
     pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef {
-        assert!(!ty::type_needs_drop(bcx.tcx(), self.ty));
+        assert!(!type_needs_drop(bcx.tcx(), self.ty));
         assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
         if self.kind.is_by_ref() {
             load_ty(bcx, self.val, self.ty)
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index ea2d42bebdf..c651255226b 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -194,12 +194,13 @@ use llvm;
 use llvm::{ModuleRef, ContextRef, ValueRef};
 use llvm::debuginfo::*;
 use metadata::csearch;
-use middle::subst::{mod, Subst, Substs};
+use middle::subst::{mod, Substs};
 use trans::{mod, adt, machine, type_of};
 use trans::common::*;
 use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
+use trans::monomorphize;
 use trans::type_::Type;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, Ty, UnboxedClosureTyper};
 use middle::pat_util;
 use session::config::{mod, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
@@ -212,7 +213,7 @@ use std::ptr;
 use std::rc::{Rc, Weak};
 use syntax::util::interner::Interner;
 use syntax::codemap::{Span, Pos};
-use syntax::{ast, codemap, ast_util, ast_map};
+use syntax::{ast, codemap, ast_util, ast_map, attr};
 use syntax::ast_util::PostExpansionMethod;
 use syntax::parse::token::{mod, special_idents};
 
@@ -426,8 +427,8 @@ impl<'tcx> TypeMap<'tcx> {
 
                 from_def_id_and_substs(self,
                                        cx,
-                                       trait_data.principal.def_id(),
-                                       trait_data.principal.substs(),
+                                       trait_data.principal_def_id(),
+                                       trait_data.principal.0.substs,
                                        &mut unique_type_id);
             },
             ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
@@ -469,9 +470,9 @@ impl<'tcx> TypeMap<'tcx> {
                                                         closure_ty.clone(),
                                                         &mut unique_type_id);
             },
-            ty::ty_unboxed_closure(ref def_id, _, substs) => {
-                let closure_ty = cx.tcx().unboxed_closures.borrow()
-                                   .get(def_id).unwrap().closure_type.subst(cx.tcx(), substs);
+            ty::ty_unboxed_closure(def_id, _, substs) => {
+                let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
+                let closure_ty = typer.unboxed_closure_type(def_id, substs);
                 self.get_unique_type_id_of_closure_type(cx,
                                                         closure_ty,
                                                         &mut unique_type_id);
@@ -740,7 +741,16 @@ pub fn finalize(cx: &CrateContext) {
     }
 
     debug!("finalize");
-    compile_unit_metadata(cx);
+    let _ = compile_unit_metadata(cx);
+
+    if needs_gdb_debug_scripts_section(cx) {
+        // Add a .debug_gdb_scripts section to this compile-unit. This will
+        // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
+        // which activates the Rust pretty printers for binary this section is
+        // contained in.
+        get_or_insert_gdb_debug_scripts_section_global(cx);
+    }
+
     unsafe {
         llvm::LLVMDIBuilderFinalize(DIB(cx));
         llvm::LLVMDIBuilderDispose(DIB(cx));
@@ -1438,7 +1448,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
 
                 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
-                let return_type = return_type.subst(cx.tcx(), param_substs);
+                let return_type = monomorphize::apply_param_substs(cx.tcx(),
+                                                                   param_substs,
+                                                                   &return_type);
                 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
             }
         }
@@ -1447,7 +1459,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         for arg in fn_decl.inputs.iter() {
             assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
             let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
-            let arg_type = arg_type.subst(cx.tcx(), param_substs);
+            let arg_type = monomorphize::apply_param_substs(cx.tcx(),
+                                                            param_substs,
+                                                            &arg_type);
             signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
         }
 
@@ -1459,8 +1473,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                          param_substs: &Substs<'tcx>,
                                          file_metadata: DIFile,
                                          name_to_append_suffix_to: &mut String)
-                                         -> DIArray {
+                                         -> DIArray
+    {
         let self_type = param_substs.self_ty();
+        let self_type = monomorphize::normalize_associated_type(cx.tcx(), &self_type);
 
         // Only true for static default methods:
         let has_self_type = self_type.is_some();
@@ -1579,7 +1595,7 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
     };
 }
 
-fn compile_unit_metadata(cx: &CrateContext) {
+fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
     let work_dir = &cx.sess().working_dir;
     let compile_unit_name = match cx.sess().local_crate_source_file {
         None => fallback_path(cx),
@@ -1614,7 +1630,7 @@ fn compile_unit_metadata(cx: &CrateContext) {
                            (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
 
     let compile_unit_name = compile_unit_name.as_ptr();
-    work_dir.as_vec().with_c_str(|work_dir| {
+    return work_dir.as_vec().with_c_str(|work_dir| {
         producer.with_c_str(|producer| {
             "".with_c_str(|flags| {
                 "".with_c_str(|split_name| {
@@ -1628,7 +1644,7 @@ fn compile_unit_metadata(cx: &CrateContext) {
                             cx.sess().opts.optimize != config::No,
                             flags,
                             0,
-                            split_name);
+                            split_name)
                     }
                 })
             })
@@ -2473,7 +2489,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         })
         .collect();
 
-    let discriminant_type_metadata = |inttype| {
+    let discriminant_type_metadata = |&: inttype| {
         // We can reuse the type of the discriminant for all monomorphized
         // instances of an enum because it doesn't depend on any type parameters.
         // The def_id, uniquely identifying the enum's polytype acts as key in
@@ -2487,9 +2503,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
                 let (discriminant_size, discriminant_align) =
                     size_and_align_of(cx, discriminant_llvm_type);
-                let discriminant_base_type_metadata = type_metadata(cx,
-                                                                    adt::ty_of_inttype(inttype),
-                                                                    codemap::DUMMY_SP);
+                let discriminant_base_type_metadata =
+                    type_metadata(cx,
+                                  adt::ty_of_inttype(cx.tcx(), inttype),
+                                  codemap::DUMMY_SP);
                 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
 
                 let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
@@ -2797,7 +2814,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         MemberDescription {
             name: "length".to_string(),
             llvm_type: member_llvm_types[1],
-            type_metadata: type_metadata(cx, ty::mk_uint(), span),
+            type_metadata: type_metadata(cx, cx.tcx().types.uint, span),
             offset: ComputedMemberOffset,
             flags: FLAGS_NONE
         },
@@ -2877,7 +2894,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     // But it does not describe the trait's methods.
 
     let def_id = match trait_type.sty {
-        ty::ty_trait(box ty::TyTrait { ref principal, .. }) => principal.def_id(),
+        ty::ty_trait(ref data) => data.principal_def_id(),
         _ => {
             let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
             cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \
@@ -2963,7 +2980,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         // FIXME Can we do better than this for unsized vec/str fields?
         ty::ty_vec(typ, None) => fixed_vec_metadata(cx, unique_type_id, typ, 0, usage_site_span),
-        ty::ty_str => fixed_vec_metadata(cx, unique_type_id, ty::mk_i8(), 0, usage_site_span),
+        ty::ty_str => fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, 0, usage_site_span),
         ty::ty_trait(..) => {
             MetadataCreationResult::new(
                         trait_pointer_metadata(cx, t, None, unique_type_id),
@@ -2975,7 +2992,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
                 }
                 ty::ty_str => {
-                    vec_slice_metadata(cx, t, ty::mk_u8(), unique_type_id, usage_site_span)
+                    vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
                 }
                 ty::ty_trait(..) => {
                     MetadataCreationResult::new(
@@ -3003,9 +3020,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::ty_closure(ref closurety) => {
             subroutine_type_metadata(cx, unique_type_id, &closurety.sig, usage_site_span)
         }
-        ty::ty_unboxed_closure(ref def_id, _, substs) => {
-            let sig = cx.tcx().unboxed_closures.borrow()
-                        .get(def_id).unwrap().closure_type.sig.subst(cx.tcx(), substs);
+        ty::ty_unboxed_closure(def_id, _, substs) => {
+            let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
+            let sig = typer.unboxed_closure_type(def_id, substs).sig;
             subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
         }
         ty::ty_struct(def_id, substs) => {
@@ -3388,10 +3405,7 @@ fn create_scope_map(cx: &CrateContext,
                     if need_new_scope {
                         // Create a new lexical scope and push it onto the stack
                         let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
-                        let file_metadata = file_metadata(cx,
-                                                          loc.file
-                                                             .name
-                                                             []);
+                        let file_metadata = file_metadata(cx, loc.file.name[]);
                         let parent_scope = scope_stack.last().unwrap().scope_metadata;
 
                         let scope_metadata = unsafe {
@@ -3533,20 +3547,14 @@ fn create_scope_map(cx: &CrateContext,
             }
 
             ast::ExprAssignOp(_, ref lhs, ref rhs) |
-            ast::ExprIndex(ref lhs, ref rhs)        |
+            ast::ExprIndex(ref lhs, ref rhs) |
             ast::ExprBinary(_, ref lhs, ref rhs)    => {
                 walk_expr(cx, &**lhs, scope_stack, scope_map);
                 walk_expr(cx, &**rhs, scope_stack, scope_map);
             }
 
-            ast::ExprSlice(ref base, ref start, ref end, _) => {
-                walk_expr(cx, &**base, scope_stack, scope_map);
-                start.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map));
-                end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map));
-            }
-
             ast::ExprRange(ref start, ref end) => {
-                walk_expr(cx, &**start, scope_stack, scope_map);
+                start.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
                 end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
             }
 
@@ -3816,8 +3824,8 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             output.push(']');
         },
         ty::ty_trait(ref trait_data) => {
-            push_item_name(cx, trait_data.principal.def_id(), false, output);
-            push_type_params(cx, trait_data.principal.substs(), output);
+            push_item_name(cx, trait_data.principal_def_id(), false, output);
+            push_type_params(cx, trait_data.principal.0.substs, output);
         },
         ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
             if unsafety == ast::Unsafety::Unsafe {
@@ -3925,9 +3933,10 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::ty_unboxed_closure(..) => {
             output.push_str("closure");
         }
-        ty::ty_err      |
+        ty::ty_err |
         ty::ty_infer(_) |
         ty::ty_open(_) |
+        ty::ty_projection(..) |
         ty::ty_param(_) => {
             cx.sess().bug(format!("debuginfo: Trying to create type name for \
                 unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))[]);
@@ -4109,3 +4118,76 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
         }
     })
 }
+
+
+//=-----------------------------------------------------------------------------
+// .debug_gdb_scripts binary section
+//=-----------------------------------------------------------------------------
+
+/// Inserts a side-effect free instruction sequence that makes sure that the
+/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
+pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
+    if needs_gdb_debug_scripts_section(ccx) {
+        let empty = b"".to_c_str();
+        let gdb_debug_scripts_section_global =
+            get_or_insert_gdb_debug_scripts_section_global(ccx);
+        unsafe {
+            let volative_load_instruction =
+                llvm::LLVMBuildLoad(ccx.raw_builder(),
+                                    gdb_debug_scripts_section_global,
+                                    empty.as_ptr());
+            llvm::LLVMSetVolatile(volative_load_instruction, llvm::True);
+        }
+    }
+}
+
+/// Allocates the global variable responsible for the .debug_gdb_scripts binary
+/// section.
+fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
+                                                  -> llvm::ValueRef {
+    let section_var_name = b"__rustc_debug_gdb_scripts_section__".to_c_str();
+
+    let section_var = unsafe {
+        llvm::LLVMGetNamedGlobal(ccx.llmod(), section_var_name.as_ptr())
+    };
+
+    if section_var == ptr::null_mut() {
+        let section_name = b".debug_gdb_scripts".to_c_str();
+        let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
+
+        unsafe {
+            let llvm_type = Type::array(&Type::i8(ccx),
+                                        section_contents.len() as u64);
+            let section_var = llvm::LLVMAddGlobal(ccx.llmod(),
+                                                  llvm_type.to_ref(),
+                                                  section_var_name.as_ptr());
+            llvm::LLVMSetSection(section_var, section_name.as_ptr());
+            llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
+            llvm::LLVMSetGlobalConstant(section_var, llvm::True);
+            llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
+            llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
+            // This should make sure that the whole section is not larger than
+            // the string it contains. Otherwise we get a warning from GDB.
+            llvm::LLVMSetAlignment(section_var, 1);
+            section_var
+        }
+    } else {
+        section_var
+    }
+}
+
+fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool {
+    let omit_gdb_pretty_printer_section =
+        attr::contains_name(ccx.tcx()
+                               .map
+                               .krate()
+                               .attrs
+                               .as_slice(),
+                            "omit_gdb_pretty_printer_section");
+
+    !omit_gdb_pretty_printer_section &&
+    !ccx.sess().target.target.options.is_like_osx &&
+    !ccx.sess().target.target.options.is_like_windows &&
+    ccx.sess().opts.debuginfo != NoDebugInfo
+}
+
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 60b5a08c7c5..cf3070919cb 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -39,7 +39,7 @@ use back::abi;
 use llvm::{mod, ValueRef};
 use middle::def;
 use middle::mem_categorization::Typer;
-use middle::subst::{mod, Subst, Substs};
+use middle::subst::{mod, Substs};
 use trans::{_match, adt, asm, base, callee, closure, consts, controlflow};
 use trans::base::*;
 use trans::build::*;
@@ -68,6 +68,7 @@ use syntax::print::pprust::{expr_to_string};
 use syntax::ptr::P;
 use syntax::parse::token;
 use std::rc::Rc;
+use std::iter::repeat;
 
 // Destinations
 
@@ -280,7 +281,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                expr.repr(bcx.tcx()),
                datum.to_string(bcx.ccx()));
 
-        if !ty::type_is_sized(bcx.tcx(), datum.ty) {
+        if !type_is_sized(bcx.tcx(), datum.ty) {
             debug!("Taking address of unsized type {}",
                    bcx.ty_to_string(datum.ty));
             ref_fat_ptr(bcx, expr, datum)
@@ -298,12 +299,16 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // into a type to be destructed. If we want to end up with a Box pointer,
     // then mk_ty should make a Box pointer (T -> Box<T>), if we want a
     // borrowed reference then it should be T -> &T.
-    // FIXME(#19596) unbox `mk_ty`
-    fn unsized_info<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                kind: &ty::UnsizeKind<'tcx>,
-                                id: ast::NodeId,
-                                unadjusted_ty: Ty<'tcx>,
-                                mk_ty: |Ty<'tcx>| -> Ty<'tcx>) -> ValueRef {
+    fn unsized_info<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
+                                   kind: &ty::UnsizeKind<'tcx>,
+                                   id: ast::NodeId,
+                                   unadjusted_ty: Ty<'tcx>,
+                                   mk_ty: F) -> ValueRef where
+        F: FnOnce(Ty<'tcx>) -> Ty<'tcx>,
+    {
+        // FIXME(#19596) workaround: `|t| t` causes monomorphization recursion
+        fn identity<T>(t: T) -> T { t }
+
         debug!("unsized_info(kind={}, id={}, unadjusted_ty={})",
                kind, id, unadjusted_ty.repr(bcx.tcx()));
         match kind {
@@ -313,17 +318,19 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     let ty_substs = substs.types.get_slice(subst::TypeSpace);
                     // The dtor for a field treats it like a value, so mk_ty
                     // should just be the identity function.
-                    unsized_info(bcx, k, id, ty_substs[tp_index], |t| t)
+                    unsized_info(bcx, k, id, ty_substs[tp_index], identity)
                 }
                 _ => bcx.sess().bug(format!("UnsizeStruct with bad sty: {}",
                                           bcx.ty_to_string(unadjusted_ty))[])
             },
             &ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => {
-                let substs = principal.substs().with_self_ty(unadjusted_ty).erase_regions();
+                // Note that we preserve binding levels here:
+                let substs = principal.0.substs.with_self_ty(unadjusted_ty).erase_regions();
+                let substs = bcx.tcx().mk_substs(substs);
                 let trait_ref =
-                    Rc::new(ty::Binder(ty::TraitRef { def_id: principal.def_id(),
-                                                      substs: bcx.tcx().mk_substs(substs) }));
-                let trait_ref = trait_ref.subst(bcx.tcx(), bcx.fcx.param_substs);
+                    ty::Binder(Rc::new(ty::TraitRef { def_id: principal.def_id(),
+                                                      substs: substs }));
+                let trait_ref = bcx.monomorphize(&trait_ref);
                 let box_ty = mk_ty(unadjusted_ty);
                 PointerCast(bcx,
                             meth::get_vtable(bcx, box_ty, trait_ref),
@@ -585,36 +592,40 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             trans_rec_tup_field(bcx, &**base, idx.node)
         }
         ast::ExprIndex(ref base, ref idx) => {
-            trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
-        }
-        ast::ExprSlice(ref base, ref start, ref end, _) => {
-            let _icx = push_ctxt("trans_slice");
-            let ccx = bcx.ccx();
-
-            let method_call = MethodCall::expr(expr.id);
-            let method_ty = ccx.tcx()
-                               .method_map
-                               .borrow()
-                               .get(&method_call)
-                               .map(|method| method.ty);
-            let base_datum = unpack_datum!(bcx, trans(bcx, &**base));
-
-            let mut args = vec![];
-            start.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
-            end.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
-
-            let result_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty.unwrap())).unwrap();
-            let scratch = rvalue_scratch_datum(bcx, result_ty, "trans_slice");
-
-            unpack_result!(bcx,
-                           trans_overloaded_op(bcx,
-                                               expr,
-                                               method_call,
-                                               base_datum,
-                                               args,
-                                               Some(SaveIn(scratch.val)),
-                                               true));
-            DatumBlock::new(bcx, scratch.to_expr_datum())
+            match idx.node {
+                ast::ExprRange(ref start, ref end) => {
+                    // Special case for slicing syntax (KILLME).
+                    let _icx = push_ctxt("trans_slice");
+                    let ccx = bcx.ccx();
+
+                    let method_call = MethodCall::expr(expr.id);
+                    let method_ty = ccx.tcx()
+                                       .method_map
+                                       .borrow()
+                                       .get(&method_call)
+                                       .map(|method| method.ty);
+                    let base_datum = unpack_datum!(bcx, trans(bcx, &**base));
+
+                    let mut args = vec![];
+                    start.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
+                    end.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
+
+                    let result_ty = ty::ty_fn_ret(monomorphize_type(bcx,
+                                                                    method_ty.unwrap())).unwrap();
+                    let scratch = rvalue_scratch_datum(bcx, result_ty, "trans_slice");
+
+                    unpack_result!(bcx,
+                                   trans_overloaded_op(bcx,
+                                                       expr,
+                                                       method_call,
+                                                       base_datum,
+                                                       args,
+                                                       Some(SaveIn(scratch.val)),
+                                                       true));
+                    DatumBlock::new(bcx, scratch.to_expr_datum())
+                }
+                _ => trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
+            }
         }
         ast::ExprBox(_, ref contents) => {
             // Special case for `Box<T>`
@@ -689,7 +700,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             field_tys[ix].mt.ty,
             |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix));
 
-        if ty::type_is_sized(bcx.tcx(), d.ty) {
+        if type_is_sized(bcx.tcx(), d.ty) {
             DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
         } else {
             let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), "");
@@ -769,7 +780,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                Some(SaveIn(scratch.val)),
                                                true));
             let datum = scratch.to_expr_datum();
-            if ty::type_is_sized(bcx.tcx(), elt_ty) {
+            if type_is_sized(bcx.tcx(), elt_ty) {
                 Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
             } else {
                 Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr)
@@ -972,7 +983,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
             let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign"));
 
-            if ty::type_needs_drop(bcx.tcx(), dst_datum.ty) {
+            if type_needs_drop(bcx.tcx(), dst_datum.ty) {
                 // If there are destructors involved, make sure we
                 // are copying from an rvalue, since that cannot possible
                 // alias an lvalue. We are concerned about code like:
@@ -1064,22 +1075,34 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
 
             // A range just desugars into a struct.
-            let (did, fields) = match end {
-                &Some(ref end) => {
+            // Note that the type of the start and end may not be the same, but
+            // they should only differ in their lifetime, which should not matter
+            // in trans.
+            let (did, fields, ty_params) = match (start, end) {
+                (&Some(ref start), &Some(ref end)) => {
                     // Desugar to Range
-                    let fields = vec!(make_field("start", start.clone()),
-                                      make_field("end", end.clone()));
-                    (tcx.lang_items.range_struct(), fields)
+                    let fields = vec![make_field("start", start.clone()),
+                                      make_field("end", end.clone())];
+                    (tcx.lang_items.range_struct(), fields, vec![node_id_type(bcx, start.id)])
                 }
-                &None => {
+                (&Some(ref start), &None) => {
                     // Desugar to RangeFrom
-                    let fields = vec!(make_field("start", start.clone()));
-                    (tcx.lang_items.range_from_struct(), fields)
+                    let fields = vec![make_field("start", start.clone())];
+                    (tcx.lang_items.range_from_struct(), fields, vec![node_id_type(bcx, start.id)])
+                }
+                (&None, &Some(ref end)) => {
+                    // Desugar to RangeTo
+                    let fields = vec![make_field("end", end.clone())];
+                    (tcx.lang_items.range_to_struct(), fields, vec![node_id_type(bcx, end.id)])
+                }
+                _ => {
+                    // Desugar to FullRange
+                    (tcx.lang_items.full_range_struct(), vec![], vec![])
                 }
             };
 
             if let Some(did) = did {
-                let substs = Substs::new_type(vec![node_id_type(bcx, start.id)], vec![]);
+                let substs = Substs::new_type(ty_params, vec![]);
                 trans_struct(bcx,
                              fields.as_slice(),
                              None,
@@ -1188,7 +1211,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                              .get(&expr.id)
                                              .map(|t| (*t).clone())
                                              .unwrap();
-                let trait_ref = trait_ref.subst(bcx.tcx(), bcx.fcx.param_substs);
+                let trait_ref = bcx.monomorphize(&trait_ref);
                 let datum = unpack_datum!(bcx, trans(bcx, &**val));
                 meth::trans_trait_cast(bcx, datum, expr.id,
                                        trait_ref, dest)
@@ -1395,7 +1418,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let tcx = bcx.tcx();
     with_field_tys(tcx, ty, Some(expr_id), |discr, field_tys| {
-        let mut need_base = Vec::from_elem(field_tys.len(), true);
+        let mut need_base: Vec<_> = repeat(true).take(field_tys.len()).collect();
 
         let numbered_fields = fields.iter().map(|field| {
             let opt_pos =
@@ -1497,7 +1520,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         assert_eq!(discr, 0);
 
         match ty::expr_kind(bcx.tcx(), &*base.expr) {
-            ty::RvalueDpsExpr | ty::RvalueDatumExpr if !ty::type_needs_drop(bcx.tcx(), ty) => {
+            ty::RvalueDpsExpr | ty::RvalueDatumExpr if !type_needs_drop(bcx.tcx(), ty) => {
                 bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
             },
             ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"),
@@ -1506,7 +1529,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 for &(i, t) in base.fields.iter() {
                     let datum = base_datum.get_element(
                             bcx, t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i));
-                    assert!(ty::type_is_sized(bcx.tcx(), datum.ty));
+                    assert!(type_is_sized(bcx.tcx(), datum.ty));
                     let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i);
                     bcx = datum.store_to(bcx, dest);
                 }
@@ -1634,7 +1657,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                -> DatumBlock<'blk, 'tcx, Expr> {
     let _icx = push_ctxt("trans_uniq_expr");
     let fcx = bcx.fcx;
-    assert!(ty::type_is_sized(bcx.tcx(), contents_ty));
+    assert!(type_is_sized(bcx.tcx(), contents_ty));
     let llty = type_of::type_of(bcx.ccx(), contents_ty);
     let size = llsize_of(bcx.ccx(), llty);
     let align = C_uint(bcx.ccx(), type_of::align_of(bcx.ccx(), contents_ty));
@@ -1969,7 +1992,7 @@ pub fn cast_type_kind<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> cast_kind {
         ty::ty_char        => cast_integral,
         ty::ty_float(..)   => cast_float,
         ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => {
-            if ty::type_is_sized(tcx, mt.ty) {
+            if type_is_sized(tcx, mt.ty) {
                 cast_pointer
             } else {
                 cast_other
@@ -2101,7 +2124,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     // Evaluate LHS (destination), which should be an lvalue
     let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
-    assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty));
+    assert!(!type_needs_drop(bcx.tcx(), dst_datum.ty));
     let dst_ty = dst_datum.ty;
     let dst = load_ty(bcx, dst_datum.val, dst_datum.ty);
 
@@ -2201,7 +2224,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let r = match datum.ty.sty {
         ty::ty_uniq(content_ty) => {
-            if ty::type_is_sized(bcx.tcx(), content_ty) {
+            if type_is_sized(bcx.tcx(), content_ty) {
                 deref_owned_pointer(bcx, expr, datum, content_ty)
             } else {
                 // A fat pointer and an opened DST value have the same
@@ -2220,7 +2243,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
         ty::ty_ptr(ty::mt { ty: content_ty, .. }) |
         ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => {
-            if ty::type_is_sized(bcx.tcx(), content_ty) {
+            if type_is_sized(bcx.tcx(), content_ty) {
                 let ptr = datum.to_llscalarish(bcx);
 
                 // Always generate an lvalue datum, even if datum.mode is
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index f94e1af3149..99dc971ed94 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -19,11 +19,12 @@ use trans::build::*;
 use trans::cabi;
 use trans::common::*;
 use trans::machine;
+use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of::*;
 use trans::type_of;
 use middle::ty::{mod, Ty};
-use middle::subst::{Subst, Substs};
+use middle::subst::{Substs};
 use std::cmp;
 use std::c_str::ToCStr;
 use libc::c_uint;
@@ -526,7 +527,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let _icx = push_ctxt("foreign::build_foreign_fn");
 
     let fnty = ty::node_id_to_type(ccx.tcx(), id);
-    let mty = fnty.subst(ccx.tcx(), param_substs);
+    let mty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fnty);
     let tys = foreign_types_for_fn_ty(ccx, mty);
 
     unsafe { // unsafe because we call LLVM operations
@@ -544,10 +545,12 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                attrs: &[ast::Attribute],
                                id: ast::NodeId,
                                hash: Option<&str>)
-                               -> ValueRef {
+                               -> ValueRef
+    {
         let _icx = push_ctxt("foreign::foreign::build_rust_fn");
         let tcx = ccx.tcx();
-        let t = ty::node_id_to_type(tcx, id).subst(ccx.tcx(), param_substs);
+        let t = ty::node_id_to_type(tcx, id);
+        let t = monomorphize::apply_param_substs(tcx, param_substs, &t);
 
         let ps = ccx.tcx().map.with_path(id, |path| {
             let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
@@ -613,7 +616,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // Array for the arguments we will pass to the rust function.
         let mut llrust_args = Vec::new();
         let mut next_foreign_arg_counter: c_uint = 0;
-        let next_foreign_arg: |pad: bool| -> c_uint = |pad: bool| {
+        let mut next_foreign_arg = |&mut : pad: bool| -> c_uint {
             next_foreign_arg_counter += if pad {
                 2
             } else {
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index e276543264b..ab5c670ef5a 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -63,7 +63,7 @@ pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef,
 
 pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef,
                                           content_ty: Ty<'tcx>) -> Block<'blk, 'tcx> {
-    assert!(ty::type_is_sized(bcx.ccx().tcx(), content_ty));
+    assert!(type_is_sized(bcx.ccx().tcx(), content_ty));
     let sizing_type = sizing_type_of(bcx.ccx(), content_ty);
     let content_size = llsize_of_alloc(bcx.ccx(), sizing_type);
 
@@ -81,19 +81,19 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let tcx = ccx.tcx();
     // Even if there is no dtor for t, there might be one deeper down and we
     // might need to pass in the vtable ptr.
-    if !ty::type_is_sized(tcx, t) {
+    if !type_is_sized(tcx, t) {
         return t
     }
-    if !ty::type_needs_drop(tcx, t) {
-        return ty::mk_i8();
+    if !type_needs_drop(tcx, t) {
+        return tcx.types.i8;
     }
     match t.sty {
-        ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ)
-                         && ty::type_is_sized(tcx, typ) => {
+        ty::ty_uniq(typ) if !type_needs_drop(tcx, typ)
+                         && type_is_sized(tcx, typ) => {
             let llty = sizing_type_of(ccx, typ);
             // `Box<ZeroSizeType>` does not allocate.
             if llsize_of_alloc(ccx, llty) == 0 {
-                ty::mk_i8()
+                tcx.types.i8
             } else {
                 t
             }
@@ -110,7 +110,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // NB: v is an *alias* of type t here, not a direct value.
     debug!("drop_ty(t={})", t.repr(bcx.tcx()));
     let _icx = push_ctxt("drop_ty");
-    if ty::type_needs_drop(bcx.tcx(), t) {
+    if type_needs_drop(bcx.tcx(), t) {
         let ccx = bcx.ccx();
         let glue = get_drop_glue(ccx, t);
         let glue_type = get_drop_glue_type(ccx, t);
@@ -150,7 +150,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val
         _ => { }
     }
 
-    let llty = if ty::type_is_sized(ccx.tcx(), t) {
+    let llty = if type_is_sized(ccx.tcx(), t) {
         type_of(ccx, t).ptr_to()
     } else {
         type_of(ccx, ty::mk_uniq(ccx.tcx(), t)).ptr_to()
@@ -193,14 +193,14 @@ fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                       substs: &subst::Substs<'tcx>)
                                       -> Block<'blk, 'tcx> {
     let repr = adt::represent_type(bcx.ccx(), t);
-    let struct_data = if ty::type_is_sized(bcx.tcx(), t) {
+    let struct_data = if type_is_sized(bcx.tcx(), t) {
         v0
     } else {
         let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
         Load(bcx, llval)
     };
     let drop_flag = unpack_datum!(bcx, adt::trans_drop_flag_ptr(bcx, &*repr, struct_data));
-    with_cond(bcx, load_ty(bcx, drop_flag.val, ty::mk_bool()), |cx| {
+    with_cond(bcx, load_ty(bcx, drop_flag.val, bcx.tcx().types.bool), |cx| {
         trans_struct_drop(cx, t, v0, dtor_did, class_did, substs)
     })
 }
@@ -234,7 +234,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     bcx.ty_to_string(fty))[])
     };
 
-    let (struct_data, info) = if ty::type_is_sized(bcx.tcx(), t) {
+    let (struct_data, info) = if type_is_sized(bcx.tcx(), t) {
         (v0, None)
     } else {
         let data = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
@@ -251,7 +251,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // Class dtors have no explicit args, so the params should
         // just consist of the environment (self).
         assert_eq!(params.len(), 1);
-        let self_arg = if ty::type_is_fat_ptr(bcx.tcx(), self_ty) {
+        let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
             // The dtor expects a fat pointer, so make one, even if we have to fake it.
             let boxed_ty = ty::mk_open(bcx.tcx(), t);
             let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self");
@@ -275,7 +275,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         for (i, ty) in st.fields.iter().enumerate().rev() {
             let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
 
-            let val = if ty::type_is_sized(bcx.tcx(), *ty) {
+            let val = if type_is_sized(bcx.tcx(), *ty) {
                 llfld_a
             } else {
                 let boxed_ty = ty::mk_open(bcx.tcx(), *ty);
@@ -292,7 +292,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                      class_did,
                                      &[get_drop_glue_type(bcx.ccx(), t)],
                                      ty::mk_nil(bcx.tcx()));
-        let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None, false);
+        let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None);
 
         variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope);
         variant_cx
@@ -303,7 +303,7 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info:
                                      -> (ValueRef, ValueRef) {
     debug!("calculate size of DST: {}; with lost info: {}",
            bcx.ty_to_string(t), bcx.val_to_string(info));
-    if ty::type_is_sized(bcx.tcx(), t) {
+    if type_is_sized(bcx.tcx(), t) {
         let sizing_type = sizing_type_of(bcx.ccx(), t);
         let size = C_uint(bcx.ccx(), llsize_of_alloc(bcx.ccx(), sizing_type));
         let align = C_uint(bcx.ccx(), align_of(bcx.ccx(), t));
@@ -383,7 +383,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
                         bcx
                     })
                 }
-                ty::ty_struct(..) if !ty::type_is_sized(bcx.tcx(), content_ty) => {
+                ty::ty_struct(..) if !type_is_sized(bcx.tcx(), content_ty) => {
                     let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
                     let llbox = Load(bcx, llval);
                     let not_null = IsNotNull(bcx, llbox);
@@ -396,7 +396,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
                     })
                 }
                 _ => {
-                    assert!(ty::type_is_sized(bcx.tcx(), content_ty));
+                    assert!(type_is_sized(bcx.tcx(), content_ty));
                     let llval = v0;
                     let llbox = Load(bcx, llval);
                     let not_null = IsNotNull(bcx, llbox);
@@ -415,7 +415,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
                     // find the drop flag (which is at the end of the struct).
                     // Lets just ignore the flag and pretend everything will be
                     // OK.
-                    if ty::type_is_sized(bcx.tcx(), t) {
+                    if type_is_sized(bcx.tcx(), t) {
                         trans_struct_drop_flag(bcx, t, v0, dtor, did, substs)
                     } else {
                         // Give the user a heads up that we are doing something
@@ -468,8 +468,8 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
         }
         ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false),
         _ => {
-            assert!(ty::type_is_sized(bcx.tcx(), t));
-            if ty::type_needs_drop(bcx.tcx(), t) &&
+            assert!(type_is_sized(bcx.tcx(), t));
+            if type_needs_drop(bcx.tcx(), t) &&
                 ty::type_is_structural(t) {
                 iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None))
             } else {
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index fff89999d99..a22ce297828 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -32,7 +32,7 @@ use middle::ty::{mod, Ty};
 use syntax::abi::RustIntrinsic;
 use syntax::ast;
 use syntax::parse::token;
-use util::ppaux::ty_to_string;
+use util::ppaux::{Repr, ty_to_string};
 
 pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
     let name = match token::get_ident(item.ident).get() {
@@ -90,46 +90,53 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti
 /// Performs late verification that intrinsics are used correctly. At present,
 /// the only intrinsic that needs such verification is `transmute`.
 pub fn check_intrinsics(ccx: &CrateContext) {
-    for transmute_restriction in ccx.tcx()
-                                    .transmute_restrictions
-                                    .borrow()
-                                    .iter() {
+    let mut last_failing_id = None;
+    for transmute_restriction in ccx.tcx().transmute_restrictions.borrow().iter() {
+        // Sometimes, a single call to transmute will push multiple
+        // type pairs to test in order to exhaustively test the
+        // possibility around a type parameter. If one of those fails,
+        // there is no sense reporting errors on the others.
+        if last_failing_id == Some(transmute_restriction.id) {
+            continue;
+        }
+
+        debug!("transmute_restriction: {}", transmute_restriction.repr(ccx.tcx()));
+
+        assert!(!ty::type_has_params(transmute_restriction.substituted_from));
+        assert!(!ty::type_has_params(transmute_restriction.substituted_to));
+
         let llfromtype = type_of::sizing_type_of(ccx,
-                                                 transmute_restriction.from);
+                                                 transmute_restriction.substituted_from);
         let lltotype = type_of::sizing_type_of(ccx,
-                                               transmute_restriction.to);
+                                               transmute_restriction.substituted_to);
         let from_type_size = machine::llbitsize_of_real(ccx, llfromtype);
         let to_type_size = machine::llbitsize_of_real(ccx, lltotype);
         if from_type_size != to_type_size {
-            ccx.sess()
-               .span_err(transmute_restriction.span,
-                format!("transmute called on types with different sizes: \
-                         {} ({} bit{}) to {} ({} bit{})",
-                        ty_to_string(ccx.tcx(), transmute_restriction.from),
-                        from_type_size as uint,
-                        if from_type_size == 1 {
-                            ""
-                        } else {
-                            "s"
-                        },
-                        ty_to_string(ccx.tcx(), transmute_restriction.to),
-                        to_type_size as uint,
-                        if to_type_size == 1 {
-                            ""
-                        } else {
-                            "s"
-                        })[]);
-        }
-        if ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) ||
-           ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) {
-            ccx.sess()
-               .add_lint(::lint::builtin::FAT_PTR_TRANSMUTES,
-                         transmute_restriction.id,
-                         transmute_restriction.span,
-                         format!("Transmuting fat pointer types; {} to {}.\
-                                  Beware of relying on the compiler's representation",
-                                 ty_to_string(ccx.tcx(), transmute_restriction.from),
-                                 ty_to_string(ccx.tcx(), transmute_restriction.to)));
+            last_failing_id = Some(transmute_restriction.id);
+
+            if transmute_restriction.original_from != transmute_restriction.substituted_from {
+                ccx.sess().span_err(
+                    transmute_restriction.span,
+                    format!("transmute called on types with potentially different sizes: \
+                             {} (could be {} bit{}) to {} (could be {} bit{})",
+                            ty_to_string(ccx.tcx(), transmute_restriction.original_from),
+                            from_type_size as uint,
+                            if from_type_size == 1 {""} else {"s"},
+                            ty_to_string(ccx.tcx(), transmute_restriction.original_to),
+                            to_type_size as uint,
+                            if to_type_size == 1 {""} else {"s"}).as_slice());
+            } else {
+                ccx.sess().span_err(
+                    transmute_restriction.span,
+                    format!("transmute called on types with different sizes: \
+                             {} ({} bit{}) to {} ({} bit{})",
+                            ty_to_string(ccx.tcx(), transmute_restriction.original_from),
+                            from_type_size as uint,
+                            if from_type_size == 1 {""} else {"s"},
+                            ty_to_string(ccx.tcx(), transmute_restriction.original_to),
+                            to_type_size as uint,
+                            if to_type_size == 1 {""} else {"s"}).as_slice());
+            }
         }
     }
     ccx.sess().abort_if_errors();
@@ -174,7 +181,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 // This should be caught by the intrinsicck pass
                 assert_eq!(in_type_size, out_type_size);
 
-                let nonpointer_nonaggregate = |llkind: TypeKind| -> bool {
+                let nonpointer_nonaggregate = |&: llkind: TypeKind| -> bool {
                     use llvm::TypeKind::*;
                     match llkind {
                         Half | Float | Double | X86_FP80 | FP128 |
@@ -365,7 +372,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         }
         (_, "needs_drop") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
-            C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty))
+            C_bool(ccx, type_needs_drop(ccx.tcx(), tp_ty))
         }
         (_, "owns_managed") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 553613a8eac..9535ffaec0e 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -13,7 +13,7 @@ use back::abi;
 use llvm;
 use llvm::ValueRef;
 use metadata::csearch;
-use middle::subst::{Subst,Substs};
+use middle::subst::{Substs};
 use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
@@ -132,8 +132,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             ref trait_ref,
             method_num
         }) => {
-            let trait_ref =
-                Rc::new(ty::Binder((**trait_ref).subst(bcx.tcx(), bcx.fcx.param_substs)));
+            let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
             let span = bcx.tcx().map.span(method_call.expr_id);
             debug!("method_call={} trait_ref={}",
                    method_call,
@@ -142,8 +141,11 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                             span,
                                             trait_ref.clone());
             debug!("origin = {}", origin.repr(bcx.tcx()));
-            trans_monomorphized_callee(bcx, method_call, trait_ref.def_id(),
-                                       method_num, origin)
+            trans_monomorphized_callee(bcx,
+                                       method_call,
+                                       trait_ref.def_id(),
+                                       method_num,
+                                       origin)
         }
 
         ty::MethodTraitObject(ref mt) => {
@@ -207,7 +209,6 @@ pub fn trans_static_method_callee(bcx: Block,
     let subst::SeparateVecsPerParamSpace {
         types: rcvr_type,
         selfs: rcvr_self,
-        assocs: rcvr_assoc,
         fns: rcvr_method
     } = rcvr_substs.types.split();
 
@@ -236,11 +237,11 @@ pub fn trans_static_method_callee(bcx: Block,
     let trait_substs =
         Substs::erased(VecPerParamSpace::new(rcvr_type,
                                              rcvr_self,
-                                             rcvr_assoc,
                                              Vec::new()));
+    let trait_substs = bcx.tcx().mk_substs(trait_substs);
     debug!("trait_substs={}", trait_substs.repr(bcx.tcx()));
-    let trait_ref = Rc::new(ty::Binder(ty::TraitRef { def_id: trait_id,
-                                                      substs: bcx.tcx().mk_substs(trait_substs) }));
+    let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: trait_id,
+                                                      substs: trait_substs }));
     let vtbl = fulfill_obligation(bcx.ccx(),
                                   DUMMY_SP,
                                   trait_ref);
@@ -273,13 +274,11 @@ pub fn trans_static_method_callee(bcx: Block,
             let subst::SeparateVecsPerParamSpace {
                 types: impl_type,
                 selfs: impl_self,
-                assocs: impl_assoc,
                 fns: _
             } = impl_substs.types.split();
             let callee_substs =
                 Substs::erased(VecPerParamSpace::new(impl_type,
                                                      impl_self,
-                                                     impl_assoc,
                                                      rcvr_method));
 
             let mth_id = method_with_name(ccx, impl_did, mname);
@@ -408,13 +407,12 @@ fn combine_impl_and_methods_tps<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let subst::SeparateVecsPerParamSpace {
         types: rcvr_type,
         selfs: rcvr_self,
-        assocs: rcvr_assoc,
         fns: rcvr_method
     } = rcvr_substs.types.clone().split();
     assert!(rcvr_method.is_empty());
     subst::Substs {
         regions: subst::ErasedRegions,
-        types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, rcvr_assoc, node_method)
+        types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method)
     }
 }
 
@@ -436,7 +434,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let self_datum = unpack_datum!(
         bcx, expr::trans(bcx, self_expr));
 
-    let llval = if ty::type_needs_drop(bcx.tcx(), self_datum.ty) {
+    let llval = if type_needs_drop(bcx.tcx(), self_datum.ty) {
         let self_datum = unpack_datum!(
             bcx, self_datum.to_rvalue_datum(bcx, "trait_callee"));
 
@@ -515,7 +513,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// This will hopefully change now that DST is underway.
 pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                               box_ty: Ty<'tcx>,
-                              trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
+                              trait_ref: ty::PolyTraitRef<'tcx>)
                               -> ValueRef
 {
     debug!("get_vtable(box_ty={}, trait_ref={})",
@@ -562,7 +560,7 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let llfn = vec![trans_fn_pointer_shim(bcx.ccx(), bare_fn_ty)];
                 llfn.into_iter()
             }
-            traits::VtableParam(..) => {
+            traits::VtableParam => {
                 bcx.sess().bug(
                     format!("resolved vtable for {} to bad vtable {} in trans",
                             trait_ref.repr(bcx.tcx()),
@@ -671,7 +669,7 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     datum: Datum<'tcx, Expr>,
                                     id: ast::NodeId,
-                                    trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+                                    trait_ref: ty::PolyTraitRef<'tcx>,
                                     dest: expr::Dest)
                                     -> Block<'blk, 'tcx> {
     let mut bcx = bcx;
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 2a6aff56513..7c8ba08d987 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -12,15 +12,18 @@ use back::link::exported_name;
 use session;
 use llvm::ValueRef;
 use llvm;
+use middle::infer;
 use middle::subst;
-use middle::subst::Subst;
+use middle::subst::{Subst, Substs};
+use middle::traits;
+use middle::ty_fold::{TypeFolder, TypeFoldable};
 use trans::base::{set_llvm_fn_attrs, set_inline_hint};
 use trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use trans::base::{trans_fn, decl_internal_rust_fn};
 use trans::base;
 use trans::common::*;
 use trans::foreign;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, HasProjectionTypes, Ty};
 use util::ppaux::Repr;
 
 use syntax::abi;
@@ -28,6 +31,7 @@ use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::{local_def, PostExpansionMethod};
 use syntax::attr;
+use syntax::codemap::DUMMY_SP;
 use std::hash::{sip, Hash};
 
 pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -92,7 +96,12 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 
     debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
+
     let mono_ty = llitem_ty.subst(ccx.tcx(), psubsts);
+    debug!("mono_ty = {} (post-substitution)", mono_ty.repr(ccx.tcx()));
+
+    let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty);
+    debug!("mono_ty = {} (post-normalization)", mono_ty.repr(ccx.tcx()));
 
     ccx.stats().n_monos.set(ccx.stats().n_monos.get() + 1);
 
@@ -130,7 +139,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     // This shouldn't need to option dance.
     let mut hash_id = Some(hash_id);
-    let mk_lldecl = |abi: abi::Abi| {
+    let mut mk_lldecl = |&mut : abi: abi::Abi| {
         let lldecl = if abi != abi::Rust {
             foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, s[])
         } else {
@@ -140,7 +149,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ccx.monomorphized().borrow_mut().insert(hash_id.take().unwrap(), lldecl);
         lldecl
     };
-    let setup_lldecl = |lldecl, attrs: &[ast::Attribute]| {
+    let setup_lldecl = |&: lldecl, attrs: &[ast::Attribute]| {
         base::update_linkage(ccx, lldecl, None, base::OriginalTranslation);
         set_llvm_fn_attrs(ccx, attrs, lldecl);
 
@@ -282,3 +291,53 @@ pub struct MonoId<'tcx> {
     pub def: ast::DefId,
     pub params: subst::VecPerParamSpace<Ty<'tcx>>
 }
+
+/// Monomorphizes a type from the AST by first applying the in-scope
+/// substitutions and then normalizing any associated types.
+pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
+                                  param_substs: &Substs<'tcx>,
+                                  value: &T)
+                                  -> T
+    where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+{
+    assert!(param_substs.regions.is_erased());
+
+    let substituted = value.subst(tcx, param_substs);
+    normalize_associated_type(tcx, &substituted)
+}
+
+/// Removes associated types, if any. Since this during
+/// monomorphization, we know that only concrete types are involved,
+/// and hence we can be sure that all associated types will be
+/// completely normalized away.
+pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
+    where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+{
+    debug!("normalize_associated_type(t={})", value.repr(tcx));
+
+    if !value.has_projection_types() {
+        return value.clone();
+    }
+
+    // FIXME(#20304) -- cache
+
+    let infcx = infer::new_infer_ctxt(tcx);
+    let param_env = ty::empty_parameter_environment();
+    let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
+    let mut selcx = traits::SelectionContext::new(&infcx, &param_env, &typer);
+    let cause = traits::ObligationCause::dummy();
+    let traits::Normalized { value: result, obligations } =
+        traits::normalize(&mut selcx, cause, value);
+
+    debug!("normalize_associated_type: result={} obligations={}",
+           result.repr(tcx),
+           obligations.repr(tcx));
+
+    let mut fulfill_cx = traits::FulfillmentContext::new();
+    for obligation in obligations.into_iter() {
+        fulfill_cx.register_predicate_obligation(&infcx, obligation);
+    }
+    let result = drain_fulfillment_cx(DUMMY_SP, &infcx, &param_env, &mut fulfill_cx, &result);
+
+    result
+}
diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs
index e09032ac2d0..688a0d07250 100644
--- a/src/librustc_trans/trans/tvec.rs
+++ b/src/librustc_trans/trans/tvec.rs
@@ -62,7 +62,7 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
 
         let dataptr = get_dataptr(bcx, vptr);
-        let bcx = if ty::type_needs_drop(tcx, unit_ty) {
+        let bcx = if type_needs_drop(tcx, unit_ty) {
             let len = get_len(bcx, vptr);
             iter_vec_raw(bcx, dataptr, unit_ty, len, |bb, vv, tt| glue::drop_ty(bb, vv, tt, None))
         } else {
diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs
index 45a2a343066..2cc40a61795 100644
--- a/src/librustc_trans/trans/type_.rs
+++ b/src/librustc_trans/trans/type_.rs
@@ -22,6 +22,7 @@ use syntax::ast;
 use std::c_str::ToCStr;
 use std::mem;
 use std::cell::RefCell;
+use std::iter::repeat;
 
 use libc::c_uint;
 
@@ -282,7 +283,7 @@ impl Type {
             if n_elts == 0 {
                 return Vec::new();
             }
-            let mut elts = Vec::from_elem(n_elts, Type { rf: 0 as TypeRef });
+            let mut elts: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_elts).collect();
             llvm::LLVMGetStructElementTypes(self.to_ref(),
                                             elts.as_mut_ptr() as *mut TypeRef);
             elts
@@ -296,7 +297,7 @@ impl Type {
     pub fn func_params(&self) -> Vec<Type> {
         unsafe {
             let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint;
-            let mut args = Vec::from_elem(n_args, Type { rf: 0 as TypeRef });
+            let mut args: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_args).collect();
             llvm::LLVMGetParamTypes(self.to_ref(),
                                     args.as_mut_ptr() as *mut TypeRef);
             args
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 499195b51b9..0bc35390cd7 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -187,7 +187,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
     }
 
     let llsizingty = match t.sty {
-        _ if !ty::lltype_is_sized(cx.tcx(), t) => {
+        _ if !lltype_is_sized(cx.tcx(), t) => {
             cx.sess().bug(format!("trying to take the sizing type of {}, an unsized type",
                                   ppaux::ty_to_string(cx.tcx(), t))[])
         }
@@ -199,7 +199,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
         ty::ty_float(t) => Type::float_from_ty(cx, t),
 
         ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
-            if ty::type_is_sized(cx.tcx(), ty) {
+            if type_is_sized(cx.tcx(), ty) {
                 Type::i8p(cx)
             } else {
                 Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
@@ -241,7 +241,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
         }
 
-        ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
+        ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
             cx.sess().bug(format!("fictitious type {} in sizing_type_of()",
                                   ppaux::ty_to_string(cx.tcx(), t))[])
         }
@@ -267,11 +267,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
         // struct which might be unsized, but is monomorphised to a sized type.
         // In this case we'll fake a fat pointer with no unsize info (we use 0).
         // However, its still a fat pointer, so we need some type use.
-        if ty::type_is_sized(cx.tcx(), t) {
+        if type_is_sized(cx.tcx(), t) {
             return Type::i8p(cx);
         }
 
-        match ty::unsized_part_of_type(cx.tcx(), t).sty {
+        match unsized_part_of_type(cx.tcx(), t).sty {
             ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyU),
             ty::ty_trait(_) => Type::vtable_ptr(cx),
             _ => panic!("Unexpected type returned from unsized_part_of_type : {}",
@@ -342,7 +342,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
                   cx.tn().find_type("str_slice").unwrap()
               }
               ty::ty_trait(..) => Type::opaque_trait(cx),
-              _ if !ty::type_is_sized(cx.tcx(), ty) => {
+              _ if !type_is_sized(cx.tcx(), ty) => {
                   let p_ty = type_of(cx, ty).ptr_to();
                   Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false)
               }
@@ -414,6 +414,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
       },
 
       ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
+      ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
       ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
       ty::ty_err(..) => cx.sess().bug("type_of with ty_err"),
     };
diff --git a/src/librustc_trans/trans/value.rs b/src/librustc_trans/trans/value.rs
index 4f9b8c5ea37..9e959ce4221 100644
--- a/src/librustc_trans/trans/value.rs
+++ b/src/librustc_trans/trans/value.rs
@@ -20,7 +20,7 @@ pub struct Value(pub ValueRef);
 macro_rules! opt_val { ($e:expr) => (
     unsafe {
         match $e {
-            p if p.is_not_null() => Some(Value(p)),
+            p if !p.is_null() => Some(Value(p)),
             _ => None
         }
     }
@@ -37,7 +37,7 @@ impl Value {
     pub fn get_parent(self) -> Option<BasicBlock> {
         unsafe {
             match llvm::LLVMGetInstructionParent(self.get()) {
-                p if p.is_not_null() => Some(BasicBlock(p)),
+                p if !p.is_null() => Some(BasicBlock(p)),
                 _ => None
             }
         }
@@ -77,7 +77,7 @@ impl Value {
     pub fn get_first_use(self) -> Option<Use> {
         unsafe {
             match llvm::LLVMGetFirstUse(self.get()) {
-                u if u.is_not_null() => Some(Use(u)),
+                u if !u.is_null() => Some(Use(u)),
                 _ => None
             }
         }
@@ -119,7 +119,7 @@ impl Value {
     /// Tests if this value is a terminator instruction
     pub fn is_a_terminator_inst(self) -> bool {
         unsafe {
-            llvm::LLVMIsATerminatorInst(self.get()).is_not_null()
+            !llvm::LLVMIsATerminatorInst(self.get()).is_null()
         }
     }
 }
@@ -142,7 +142,7 @@ impl Use {
     pub fn get_next_use(self) -> Option<Use> {
         unsafe {
             match llvm::LLVMGetNextUse(self.get()) {
-                u if u.is_not_null() => Some(Use(u)),
+                u if !u.is_null() => Some(Use(u)),
                 _ => None
             }
         }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 81e6ec4df56..dee9aafd06d 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -16,11 +16,11 @@
 //! somewhat differently during the collect and check phases,
 //! particularly with respect to looking up the types of top-level
 //! items.  In the collect phase, the crate context is used as the
-//! `AstConv` instance; in this phase, the `get_item_ty()` function
+//! `AstConv` instance; in this phase, the `get_item_type_scheme()` function
 //! triggers a recursive call to `ty_of_item()`  (note that
 //! `ast_ty_to_ty()` will detect recursive types and report an error).
 //! In the check phase, when the FnCtxt is used as the `AstConv`,
-//! `get_item_ty()` just looks up the item type in `tcx.tcache`.
+//! `get_item_type_scheme()` just looks up the item type in `tcx.tcache`.
 //!
 //! The `RegionScope` trait controls what happens when the user does
 //! not specify a region in some location where a region is required
@@ -51,7 +51,7 @@ use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGION
 use middle::const_eval;
 use middle::def;
 use middle::resolve_lifetime as rl;
-use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
+use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::subst::{VecPerParamSpace};
 use middle::ty::{mod, RegionEscape, Ty};
 use rscope::{mod, UnelidableRscope, RegionScope, SpecificRscope,
@@ -62,7 +62,7 @@ use util::nodemap::DefIdMap;
 use util::ppaux::{mod, Repr, UserString};
 
 use std::rc::Rc;
-use std::iter::AdditiveIterator;
+use std::iter::{repeat, AdditiveIterator};
 use syntax::{abi, ast, ast_util};
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -70,7 +70,7 @@ use syntax::print::pprust;
 
 pub trait AstConv<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx>;
+    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx>;
     fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
 
     /// Return an (optional) substitution to convert bound type parameters that
@@ -84,25 +84,45 @@ pub trait AstConv<'tcx> {
     /// What type should we use when a type is omitted?
     fn ty_infer(&self, span: Span) -> Ty<'tcx>;
 
-    /// Returns true if associated types from the given trait and type are
-    /// allowed to be used here and false otherwise.
-    fn associated_types_of_trait_are_valid(&self,
-                                           ty: Ty<'tcx>,
-                                           trait_id: ast::DefId)
-                                           -> bool;
-
-    /// Returns the concrete type bound to the given associated type (indicated
-    /// by associated_type_id) in the current context. For example,
-    /// in `trait Foo { type A; }` looking up `A` will give a type variable;
-    /// in `impl Foo for ... { type A = int; ... }` looking up `A` will give `int`.
-    fn associated_type_binding(&self,
-                               span: Span,
-                               self_ty: Option<Ty<'tcx>>,
-                               // DefId for the declaration of the trait
-                               // in which the associated type is declared.
-                               trait_id: ast::DefId,
-                               associated_type_id: ast::DefId)
-                               -> Option<Ty<'tcx>>;
+    /// Projecting an associated type from a (potentially)
+    /// higher-ranked trait reference is more complicated, because of
+    /// the possibility of late-bound regions appearing in the
+    /// associated type binding. This is not legal in function
+    /// signatures for that reason. In a function body, we can always
+    /// handle it because we can use inference variables to remove the
+    /// late-bound regions.
+    fn projected_ty_from_poly_trait_ref(&self,
+                                        span: Span,
+                                        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+                                        item_name: ast::Name)
+                                        -> Ty<'tcx>
+    {
+        if ty::binds_late_bound_regions(self.tcx(), &poly_trait_ref) {
+            self.tcx().sess.span_err(
+                span,
+                "cannot extract an associated type from a higher-ranked trait bound \
+                 in this context");
+            self.tcx().types.err
+        } else {
+            // no late-bound regions, we can just ignore the binder
+            self.projected_ty(span, poly_trait_ref.0.clone(), item_name)
+        }
+    }
+
+    /// Project an associated type from a non-higher-ranked trait reference.
+    /// This is fairly straightforward and can be accommodated in any context.
+    fn projected_ty(&self,
+                    span: Span,
+                    _trait_ref: Rc<ty::TraitRef<'tcx>>,
+                    _item_name: ast::Name)
+                    -> Ty<'tcx>
+    {
+        self.tcx().sess.span_err(
+            span,
+            "associated types are not accepted in this context");
+
+        self.tcx().types.err
+    }
 }
 
 pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
@@ -164,10 +184,16 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                             let mut m = String::new();
                             let len = v.len();
                             for (i, (name, n)) in v.into_iter().enumerate() {
-                                m.push_str(if n == 1 {
+                                let help_name = if name.is_empty() {
+                                    format!("argument {}", i + 1)
+                                } else {
                                     format!("`{}`", name)
+                                };
+
+                                m.push_str(if n == 1 {
+                                    help_name
                                 } else {
-                                    format!("one of `{}`'s {} elided lifetimes", name, n)
+                                    format!("one of {}'s {} elided lifetimes", help_name, n)
                                 }[]);
 
                                 if len == 2 && i == 0 {
@@ -218,7 +244,6 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
 fn ast_path_substs_for_ty<'tcx,AC,RS>(
     this: &AC,
     rscope: &RS,
-    decl_def_id: ast::DefId,
     decl_generics: &ty::Generics<'tcx>,
     path: &ast::Path)
     -> Substs<'tcx>
@@ -249,28 +274,26 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
         }
     };
 
+    prohibit_projections(this.tcx(), assoc_bindings.as_slice());
+
     create_substs_for_ast_path(this,
                                rscope,
                                path.span,
-                               decl_def_id,
                                decl_generics,
                                None,
                                types,
-                               regions,
-                               assoc_bindings)
+                               regions)
 }
 
 fn create_substs_for_ast_path<'tcx,AC,RS>(
     this: &AC,
     rscope: &RS,
     span: Span,
-    decl_def_id: ast::DefId,
     decl_generics: &ty::Generics<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     types: Vec<Ty<'tcx>>,
-    regions: Vec<ty::Region>,
-    assoc_bindings: Vec<(ast::Ident, Ty<'tcx>)>)
-    -> Substs<'tcx>
+    regions: Vec<ty::Region>)
+ -> Substs<'tcx>
     where AC: AstConv<'tcx>, RS: RegionScope
 {
     let tcx = this.tcx();
@@ -294,8 +317,8 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
 
         match anon_regions {
             Ok(v) => v.into_iter().collect(),
-            Err(_) => Vec::from_fn(expected_num_region_params,
-                                   |_| ty::ReStatic) // hokey
+            Err(_) => range(0, expected_num_region_params)
+                          .map(|_| ty::ReStatic).collect() // hokey
         }
     };
 
@@ -376,52 +399,21 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
         }
     }
 
-    for formal_assoc in decl_generics.types.get_slice(AssocSpace).iter() {
-        let mut found = false;
-        for &(ident, ty) in assoc_bindings.iter() {
-            if formal_assoc.name.ident() == ident {
-                substs.types.push(AssocSpace, ty);
-                found = true;
-                break;
-            }
-        }
-        if !found {
-            match this.associated_type_binding(span,
-                                               self_ty,
-                                               decl_def_id,
-                                               formal_assoc.def_id) {
-                Some(ty) => {
-                    substs.types.push(AssocSpace, ty);
-                }
-                None => {
-                    substs.types.push(AssocSpace, ty::mk_err());
-                    span_err!(this.tcx().sess, span, E0171,
-                              "missing type for associated type `{}`",
-                              token::get_ident(formal_assoc.name.ident()));
-                }
-            }
-        }
-    }
-
-    for &(ident, _) in assoc_bindings.iter() {
-        let mut formal_idents = decl_generics.types.get_slice(AssocSpace)
-                                .iter().map(|t| t.name.ident());
-        if !formal_idents.any(|i| i == ident) {
-            span_err!(this.tcx().sess, span, E0177,
-                      "associated type `{}` does not exist",
-                      token::get_ident(ident));
-        }
-    }
-
     return substs;
 }
 
+struct ConvertedBinding<'tcx> {
+    item_name: ast::Name,
+    ty: Ty<'tcx>,
+    span: Span,
+}
+
 fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
                                                     rscope: &RS,
                                                     data: &ast::AngleBracketedParameterData)
                                                     -> (Vec<ty::Region>,
                                                         Vec<Ty<'tcx>>,
-                                                        Vec<(ast::Ident, Ty<'tcx>)>)
+                                                        Vec<ConvertedBinding<'tcx>>)
     where AC: AstConv<'tcx>, RS: RegionScope
 {
     let regions: Vec<_> =
@@ -436,7 +428,9 @@ fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
 
     let assoc_bindings: Vec<_> =
         data.bindings.iter()
-        .map(|b| (b.ident, ast_ty_to_ty(this, rscope, &*b.ty)))
+        .map(|b| ConvertedBinding { item_name: b.ident.name,
+                                    ty: ast_ty_to_ty(this, rscope, &*b.ty),
+                                    span: b.span })
         .collect();
 
     (regions, types, assoc_bindings)
@@ -506,7 +500,7 @@ fn convert_parenthesized_parameters<'tcx,AC>(this: &AC,
                             .map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t))
                             .collect::<Vec<Ty<'tcx>>>();
 
-    let input_params = Vec::from_elem(inputs.len(), String::new());
+    let input_params: Vec<_> = repeat(String::new()).take(inputs.len()).collect();
     let (implied_output_region,
          params_lifetimes) = find_implied_output_region(&*inputs, input_params);
 
@@ -528,38 +522,47 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
     rscope: &RS,
     ast_trait_ref: &ast::PolyTraitRef,
     self_ty: Option<Ty<'tcx>>,
-    allow_eq: AllowEqConstraints)
-    -> Rc<ty::PolyTraitRef<'tcx>>
+    poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+    -> ty::PolyTraitRef<'tcx>
     where AC: AstConv<'tcx>, RS: RegionScope
 {
+    let mut projections = Vec::new();
+
     let trait_ref =
-        instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, allow_eq);
-    let trait_ref = (*trait_ref).clone();
-    Rc::new(ty::Binder(trait_ref)) // Ugh.
+        instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref,
+                              self_ty, Some(&mut projections));
+
+    for projection in projections.into_iter() {
+        poly_projections.push(ty::Binder(projection));
+    }
+
+    ty::Binder(trait_ref)
 }
 
 /// Instantiates the path for the given trait reference, assuming that it's
 /// bound to a valid trait type. Returns the def_id for the defining trait.
 /// Fails if the type is a type other than a trait type.
-pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
-                                         rscope: &RS,
-                                         ast_trait_ref: &ast::TraitRef,
-                                         self_ty: Option<Ty<'tcx>>,
-                                         allow_eq: AllowEqConstraints)
-                                         -> Rc<ty::TraitRef<'tcx>>
-                                         where AC: AstConv<'tcx>,
-                                               RS: RegionScope
+///
+/// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
+/// are disallowed. Otherwise, they are pushed onto the vector given.
+pub fn instantiate_trait_ref<'tcx,AC,RS>(
+    this: &AC,
+    rscope: &RS,
+    ast_trait_ref: &ast::TraitRef,
+    self_ty: Option<Ty<'tcx>>,
+    projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
+    -> Rc<ty::TraitRef<'tcx>>
+    where AC: AstConv<'tcx>, RS: RegionScope
 {
     match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
         def::DefTrait(trait_def_id) => {
-            let trait_ref = Rc::new(ast_path_to_trait_ref(this,
-                                                          rscope,
-                                                          trait_def_id,
-                                                          self_ty,
-                                                          &ast_trait_ref.path,
-                                                          allow_eq));
-            this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
-                                                      trait_ref.clone());
+            let trait_ref = ast_path_to_trait_ref(this,
+                                                  rscope,
+                                                  trait_def_id,
+                                                  self_ty,
+                                                  &ast_trait_ref.path,
+                                                  projections);
+            this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone());
             trait_ref
         }
         _ => {
@@ -570,20 +573,14 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
     }
 }
 
-#[deriving(PartialEq,Show)]
-pub enum AllowEqConstraints {
-    Allow,
-    DontAllow
-}
-
-fn ast_path_to_trait_ref<'tcx,AC,RS>(
+fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
     this: &AC,
     rscope: &RS,
     trait_def_id: ast::DefId,
     self_ty: Option<Ty<'tcx>>,
     path: &ast::Path,
-    allow_eq: AllowEqConstraints)
-    -> ty::TraitRef<'tcx>
+    mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
+    -> Rc<ty::TraitRef<'tcx>>
     where AC: AstConv<'tcx>, RS: RegionScope
 {
     debug!("ast_path_to_trait_ref {}", path);
@@ -618,22 +615,75 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
         }
     };
 
-    if allow_eq == AllowEqConstraints::DontAllow && assoc_bindings.len() > 0 {
-        span_err!(this.tcx().sess, path.span, E0173,
-                  "equality constraints are not allowed in this position");
-    }
-
     let substs = create_substs_for_ast_path(this,
                                             &shifted_rscope,
                                             path.span,
-                                            trait_def_id,
                                             &trait_def.generics,
                                             self_ty,
                                             types,
-                                            regions,
-                                            assoc_bindings);
+                                            regions);
+    let substs = this.tcx().mk_substs(substs);
+
+    let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs));
+
+    match projections {
+        None => {
+            prohibit_projections(this.tcx(), assoc_bindings.as_slice());
+        }
+        Some(ref mut v) => {
+            for binding in assoc_bindings.iter() {
+                match ast_type_binding_to_projection_predicate(this, trait_ref.clone(), binding) {
+                    Ok(pp) => { v.push(pp); }
+                    Err(ErrorReported) => { }
+                }
+            }
+        }
+    }
+
+    trait_ref
+}
+
+pub fn ast_type_binding_to_projection_predicate<'tcx,AC>(
+    this: &AC,
+    trait_ref: Rc<ty::TraitRef<'tcx>>,
+    binding: &ConvertedBinding<'tcx>)
+    -> Result<ty::ProjectionPredicate<'tcx>, ErrorReported>
+    where AC : AstConv<'tcx>
+{
+    // Given something like `U : SomeTrait<T=X>`, we want to produce a
+    // predicate like `<U as SomeTrait>::T = X`. This is somewhat
+    // subtle in the event that `T` is defined in a supertrait of
+    // `SomeTrait`, because in that case we need to upcast.
+    //
+    // That is, consider this case:
+    //
+    // ```
+    // trait SubTrait : SuperTrait<int> { }
+    // trait SuperTrait<A> { type T; }
+    //
+    // ... B : SubTrait<T=foo> ...
+    // ```
+    //
+    // We want to produce `<B as SuperTrait<int>>::T == foo`.
+
+    // FIXME(#19541): supertrait upcasting not actually impl'd :)
+
+    if !trait_defines_associated_type_named(this, trait_ref.def_id, binding.item_name) {
+        this.tcx().sess.span_err(
+            binding.span,
+            format!("no associated type `{}` defined in `{}`",
+                    token::get_name(binding.item_name),
+                    trait_ref.user_string(this.tcx())).as_slice());
+        return Err(ErrorReported);
+    }
 
-    ty::TraitRef::new(trait_def_id, this.tcx().mk_substs(substs))
+    Ok(ty::ProjectionPredicate {
+        projection_ty: ty::ProjectionTy {
+            trait_ref: trait_ref,
+            item_name: binding.item_name,
+        },
+        ty: binding.ty,
+    })
 }
 
 pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
@@ -644,14 +694,13 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     -> TypeAndSubsts<'tcx>
 {
     let tcx = this.tcx();
-    let ty::Polytype {
+    let ty::TypeScheme {
         generics,
         ty: decl_ty
-    } = this.get_item_ty(did);
+    } = this.get_item_type_scheme(did);
 
     let substs = ast_path_substs_for_ty(this,
                                         rscope,
-                                        did,
                                         &generics,
                                         path);
     let ty = decl_ty.subst(tcx, &substs);
@@ -672,10 +721,10 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
     where AC : AstConv<'tcx>, RS : RegionScope
 {
     let tcx = this.tcx();
-    let ty::Polytype {
+    let ty::TypeScheme {
         generics,
         ty: decl_ty
-    } = this.get_item_ty(did);
+    } = this.get_item_type_scheme(did);
 
     let wants_params =
         generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
@@ -685,15 +734,15 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
         path.segments.iter().all(|s| s.parameters.is_empty());
 
     let substs = if needs_defaults {
-        let type_params = Vec::from_fn(generics.types.len(TypeSpace),
-                                       |_| this.ty_infer(path.span));
+        let type_params: Vec<_> = range(0, generics.types.len(TypeSpace))
+                                      .map(|_| this.ty_infer(path.span)).collect();
         let region_params =
             rscope.anon_regions(path.span, generics.regions.len(TypeSpace))
                   .unwrap();
         Substs::new(VecPerParamSpace::params_from_type(type_params),
                     VecPerParamSpace::params_from_type(region_params))
     } else {
-        ast_path_substs_for_ty(this, rscope, did, &generics, path)
+        ast_path_substs_for_ty(this, rscope, &generics, path)
     };
 
     let ty = decl_ty.subst(tcx, &substs);
@@ -756,11 +805,13 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
     }
 }
 
+type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
+
 fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
                                    rscope: &RS,
                                    ty: &ast::Ty,
                                    bounds: &[ast::TyParamBound])
-                                   -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
+                                   -> Result<TraitAndProjections<'tcx>, ErrorReported>
     where AC : AstConv<'tcx>, RS : RegionScope
 {
     /*!
@@ -778,12 +829,17 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
         ast::TyPath(ref path, id) => {
             match this.tcx().def_map.borrow().get(&id) {
                 Some(&def::DefTrait(trait_def_id)) => {
-                    return Ok(ty::Binder(ast_path_to_trait_ref(this,
-                                                               rscope,
-                                                               trait_def_id,
-                                                               None,
-                                                               path,
-                                                               AllowEqConstraints::Allow)));
+                    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();
+                    Ok((trait_ref, projection_bounds))
                 }
                 _ => {
                     span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait");
@@ -826,6 +882,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
                                         rscope: &RS,
                                         span: Span,
                                         trait_ref: ty::PolyTraitRef<'tcx>,
+                                        projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
                                         bounds: &[ast::TyParamBound])
                                         -> Ty<'tcx>
     where AC : AstConv<'tcx>, RS : RegionScope
@@ -833,7 +890,8 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
     let existential_bounds = conv_existential_bounds(this,
                                                      rscope,
                                                      span,
-                                                     Some(&trait_ref),
+                                                     Some(trait_ref.clone()),
+                                                     projection_bounds,
                                                      bounds);
 
     let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
@@ -843,6 +901,68 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
     result
 }
 
+fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
+                                   ast_ty: &ast::Ty,
+                                   provenance: def::TyParamProvenance,
+                                   assoc_name: ast::Name)
+                                   -> Ty<'tcx>
+{
+    let tcx = this.tcx();
+    let ty_param_def_id = provenance.def_id();
+    let mut suitable_bounds: Vec<_>;
+    let ty_param_name: ast::Name;
+    { // contain scope of refcell:
+        let ty_param_defs = tcx.ty_param_defs.borrow();
+        let ty_param_def = &ty_param_defs[ty_param_def_id.node];
+        ty_param_name = ty_param_def.name;
+
+        // FIXME(#19541): we should consider associated types in
+        // super-traits. Probably by elaborating the bounds.
+
+        suitable_bounds =
+            ty_param_def.bounds.trait_bounds // FIXME(#20300) -- search where clauses, not bounds
+            .iter()
+            .cloned()
+            .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
+            .collect();
+    }
+
+    if suitable_bounds.len() == 0 {
+        tcx.sess.span_err(ast_ty.span,
+                          format!("associated type `{}` not found for type parameter `{}`",
+                                  token::get_name(assoc_name),
+                                  token::get_name(ty_param_name)).as_slice());
+        return this.tcx().types.err;
+    }
+
+    if suitable_bounds.len() > 1 {
+        tcx.sess.span_err(ast_ty.span,
+                          format!("ambiguous associated type `{}` in bounds of `{}`",
+                                  token::get_name(assoc_name),
+                                  token::get_name(ty_param_name)).as_slice());
+
+        for suitable_bound in suitable_bounds.iter() {
+            span_note!(this.tcx().sess, ast_ty.span,
+                       "associated type `{}` could derive from `{}`",
+                       token::get_name(ty_param_name),
+                       suitable_bound.user_string(this.tcx()));
+        }
+    }
+
+    let suitable_bound = suitable_bounds.pop().unwrap().clone();
+    return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name);
+}
+
+fn trait_defines_associated_type_named(this: &AstConv,
+                                       trait_def_id: ast::DefId,
+                                       assoc_name: ast::Name)
+                                       -> bool
+{
+    let tcx = this.tcx();
+    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+    trait_def.associated_type_names.contains(&assoc_name)
+}
+
 fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
                            rscope: &RS,
                            ast_ty: &ast::Ty, // the TyQPath
@@ -861,33 +981,13 @@ fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
                                           rscope,
                                           &*qpath.trait_ref,
                                           Some(self_type),
-                                          AllowEqConstraints::DontAllow);
+                                          None);
 
     debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
 
-    if let Some(ty) = find_assoc_ty(this, &*trait_ref, qpath.item_name) {
-        return ty;
-    }
-
-    this.tcx().sess.span_bug(ast_ty.span,
-                             "this associated type didn't get added \
-                              as a parameter for some reason")
-}
-
-fn find_assoc_ty<'tcx, AC>(this: &AC,
-                           trait_ref: &ty::TraitRef<'tcx>,
-                           type_name: ast::Ident)
-                           -> Option<Ty<'tcx>>
-where AC: AstConv<'tcx> {
-    let trait_def = this.get_trait_def(trait_ref.def_id);
-
-    for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() {
-        if ty_param_def.name == type_name.name {
-            return Some(trait_ref.substs.type_for_def(ty_param_def));
-        }
-    }
-
-    None
+    return this.projected_ty(ast_ty.span,
+                             trait_ref,
+                             qpath.item_name.name);
 }
 
 // Parses the programmer's textual representation of a type into our
@@ -921,12 +1021,12 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             }
             ast::TyObjectSum(ref ty, ref bounds) => {
                 match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) {
-                    Ok(trait_ref) => {
+                    Ok((trait_ref, projection_bounds)) => {
                         trait_ref_to_object_type(this, rscope, ast_ty.span,
-                                                 trait_ref, bounds[])
+                                                 trait_ref, projection_bounds, bounds[])
                     }
                     Err(ErrorReported) => {
-                        ty::mk_err()
+                        this.tcx().types.err
                     }
                 }
             }
@@ -964,13 +1064,15 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                      rscope,
                                                      ast_ty.span,
                                                      None,
+                                                     Vec::new(),
                                                      f.bounds.as_slice());
+                let region_bound = bounds.region_bound;
                 let fn_decl = ty_of_closure(this,
                                             f.unsafety,
                                             f.onceness,
                                             bounds,
                                             ty::RegionTraitStore(
-                                                bounds.region_bound,
+                                                region_bound,
                                                 ast::MutMutable),
                                             &*f.decl,
                                             abi::Rust,
@@ -994,28 +1096,33 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     def::DefTrait(trait_def_id) => {
                         // N.B. this case overlaps somewhat with
                         // TyObjectSum, see that fn for details
-                        let result = ty::Binder(ast_path_to_trait_ref(this,
-                                                                      rscope,
-                                                                      trait_def_id,
-                                                                      None,
-                                                                      path,
-                                                                      AllowEqConstraints::Allow));
-                        trait_ref_to_object_type(this, rscope, path.span, result, &[])
+                        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();
+                        trait_ref_to_object_type(this, rscope, path.span,
+                                                 trait_ref, projection_bounds, &[])
                     }
                     def::DefTy(did, _) | def::DefStruct(did) => {
                         ast_path_to_ty(this, rscope, did, path).ty
                     }
-                    def::DefTyParam(space, id, n) => {
+                    def::DefTyParam(space, index, _, name) => {
                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                        ty::mk_param(tcx, space, n, id)
+                        ty::mk_param(tcx, space, index, name)
                     }
-                    def::DefSelfTy(id) => {
+                    def::DefSelfTy(_) => {
                         // n.b.: resolve guarantees that the this type only appears in a
                         // trait, which we rely upon in various places when creating
                         // substs
                         check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                        let did = ast_util::local_def(id);
-                        ty::mk_self_type(tcx, did)
+                        ty::mk_self_type(tcx)
                     }
                     def::DefMod(id) => {
                         tcx.sess.span_fatal(ast_ty.span,
@@ -1040,46 +1147,10 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                           .unwrap()
                                                           .identifier)
                                                   .get())[]);
-                        ty::mk_err()
+                        this.tcx().types.err
                     }
-                    def::DefAssociatedPath(typ, assoc_ident) => {
-                        // FIXME(#19541): in both branches we should consider
-                        // associated types in super-traits.
-                        let (assoc_tys, tp_name): (Vec<_>, _) = match typ {
-                            def::TyParamProvenance::FromParam(did) |
-                            def::TyParamProvenance::FromSelf(did) => {
-                                let ty_param_defs = tcx.ty_param_defs.borrow();
-                                let tp_def = &(*ty_param_defs)[did.node];
-                                let assoc_tys = tp_def.bounds.trait_bounds.iter()
-                                    .filter_map(|b| find_assoc_ty(this, &b.0, assoc_ident))
-                                    .collect();
-                                (assoc_tys, token::get_name(tp_def.name).to_string())
-                            }
-                        };
-
-                        if assoc_tys.len() == 0 {
-                            tcx.sess.span_err(ast_ty.span,
-                                              format!("associated type `{}` not \
-                                                       found for type parameter `{}`",
-                                                      token::get_ident(assoc_ident),
-                                                      tp_name).as_slice());
-                            return ty::mk_err()
-                        }
-
-                        if assoc_tys.len() > 1 {
-                            tcx.sess.span_err(ast_ty.span,
-                                              format!("ambiguous associated type \
-                                                       `{}` in bounds of `{}`",
-                                                      token::get_ident(assoc_ident),
-                                                      tp_name).as_slice());
-                        }
-
-                        let mut result_ty = assoc_tys[0];
-                        if let Some(substs) = this.get_free_substs() {
-                            result_ty = result_ty.subst(tcx, substs);
-                        }
-
-                        result_ty
+                    def::DefAssociatedPath(provenance, assoc_ident) => {
+                        associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
                     }
                     _ => {
                         tcx.sess.span_fatal(ast_ty.span,
@@ -1372,7 +1443,7 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
     this: &AC,
     unsafety: ast::Unsafety,
     onceness: ast::Onceness,
-    bounds: ty::ExistentialBounds,
+    bounds: ty::ExistentialBounds<'tcx>,
     store: ty::TraitStore,
     decl: &ast::FnDecl,
     abi: abi::Abi,
@@ -1434,15 +1505,16 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
     this: &AC,
     rscope: &RS,
     span: Span,
-    principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for boxed closures
+    principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
+    projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
     ast_bounds: &[ast::TyParamBound])
-    -> ty::ExistentialBounds
+    -> ty::ExistentialBounds<'tcx>
 {
     let partitioned_bounds =
         partition_bounds(this.tcx(), span, ast_bounds);
 
     conv_existential_bounds_from_partitioned_bounds(
-        this, rscope, span, principal_trait_ref, partitioned_bounds)
+        this, rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
 }
 
 fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
@@ -1455,32 +1527,32 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
 {
     let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
 
-    let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
-        Some(trait_bound) => {
-            Some(instantiate_poly_trait_ref(this,
-                                            rscope,
-                                            trait_bound,
-                                            None,
-                                            AllowEqConstraints::Allow))
-        }
-        None => {
-            this.tcx().sess.span_err(
-                span,
-                "at least one non-builtin trait is required for an object type");
-            None
-        }
+    let mut projection_bounds = Vec::new();
+    let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
+        let trait_bound = partitioned_bounds.trait_bounds.remove(0);
+        Some(instantiate_poly_trait_ref(this,
+                                        rscope,
+                                        trait_bound,
+                                        None,
+                                        &mut projection_bounds))
+    } else {
+        this.tcx().sess.span_err(
+            span,
+            "at least one non-builtin trait is required for an object type");
+        None
     };
 
     let bounds =
         conv_existential_bounds_from_partitioned_bounds(this,
                                                         rscope,
                                                         span,
-                                                        main_trait_bound.as_ref().map(|tr| &**tr),
+                                                        main_trait_bound.clone(),
+                                                        projection_bounds,
                                                         partitioned_bounds);
 
     match main_trait_bound {
-        None => ty::mk_err(),
-        Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds)
+        None => this.tcx().types.err,
+        Some(principal) => ty::mk_trait(this.tcx(), principal, bounds)
     }
 }
 
@@ -1488,9 +1560,10 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
     this: &AC,
     rscope: &RS,
     span: Span,
-    principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for boxed closures
+    principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
+    mut projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, // Empty for boxed closures
     partitioned_bounds: PartitionedBounds)
-    -> ty::ExistentialBounds
+    -> ty::ExistentialBounds<'tcx>
     where AC: AstConv<'tcx>, RS:RegionScope
 {
     let PartitionedBounds { builtin_bounds,
@@ -1513,9 +1586,12 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
                                             principal_trait_ref,
                                             builtin_bounds);
 
+    ty::sort_bounds_list(projection_bounds.as_mut_slice());
+
     ty::ExistentialBounds {
         region_bound: region_bound,
         builtin_bounds: builtin_bounds,
+        projection_bounds: projection_bounds,
     }
 }
 
@@ -1526,7 +1602,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
 fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
                                   span: Span,
                                   explicit_region_bounds: &[&ast::Lifetime],
-                                  principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>,
+                                  principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>,
                                   builtin_bounds: ty::BuiltinBounds)
                                   -> Option<ty::Region>
 {
@@ -1551,7 +1627,7 @@ fn compute_opt_region_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
     // No explicit region bound specified. Therefore, examine trait
     // bounds and see if we can derive region bounds from those.
     let derived_region_bounds =
-        ty::object_region_bounds(tcx, principal_trait_ref, builtin_bounds);
+        ty::object_region_bounds(tcx, principal_trait_ref.as_ref(), builtin_bounds);
 
     // If there are no derived region bounds, then report back that we
     // can find no region bound.
@@ -1586,7 +1662,7 @@ fn compute_region_bound<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
     rscope: &RS,
     span: Span,
     region_bounds: &[&ast::Lifetime],
-    principal_trait_ref: Option<&ty::PolyTraitRef<'tcx>>, // None for closures
+    principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for closures
     builtin_bounds: ty::BuiltinBounds)
     -> ty::Region
 {
@@ -1626,7 +1702,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
     let mut trait_def_ids = DefIdMap::new();
     for ast_bound in ast_bounds.iter() {
         match *ast_bound {
-            ast::TraitTyParamBound(ref b) => {
+            ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
                 match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
                     def::DefTrait(trait_did) => {
                         match trait_def_ids.get(&trait_did) {
@@ -1654,6 +1730,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                         if ty::try_add_builtin_trait(tcx,
                                                      trait_did,
                                                      &mut builtin_bounds) {
+                            // FIXME(#20302) -- we should check for things like Copy<T>
                             continue; // success
                         }
                     }
@@ -1664,6 +1741,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                 }
                 trait_bounds.push(b);
             }
+            ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {}
             ast::RegionTyParamBound(ref l) => {
                 region_bounds.push(l);
             }
@@ -1676,3 +1754,13 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
         region_bounds: region_bounds,
     }
 }
+
+fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>,
+                              bindings: &[ConvertedBinding<'tcx>])
+{
+    for binding in bindings.iter().take(1) {
+        tcx.sess.span_err(
+            binding.span,
+            "associated type bindings are not allowed here");
+    }
+}
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 09a5dd521f8..7c431b4fc0b 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -11,7 +11,7 @@
 use middle::def;
 use middle::infer;
 use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const};
-use middle::subst::{Subst, Substs};
+use middle::subst::{Substs};
 use middle::ty::{mod, Ty};
 use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
 use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
@@ -79,9 +79,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         }
         ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
             let const_did = tcx.def_map.borrow()[pat.id].clone().def_id();
-            let const_pty = ty::lookup_item_type(tcx, const_did);
-            fcx.write_ty(pat.id, const_pty.ty);
-            demand::suptype(fcx, pat.span, expected, const_pty.ty);
+            let const_scheme = ty::lookup_item_type(tcx, const_did);
+            fcx.write_ty(pat.id, const_scheme.ty);
+            demand::suptype(fcx, pat.span, expected, const_scheme.ty);
         }
         ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
             let typ = fcx.local_ty(pat.span, pat.id);
@@ -124,7 +124,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             check_pat_struct(pcx, pat, path, fields.as_slice(), etc, expected);
         }
         ast::PatTup(ref elements) => {
-            let element_tys = Vec::from_fn(elements.len(), |_| fcx.infcx().next_ty_var());
+            let element_tys: Vec<_> = range(0, elements.len()).map(|_| fcx.infcx()
+                .next_ty_var()).collect();
             let pat_ty = ty::mk_tup(tcx, element_tys.clone());
             fcx.write_ty(pat.id, pat_ty);
             demand::eqtype(fcx, pat.span, expected, pat_ty);
@@ -142,7 +143,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**inner, inner_ty);
             } else {
                 fcx.write_error(pat.id);
-                check_pat(pcx, &**inner, ty::mk_err());
+                check_pat(pcx, &**inner, tcx.types.err);
             }
         }
         ast::PatRegion(ref inner) => {
@@ -162,7 +163,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**inner, inner_ty);
             } else {
                 fcx.write_error(pat.id);
-                check_pat(pcx, &**inner, ty::mk_err());
+                check_pat(pcx, &**inner, tcx.types.err);
             }
         }
         ast::PatVec(ref before, ref slice, ref after) => {
@@ -285,11 +286,11 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         };
 
         if let Some(ref e) = arm.guard {
-            check_expr_has_type(fcx, &**e, ty::mk_bool());
+            check_expr_has_type(fcx, &**e, tcx.types.bool);
         }
 
         if ty::type_is_error(result_ty) || ty::type_is_error(bty) {
-            ty::mk_err()
+            tcx.types.err
         } else {
             let (origin, expected, found) = match match_src {
                 /* if-let construct without an else block */
@@ -339,7 +340,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
             fcx.write_error(pat.id);
 
             for field in fields.iter() {
-                check_pat(pcx, &*field.node.pat, ty::mk_err());
+                check_pat(pcx, &*field.node.pat, tcx.types.err);
             }
             return;
         },
@@ -358,7 +359,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
                     fcx.write_error(pat.id);
 
                     for field in fields.iter() {
-                        check_pat(pcx, &*field.node.pat, ty::mk_err());
+                        check_pat(pcx, &*field.node.pat, tcx.types.err);
                     }
                     return;
                 }
@@ -395,32 +396,39 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
     let enum_def = def.variant_def_ids()
         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
 
-    let ctor_pty = ty::lookup_item_type(tcx, enum_def);
-    let path_ty = if ty::is_fn_ty(ctor_pty.ty) {
-        ty::Polytype {
-            ty: ty::ty_fn_ret(ctor_pty.ty).unwrap(),
-            ..ctor_pty
+    let ctor_scheme = ty::lookup_item_type(tcx, enum_def);
+    let path_scheme = if ty::is_fn_ty(ctor_scheme.ty) {
+        ty::TypeScheme {
+            ty: ty::ty_fn_ret(ctor_scheme.ty).unwrap(),
+            ..ctor_scheme
         }
     } else {
-        ctor_pty
+        ctor_scheme
     };
-    instantiate_path(pcx.fcx, path, path_ty, def, pat.span, pat.id);
+    instantiate_path(pcx.fcx, path, path_scheme, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
 
     let real_path_ty = fcx.node_ty(pat.id);
-    let (arg_tys, kind_name) = match real_path_ty.sty {
+    let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
         ty::ty_enum(enum_def_id, expected_substs)
-            if def == def::DefVariant(enum_def_id, def.def_id(), false) => {
+            if def == def::DefVariant(enum_def_id, def.def_id(), false) =>
+        {
             let variant = ty::enum_variant_with_id(tcx, enum_def_id, def.def_id());
-            (variant.args.iter().map(|t| t.subst(tcx, expected_substs)).collect::<Vec<_>>(),
-                "variant")
+            (variant.args.iter()
+                         .map(|t| fcx.instantiate_type_scheme(pat.span, expected_substs, t))
+                         .collect(),
+             "variant")
         }
         ty::ty_struct(struct_def_id, expected_substs) => {
             let struct_fields = ty::struct_fields(tcx, struct_def_id, expected_substs);
-            (struct_fields.iter().map(|field| field.mt.ty).collect::<Vec<_>>(),
-                "struct")
+            (struct_fields.iter()
+                          .map(|field| fcx.instantiate_type_scheme(pat.span,
+                                                                   expected_substs,
+                                                                   &field.mt.ty))
+                          .collect(),
+             "struct")
         }
         _ => {
             let name = pprust::path_to_string(path);
@@ -430,7 +438,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
 
             if let Some(ref subpats) = *subpats {
                 for pat in subpats.iter() {
-                    check_pat(pcx, &**pat, ty::mk_err());
+                    check_pat(pcx, &**pat, tcx.types.err);
                 }
             }
             return;
@@ -448,7 +456,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
                       subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
 
             for pat in subpats.iter() {
-                check_pat(pcx, &**pat, ty::mk_err());
+                check_pat(pcx, &**pat, tcx.types.err);
             }
         } else {
             span_err!(tcx.sess, pat.span, E0023,
@@ -458,7 +466,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
                       arg_tys.len(), if arg_tys.len() == 1 {""} else {"s"});
 
             for pat in subpats.iter() {
-                check_pat(pcx, &**pat, ty::mk_err());
+                check_pat(pcx, &**pat, tcx.types.err);
             }
         }
     }
@@ -496,7 +504,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 span_note!(tcx.sess, *occupied.get(),
                     "field `{}` previously bound here",
                     token::get_ident(field.ident));
-                ty::mk_err()
+                tcx.types.err
             }
             Vacant(vacant) => {
                 vacant.set(span);
@@ -506,7 +514,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                             "struct `{}` does not have a field named `{}`",
                             ty::item_path_str(tcx, struct_id),
                             token::get_ident(field.ident));
-                        ty::mk_err()
+                        tcx.types.err
                     })
             }
         };
diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs
new file mode 100644
index 00000000000..5e9843d0e00
--- /dev/null
+++ b/src/librustc_typeck/check/assoc.rs
@@ -0,0 +1,41 @@
+// 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 middle::infer::InferCtxt;
+use middle::traits::{mod, FulfillmentContext, Normalized, MiscObligation,
+                     SelectionContext, ObligationCause};
+use middle::ty::{mod, HasProjectionTypes};
+use middle::ty_fold::{TypeFoldable, TypeFolder};
+use syntax::ast;
+use syntax::codemap::Span;
+use util::ppaux::Repr;
+
+pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+                                                param_env: &ty::ParameterEnvironment<'tcx>,
+                                                typer: &(ty::UnboxedClosureTyper<'tcx>+'a),
+                                                fulfillment_cx: &mut FulfillmentContext<'tcx>,
+                                                span: Span,
+                                                body_id: ast::NodeId,
+                                                value: &T)
+                                                -> T
+    where T : TypeFoldable<'tcx> + HasProjectionTypes + Clone + Repr<'tcx>
+{
+    debug!("normalize_associated_types_in(value={})", value.repr(infcx.tcx));
+    let mut selcx = SelectionContext::new(infcx, param_env, typer);
+    let cause = ObligationCause::new(span, body_id, MiscObligation);
+    let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value);
+    debug!("normalize_associated_types_in: result={} predicates={}",
+           result.repr(infcx.tcx),
+           obligations.repr(infcx.tcx));
+    for obligation in obligations.into_iter() {
+        fulfillment_cx.register_predicate_obligation(infcx, obligation);
+    }
+    result
+}
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index c8a8a0ff559..eba040e7ea8 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -14,8 +14,9 @@ use super::{check_fn, Expectation, FnCtxt};
 
 use astconv;
 use middle::infer;
+use middle::region::CodeExtent;
 use middle::subst;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, ToPolyTraitRef, Ty};
 use rscope::RegionScope;
 use syntax::abi;
 use syntax::ast;
@@ -47,7 +48,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
             match expected_sig_and_kind {
                 None => { // doesn't look like an unboxed closure
                     let region = astconv::opt_ast_region_to_region(fcx,
-                                                                   fcx.infcx(),
+                                                                   fcx,
                                                                    expr.span,
                                                                    &None);
 
@@ -116,7 +117,7 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         abi::RustCall,
         expected_sig);
 
-    let region = match fcx.infcx().anon_regions(expr.span, 1) {
+    let region = match fcx.anon_regions(expr.span, 1) {
         Err(_) => {
             fcx.ccx.tcx.sess.span_bug(expr.span,
                                       "can't make anon regions here?!")
@@ -132,10 +133,13 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
     fcx.write_ty(expr.id, closure_type);
 
+    let fn_sig =
+        ty::liberate_late_bound_regions(fcx.tcx(), CodeExtent::from_node_id(body.id), &fn_ty.sig);
+
     check_fn(fcx.ccx,
              ast::Unsafety::Normal,
              expr.id,
-             &fn_ty.sig,
+             &fn_sig,
              decl,
              expr.id,
              &*body,
@@ -168,7 +172,10 @@ fn deduce_unboxed_closure_expectations_from_expected_type<'a,'tcx>(
 {
     match expected_ty.sty {
         ty::ty_trait(ref object_type) => {
-            deduce_unboxed_closure_expectations_from_trait_ref(fcx, &object_type.principal)
+            let trait_ref =
+                object_type.principal_trait_ref_with_self_ty(fcx.tcx(),
+                                                             fcx.tcx().types.err);
+            deduce_unboxed_closure_expectations_from_trait_ref(fcx, &trait_ref)
         }
         ty::ty_infer(ty::TyVar(vid)) => {
             deduce_unboxed_closure_expectations_from_obligations(fcx, vid)
@@ -227,23 +234,21 @@ fn deduce_unboxed_closure_expectations_from_obligations<'a,'tcx>(
 {
     // Here `expected_ty` is known to be a type inference variable.
     for obligation in fcx.inh.fulfillment_cx.borrow().pending_obligations().iter() {
-        match obligation.trait_ref {
-            ty::Predicate::Trait(ref trait_ref) => {
+        match obligation.predicate {
+            ty::Predicate::Trait(ref trait_predicate) => {
+                let trait_ref = trait_predicate.to_poly_trait_ref();
                 let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
                 match self_ty.sty {
                     ty::ty_infer(ty::TyVar(v)) if expected_vid == v => { }
                     _ => { continue; }
                 }
 
-                match deduce_unboxed_closure_expectations_from_trait_ref(fcx, &**trait_ref) {
+                match deduce_unboxed_closure_expectations_from_trait_ref(fcx, &trait_ref) {
                     Some(e) => { return Some(e); }
                     None => { }
                 }
             }
-            ty::Predicate::Equate(..) |
-            ty::Predicate::RegionOutlives(..) |
-            ty::Predicate::TypeOutlives(..) => {
-            }
+            _ => { }
         }
     }
 
@@ -290,7 +295,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                 (&ty::UniqTraitStore, _) => ast::Once,
                 (&ty::RegionTraitStore(..), _) => ast::Many,
             };
-            (Some(sig), onceness, cenv.bounds)
+            (Some(sig), onceness, cenv.bounds.clone())
         }
         _ => {
             // Not an error! Means we're inferring the closure type
@@ -311,7 +316,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                        decl,
                                        abi::Rust,
                                        expected_sig);
-    let fty_sig = fn_ty.sig.clone();
+    let fn_sig = fn_ty.sig.clone();
     let fty = ty::mk_closure(tcx, fn_ty);
     debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
 
@@ -326,10 +331,13 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         ty::UniqTraitStore => (ast::Unsafety::Normal, expr.id)
     };
 
+    let fn_sig =
+        ty::liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), &fn_sig);
+
     check_fn(fcx.ccx,
              inherited_style,
              inherited_style_id,
-             &fty_sig,
+             &fn_sig,
              &*decl,
              expr.id,
              &*body,
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 8ce7a7edb46..a751b65a0f8 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -10,8 +10,9 @@
 
 use super::probe;
 
-use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee};
-use middle::subst::{mod, Subst};
+use check::{mod, FnCtxt, NoPreference, PreferMutLvalue, callee, demand};
+use middle::mem_categorization::Typer;
+use middle::subst::{mod};
 use middle::traits;
 use middle::ty::{mod, Ty};
 use middle::ty::{MethodCall, MethodCallee, MethodObject, MethodOrigin,
@@ -23,6 +24,7 @@ use syntax::ast;
 use syntax::codemap::Span;
 use std::rc::Rc;
 use std::mem;
+use std::iter::repeat;
 use util::ppaux::Repr;
 
 struct ConfirmContext<'a, 'tcx:'a> {
@@ -41,12 +43,6 @@ struct InstantiatedMethodSig<'tcx> {
     /// the method.
     all_substs: subst::Substs<'tcx>,
 
-    /// Substitution to use when adding obligations from the method
-    /// bounds. Normally equal to `all_substs` except for object
-    /// receivers. See FIXME in instantiate_method_sig() for
-    /// explanation.
-    method_bounds_substs: subst::Substs<'tcx>,
-
     /// Generic bounds on the method's parameters which must be added
     /// as pending obligations.
     method_bounds: ty::GenericBounds<'tcx>,
@@ -102,7 +98,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
 
         // Create the final signature for the method, replacing late-bound regions.
         let InstantiatedMethodSig {
-            method_sig, all_substs, method_bounds_substs, method_bounds
+            method_sig, all_substs, method_bounds
         } = self.instantiate_method_sig(&pick, all_substs);
         let method_self_ty = method_sig.inputs[0];
 
@@ -110,7 +106,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         self.unify_receivers(self_ty, method_self_ty);
 
         // Add any trait/regions obligations specified on the method's type parameters.
-        self.add_obligations(&pick, &method_bounds_substs, &method_bounds);
+        self.add_obligations(&pick, &all_substs, &method_bounds);
 
         // Create the final `MethodCallee`.
         let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
@@ -227,14 +223,14 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                     let upcast_poly_trait_ref =
                         this.upcast(original_poly_trait_ref.clone(), trait_def_id);
                     let upcast_trait_ref =
-                        this.replace_late_bound_regions_with_fresh_var(&*upcast_poly_trait_ref);
+                        this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
                     debug!("original_poly_trait_ref={} upcast_trait_ref={} target_trait={}",
                            original_poly_trait_ref.repr(this.tcx()),
                            upcast_trait_ref.repr(this.tcx()),
                            trait_def_id.repr(this.tcx()));
                     let substs = upcast_trait_ref.substs.clone();
                     let origin = MethodTraitObject(MethodObject {
-                        trait_ref: Rc::new(upcast_trait_ref),
+                        trait_ref: upcast_trait_ref,
                         object_trait_id: trait_def_id,
                         method_num: method_num,
                         real_index: real_index,
@@ -254,9 +250,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                 // parameters from the trait ([$A,$B]), not those from
                 // the impl ([$A,$B,$C]) not the receiver type ([$C]).
                 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
-                let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id)
-                                     .unwrap()
-                                     .subst(self.tcx(), &impl_polytype.substs);
+                let impl_trait_ref =
+                    self.fcx.instantiate_type_scheme(
+                        self.span,
+                        &impl_polytype.substs,
+                        &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
                 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
                                                            method_num: method_num });
                 (impl_trait_ref.substs.clone(), origin)
@@ -284,9 +282,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             probe::WhereClausePick(ref poly_trait_ref, method_num) => {
                 // Where clauses can have bound regions in them. We need to instantiate
                 // those to convert from a poly-trait-ref to a trait-ref.
-                let trait_ref = self.replace_late_bound_regions_with_fresh_var(&**poly_trait_ref);
+                let trait_ref = self.replace_late_bound_regions_with_fresh_var(&*poly_trait_ref);
                 let substs = trait_ref.substs.clone();
-                let origin = MethodTypeParam(MethodParam { trait_ref: Rc::new(trait_ref),
+                let origin = MethodTypeParam(MethodParam { trait_ref: trait_ref,
                                                            method_num: method_num });
                 (substs, origin)
             }
@@ -342,7 +340,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             } else if num_supplied_types != num_method_types {
                 span_err!(self.tcx().sess, self.span, E0036,
                     "incorrect number of type parameters given for this method");
-                Vec::from_elem(num_method_types, ty::mk_err())
+                repeat(self.tcx().types.err).take(num_method_types).collect()
             } else {
                 supplied_method_types
             }
@@ -400,52 +398,49 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         // type `Trait`, this leads to an obligation
         // `Trait:Trait`. Until such time we DST is fully implemented,
         // that obligation is not necessarily satisfied. (In the
-        // future, it would be.)
-        //
-        // To sidestep this, we overwrite the binding for `Self` with
-        // `err` (just for trait objects) when we generate the
-        // obligations.  This causes us to generate the obligation
-        // `err:Trait`, and the error type is considered to implement
-        // all traits, so we're all good. Hack hack hack.
-        let method_bounds_substs = match pick.kind {
+        // future, it would be.) But we know that the true `Self` DOES implement
+        // the trait. So we just delete this requirement. Hack hack hack.
+        let mut method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &all_substs);
+        match pick.kind {
             probe::ObjectPick(..) => {
-                let mut temp_substs = all_substs.clone();
-                temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = ty::mk_err();
-                temp_substs
+                assert_eq!(method_bounds.predicates.get_slice(subst::SelfSpace).len(), 1);
+                method_bounds.predicates.pop(subst::SelfSpace);
             }
-            _ => {
-                all_substs.clone()
-            }
-        };
-        let method_bounds = pick.method_ty.generics.to_bounds(self.tcx(), &method_bounds_substs);
+            _ => { }
+        }
+        let method_bounds = self.fcx.normalize_associated_types_in(self.span, &method_bounds);
 
         debug!("method_bounds after subst = {}",
                method_bounds.repr(self.tcx()));
 
-        // Substitute the type/early-bound-regions into the method
-        // signature. In addition, the method signature may bind
-        // late-bound regions, so instantiate those.
-        let method_sig = pick.method_ty.fty.sig.subst(self.tcx(), &all_substs);
-        let method_sig = self.replace_late_bound_regions_with_fresh_var(&method_sig);
-
+        // Instantiate late-bound regions and substitute the trait
+        // parameters into the method type to get the actual method type.
+        //
+        // NB: Instantiate late-bound regions first so that
+        // `instantiate_type_scheme` can normalize associated types that
+        // may reference those regions.
+        let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.method_ty.fty.sig);
         debug!("late-bound lifetimes from method instantiated, method_sig={}",
                method_sig.repr(self.tcx()));
 
+        let method_sig = self.fcx.instantiate_type_scheme(self.span, &all_substs, &method_sig);
+        debug!("type scheme substituted, method_sig={}",
+               method_sig.repr(self.tcx()));
+
         InstantiatedMethodSig {
             method_sig: method_sig,
             all_substs: all_substs,
-            method_bounds_substs: method_bounds_substs,
             method_bounds: method_bounds,
         }
     }
 
     fn add_obligations(&mut self,
                        pick: &probe::Pick<'tcx>,
-                       method_bounds_substs: &subst::Substs<'tcx>,
+                       all_substs: &subst::Substs<'tcx>,
                        method_bounds: &ty::GenericBounds<'tcx>) {
-        debug!("add_obligations: pick={} method_bounds_substs={} method_bounds={}",
+        debug!("add_obligations: pick={} all_substs={} method_bounds={}",
                pick.repr(self.tcx()),
-               method_bounds_substs.repr(self.tcx()),
+               all_substs.repr(self.tcx()),
                method_bounds.repr(self.tcx()));
 
         self.fcx.add_obligations_for_parameters(
@@ -453,7 +448,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             method_bounds);
 
         self.fcx.add_default_region_param_bounds(
-            method_bounds_substs,
+            all_substs,
             self.call_expr);
     }
 
@@ -488,7 +483,6 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                 ast::ExprParen(ref expr) |
                 ast::ExprField(ref expr, _) |
                 ast::ExprTupField(ref expr, _) |
-                ast::ExprSlice(ref expr, _, _, _) |
                 ast::ExprIndex(ref expr, _) |
                 ast::ExprUnary(ast::UnDeref, ref expr) => exprs.push(&**expr),
                 _ => break,
@@ -534,7 +528,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             // Don't retry the first one or we might infinite loop!
             if i != 0 {
                 match expr.node {
-                    ast::ExprIndex(ref base_expr, _) => {
+                    ast::ExprIndex(ref base_expr, ref index_expr) => {
                         let mut base_adjustment =
                             match self.fcx.inh.adjustments.borrow().get(&base_expr.id) {
                                 Some(&ty::AdjustDerefRef(ref adr)) => (*adr).clone(),
@@ -570,7 +564,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                                 &**base_expr,
                                 Some(&ty::AdjustDerefRef(base_adjustment.clone())));
 
-                        check::try_index_step(
+                        let result = check::try_index_step(
                             self.fcx,
                             MethodCall::expr(expr.id),
                             *expr,
@@ -578,6 +572,14 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                             adjusted_base_ty,
                             base_adjustment,
                             PreferMutLvalue);
+
+                        if let Some((input_ty, return_ty)) = result {
+                            let index_expr_ty = self.fcx.expr_ty(&**index_expr);
+                            demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
+
+                            let expr_ty = self.fcx.expr_ty(&**expr);
+                            demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
+                        }
                     }
                     ast::ExprUnary(ast::UnDeref, ref base_expr) => {
                         // if this is an overloaded deref, then re-evaluate with
@@ -627,9 +629,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     }
 
     fn upcast(&mut self,
-              source_trait_ref: Rc<ty::PolyTraitRef<'tcx>>,
+              source_trait_ref: ty::PolyTraitRef<'tcx>,
               target_trait_def_id: ast::DefId)
-              -> Rc<ty::PolyTraitRef<'tcx>>
+              -> ty::PolyTraitRef<'tcx>
     {
         for super_trait_ref in traits::supertraits(self.tcx(), source_trait_ref.clone()) {
             if super_trait_ref.def_id() == target_trait_def_id {
diff --git a/src/librustc_typeck/check/method/doc.rs b/src/librustc_typeck/check/method/doc.rs
index 6129e38e39c..d748266ed2e 100644
--- a/src/librustc_typeck/check/method/doc.rs
+++ b/src/librustc_typeck/check/method/doc.rs
@@ -53,12 +53,12 @@
 //! The first thing that the probe phase does is to create a series of
 //! *steps*. This is done by progressively dereferencing the receiver type
 //! until it cannot be deref'd anymore, as well as applying an optional
-//! "unsize" step. So if the receiver has type `Rc<Box<[T, ..3]>>`, this
+//! "unsize" step. So if the receiver has type `Rc<Box<[T; 3]>>`, this
 //! might yield:
 //!
-//!     Rc<Box<[T, ..3]>>
-//!     Box<[T, ..3]>
-//!     [T, ..3]
+//!     Rc<Box<[T; 3]>>
+//!     Box<[T; 3]>
+//!     [T; 3]
 //!     [T]
 //!
 //! ### Candidate assembly
@@ -96,13 +96,13 @@
 //! method.
 //!
 //! So, let's continue our example. Imagine that we were calling a method
-//! `foo` with the receiver `Rc<Box<[T, ..3]>>` and there is a trait `Foo`
+//! `foo` with the receiver `Rc<Box<[T; 3]>>` and there is a trait `Foo`
 //! that defines it with `&self` for the type `Rc<U>` as well as a method
 //! on the type `Box` that defines `Foo` but with `&mut self`. Then we
 //! might have two candidates:
 //!
-//!     &Rc<Box<[T, ..3]>> from the impl of `Foo` for `Rc<U>` where `U=Box<T, ..3]>
-//!     &mut Box<[T, ..3]>> from the inherent impl on `Box<U>` where `U=[T, ..3]`
+//!     &Rc<Box<[T; 3]>> from the impl of `Foo` for `Rc<U>` where `U=Box<T; 3]>
+//!     &mut Box<[T; 3]>> from the inherent impl on `Box<U>` where `U=[T; 3]`
 //!
 //! ### Candidate search
 //!
@@ -112,9 +112,9 @@
 //! that makes any of the candidates match. We pick the first step where
 //! we find a match.
 //!
-//! In the case of our example, the first step is `Rc<Box<[T, ..3]>>`,
+//! In the case of our example, the first step is `Rc<Box<[T; 3]>>`,
 //! which does not itself match any candidate. But when we autoref it, we
-//! get the type `&Rc<Box<[T, ..3]>>` which does match. We would then
+//! get the type `&Rc<Box<[T; 3]>>` which does match. We would then
 //! recursively consider all where-clauses that appear on the impl: if
 //! those match (or we cannot rule out that they do), then this is the
 //! method we would pick. Otherwise, we would continue down the series of
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 0c094823a75..4e6593deddd 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -16,7 +16,6 @@ use check::{impl_self_ty};
 use check::vtable;
 use check::vtable::select_new_fcx_obligations;
 use middle::subst;
-use middle::subst::{Subst};
 use middle::traits;
 use middle::ty::*;
 use middle::ty;
@@ -156,18 +155,15 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
         }
     };
 
-    let number_assoc_types = trait_def.generics.types.len(subst::AssocSpace);
-    let assoc_types = fcx.inh.infcx.next_ty_vars(number_assoc_types);
-
     assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
     assert!(trait_def.generics.regions.is_empty());
 
     // Construct a trait-reference `self_ty : Trait<input_tys>`
-    let substs = subst::Substs::new_trait(input_types, Vec::new(), assoc_types, self_ty);
+    let substs = subst::Substs::new_trait(input_types, Vec::new(), self_ty);
     let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, fcx.tcx().mk_substs(substs)));
 
     // Construct an obligation
-    let poly_trait_ref = Rc::new(ty::Binder((*trait_ref).clone()));
+    let poly_trait_ref = trait_ref.to_poly_trait_ref();
     let obligation = traits::Obligation::misc(span,
                                               fcx.body_id,
                                               poly_trait_ref.as_predicate());
@@ -191,18 +187,21 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
     debug!("lookup_in_trait_adjusted: method_num={} method_ty={}",
            method_num, method_ty.repr(fcx.tcx()));
 
-    // Substitute the trait parameters into the method type and
-    // instantiate late-bound regions to get the actual method type.
-    let ref bare_fn_ty = method_ty.fty;
-    let fn_sig = bare_fn_ty.sig.subst(tcx, trait_ref.substs);
+    // Instantiate late-bound regions and substitute the trait
+    // parameters into the method type to get the actual method type.
+    //
+    // NB: Instantiate late-bound regions first so that
+    // `instantiate_type_scheme` can normalize associated types that
+    // may reference those regions.
     let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span,
                                                                        infer::FnCall,
-                                                                       &fn_sig).0;
+                                                                       &method_ty.fty.sig).0;
+    let fn_sig = fcx.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
     let transformed_self_ty = fn_sig.inputs[0];
     let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
         sig: ty::Binder(fn_sig),
-        unsafety: bare_fn_ty.unsafety,
-        abi: bare_fn_ty.abi.clone(),
+        unsafety: method_ty.fty.unsafety,
+        abi: method_ty.fty.abi.clone(),
     }));
 
     debug!("lookup_in_trait_adjusted: matched method fty={} obligation={}",
@@ -217,7 +216,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
     //
     // Note that as the method comes from a trait, it should not have
     // any late-bound regions appearing in its bounds.
-    let method_bounds = method_ty.generics.to_bounds(fcx.tcx(), trait_ref.substs);
+    let method_bounds = fcx.instantiate_bounds(span, trait_ref.substs, &method_ty.generics);
     assert!(!method_bounds.has_escaping_regions());
     fcx.add_obligations_for_parameters(
         traits::ObligationCause::misc(span, fcx.body_id),
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 3ecd2007ff1..f00e3e2d452 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -18,7 +18,7 @@ use middle::fast_reject;
 use middle::subst;
 use middle::subst::Subst;
 use middle::traits;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, Ty, ToPolyTraitRef};
 use middle::ty_fold::TypeFoldable;
 use middle::infer;
 use middle::infer::InferCtxt;
@@ -61,7 +61,7 @@ enum CandidateKind<'tcx> {
     ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::TraitRef<'tcx>>,
                            subst::Substs<'tcx>, MethodIndex),
     UnboxedClosureCandidate(/* Trait */ ast::DefId, MethodIndex),
-    WhereClauseCandidate(Rc<ty::PolyTraitRef<'tcx>>, MethodIndex),
+    WhereClauseCandidate(ty::PolyTraitRef<'tcx>, MethodIndex),
 }
 
 pub struct Pick<'tcx> {
@@ -76,7 +76,7 @@ pub enum PickKind<'tcx> {
     ObjectPick(/* Trait */ ast::DefId, /* method_num */ uint, /* real_index */ uint),
     ExtensionImplPick(/* Impl */ ast::DefId, MethodIndex),
     TraitPick(/* Trait */ ast::DefId, MethodIndex),
-    WhereClausePick(/* Trait */ Rc<ty::PolyTraitRef<'tcx>>, MethodIndex),
+    WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, MethodIndex),
 }
 
 pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError>;
@@ -235,7 +235,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         match self_ty.sty {
             ty::ty_trait(box ref data) => {
                 self.assemble_inherent_candidates_from_object(self_ty, data);
-                self.assemble_inherent_impl_candidates_for_type(data.principal.def_id());
+                self.assemble_inherent_impl_candidates_for_type(data.principal_def_id());
             }
             ty::ty_enum(did, _) |
             ty::ty_struct(did, _) |
@@ -308,7 +308,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
         self.elaborate_bounds(&[trait_ref.clone()], false, |this, new_trait_ref, m, method_num| {
             let vtable_index =
-                get_method_index(tcx, &*new_trait_ref, trait_ref.clone(), method_num);
+                get_method_index(tcx, &new_trait_ref, trait_ref.clone(), method_num);
 
             let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs());
 
@@ -330,13 +330,16 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             .iter()
             .filter_map(|predicate| {
                 match *predicate {
-                    ty::Predicate::Trait(ref trait_ref) => {
-                        match trait_ref.self_ty().sty {
-                            ty::ty_param(ref p) if *p == param_ty => Some(trait_ref.clone()),
+                    ty::Predicate::Trait(ref trait_predicate) => {
+                        match trait_predicate.0.trait_ref.self_ty().sty {
+                            ty::ty_param(ref p) if *p == param_ty => {
+                                Some(trait_predicate.to_poly_trait_ref())
+                            }
                             _ => None
                         }
                     }
                     ty::Predicate::Equate(..) |
+                    ty::Predicate::Projection(..) |
                     ty::Predicate::RegionOutlives(..) |
                     ty::Predicate::TypeOutlives(..) => {
                         None
@@ -381,10 +384,10 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     // create the candidates.
     fn elaborate_bounds(
         &mut self,
-        bounds: &[Rc<ty::PolyTraitRef<'tcx>>],
+        bounds: &[ty::PolyTraitRef<'tcx>],
         num_includes_types: bool,
         mk_cand: for<'b> |this: &mut ProbeContext<'b, 'tcx>,
-                          tr: Rc<ty::PolyTraitRef<'tcx>>,
+                          tr: ty::PolyTraitRef<'tcx>,
                           m: Rc<ty::Method<'tcx>>,
                           method_num: uint|)
     {
@@ -765,6 +768,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                     // Check whether the impl imposes obligations we have to worry about.
                     let impl_generics = ty::lookup_item_type(self.tcx(), impl_def_id).generics;
                     let impl_bounds = impl_generics.to_bounds(self.tcx(), substs);
+                    // FIXME(#20378) assoc type normalization here?
 
                     // Erase any late-bound regions bound in the impl
                     // which appear in the bounds.
@@ -996,7 +1000,7 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
 // to a trait and its supertraits.
 fn get_method_index<'tcx>(tcx: &ty::ctxt<'tcx>,
                           trait_ref: &ty::PolyTraitRef<'tcx>,
-                          subtrait: Rc<ty::PolyTraitRef<'tcx>>,
+                          subtrait: ty::PolyTraitRef<'tcx>,
                           n_method: uint) -> uint {
     // We need to figure the "real index" of the method in a
     // listing of all the methods of an object. We do this by
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 68cf139338a..d4e025a3813 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -91,12 +91,12 @@ use middle::pat_util::{mod, pat_id_map};
 use middle::region::CodeExtent;
 use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace};
 use middle::traits;
-use middle::ty::{FnSig, VariantInfo, Polytype};
+use middle::ty::{FnSig, VariantInfo, TypeScheme};
 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, HasProjectionTypes, RegionEscape, Ty};
 use middle::ty::liberate_late_bound_regions;
 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
-use middle::ty_fold::TypeFolder;
+use middle::ty_fold::{TypeFolder, TypeFoldable};
 use rscope::RegionScope;
 use session::Session;
 use {CrateCtxt, lookup_def_ccx, no_params, require_same_types};
@@ -110,6 +110,7 @@ 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 syntax::{mod, abi, attr};
 use syntax::ast::{mod, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
 use syntax::ast_util::{mod, local_def, PostExpansionMethod};
@@ -120,6 +121,7 @@ use syntax::print::pprust;
 use syntax::ptr::P;
 use syntax::visit::{mod, Visitor};
 
+mod assoc;
 pub mod _match;
 pub mod vtable;
 pub mod writeback;
@@ -317,15 +319,37 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
         self.tcx().temporary_scope(rvalue_id)
     }
-    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
-        self.inh.upvar_borrow_map.borrow()[upvar_id].clone()
+    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
+        self.inh.upvar_borrow_map.borrow().get(&upvar_id).cloned()
     }
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
                     -> ast::CaptureClause {
         self.ccx.tcx.capture_mode(closure_expr_id)
     }
-    fn unboxed_closures(&self) -> &RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
-        &self.inh.unboxed_closures
+}
+
+impl<'a, 'tcx> ty::UnboxedClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
+    fn unboxed_closure_kind(&self,
+                            def_id: ast::DefId)
+                            -> ty::UnboxedClosureKind
+    {
+        self.inh.unboxed_closures.borrow()[def_id].kind
+    }
+
+    fn unboxed_closure_type(&self,
+                            def_id: ast::DefId,
+                            substs: &subst::Substs<'tcx>)
+                            -> ty::ClosureTy<'tcx>
+    {
+        self.inh.unboxed_closures.borrow()[def_id].closure_type.subst(self.tcx(), substs)
+    }
+
+    fn unboxed_closure_upvars(&self,
+                              def_id: ast::DefId,
+                              substs: &Substs<'tcx>)
+                              -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
+    {
+        ty::unboxed_closure_upvars(self, def_id, substs)
     }
 }
 
@@ -348,6 +372,24 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
             fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
         }
     }
+
+    fn normalize_associated_types_in<T>(&self,
+                                        typer: &ty::UnboxedClosureTyper<'tcx>,
+                                        span: Span,
+                                        body_id: ast::NodeId,
+                                        value: &T)
+                                        -> T
+        where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
+    {
+        let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
+        assoc::normalize_associated_types_in(&self.infcx,
+                                             &self.param_env,
+                                             typer,
+                                             &mut *fulfillment_cx, span,
+                                             body_id,
+                                             value)
+    }
+
 }
 
 // Used by check_const and check_enum_variants
@@ -386,7 +428,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, t: &ast::Ty) {
         match t.node {
             ast::TyFixedLengthVec(_, ref expr) => {
-                check_const_in_type(self.ccx, &**expr, ty::mk_uint());
+                check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
             }
             _ => {}
         }
@@ -414,21 +456,25 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            decl: &ast::FnDecl,
                            body: &ast::Block,
                            id: ast::NodeId,
-                           fty: Ty<'tcx>,
+                           raw_fty: Ty<'tcx>,
                            param_env: ty::ParameterEnvironment<'tcx>) {
-    // Compute the fty from point of view of inside fn
-    // (replace any type-scheme with a type)
-    let fty = fty.subst(ccx.tcx, &param_env.free_substs);
-
-    match fty.sty {
+    match raw_fty.sty {
         ty::ty_bare_fn(_, ref fn_ty) => {
             let inh = Inherited::new(ccx.tcx, param_env);
-            let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig,
+
+            // Compute the fty from point of view of inside fn.
+            let fn_sig =
+                fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
+            let fn_sig =
+                liberate_late_bound_regions(ccx.tcx, CodeExtent::from_node_id(body.id), &fn_sig);
+            let fn_sig =
+                inh.normalize_associated_types_in(ccx.tcx, body.span, body.id, &fn_sig);
+
+            let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig,
                                decl, id, body, &inh);
 
             vtable::select_all_fcx_obligations_or_error(&fcx);
             regionck::regionck_fn(&fcx, id, decl, body);
-            fcx.default_diverging_type_variables_to_nil();
             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
         _ => ccx.tcx.sess.impossible_case(body.span,
@@ -505,7 +551,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
         match t.node {
             ast::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&**ty);
-                check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
+                check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
             }
             _ => visit::walk_ty(self, t)
         }
@@ -527,19 +573,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
                       unsafety: ast::Unsafety,
                       unsafety_id: ast::NodeId,
-                      fn_sig: &ty::PolyFnSig<'tcx>,
+                      fn_sig: &ty::FnSig<'tcx>,
                       decl: &ast::FnDecl,
                       fn_id: ast::NodeId,
                       body: &ast::Block,
                       inherited: &'a Inherited<'a, 'tcx>)
-                      -> FnCtxt<'a, 'tcx> {
+                      -> FnCtxt<'a, 'tcx>
+{
     let tcx = ccx.tcx;
     let err_count_on_creation = tcx.sess.err_count();
 
-    // First, we have to replace any bound regions in the fn type with free ones.
-    // The free region references will be bound the node_id of the body block.
-    let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig);
-
     let arg_tys = fn_sig.inputs[];
     let ret_ty = fn_sig.output;
 
@@ -673,7 +716,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         }
 
       }
-      ast::ItemTrait(_, _, _, _, ref trait_methods) => {
+      ast::ItemTrait(_, _, _, ref trait_methods) => {
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_method in trait_methods.iter() {
             match *trait_method {
@@ -771,9 +814,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 // corresponding method definition in the trait.
                 let opt_trait_method_ty =
                     trait_items.iter()
-                               .find(|ti| {
-                                   ti.name() == impl_item_ty.name()
-                               });
+                               .find(|ti| ti.name() == impl_item_ty.name());
                 match opt_trait_method_ty {
                     Some(trait_method_ty) => {
                         match (trait_method_ty, &impl_item_ty) {
@@ -917,6 +958,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
            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;
 
@@ -1034,21 +1076,15 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     // this kind of equivalency just fine.
 
     // Create mapping from impl to skolemized.
-    let skol_tps =
-        impl_m.generics.types.map(
-            |d| ty::mk_param_from_def(tcx, d));
-    let skol_regions =
-        impl_m.generics.regions.map(
-            |l| ty::free_region_from_def(impl_m_body_id, l));
-    let impl_to_skol_substs =
-        subst::Substs::new(skol_tps.clone(), skol_regions.clone());
+    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(skol_tps.get_slice(subst::FnSpace).to_vec(),
-                     skol_regions.get_slice(subst::FnSpace).to_vec());
+        .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,
@@ -1057,7 +1093,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                            &trait_m.generics,
                                            &impl_m.generics,
                                            &trait_to_skol_substs,
-                                           &impl_to_skol_substs) {
+                                           impl_to_skol_substs) {
         return;
     }
 
@@ -1120,7 +1156,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         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);
+                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
@@ -1134,7 +1170,6 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                     debug!("compare_impl_method(): trait-bound subst");
                     let trait_bound =
                         trait_bound.subst(tcx, &trait_to_skol_substs);
-                    let infcx = infer::new_infer_ctxt(tcx);
                     infer::mk_sub_poly_trait_refs(&infcx,
                                                   true,
                                                   infer::Misc(impl_m_span),
@@ -1153,33 +1188,99 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'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 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);
 
-    // Check the impl method type IM is a subtype of the trait method
-    // type TM. To see why this makes sense, think of a vtable. The
-    // expected type of the function pointers in the vtable is the
-    // type TM of the trait method.  The actual type will be the type
-    // IM of the impl method. Because we know that IM <: TM, that
-    // means that anywhere a TM is expected, a IM will do instead. In
-    // other words, anyone expecting to call a method with the type
-    // from the trait, can safely call a method with the type from the
-    // impl instead.
-    debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
-           impl_fty.repr(tcx),
-           trait_fty.repr(tcx));
-    match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
-                          impl_fty, trait_fty) {
-        Ok(()) => {}
-        Err(ref terr) => {
+    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,
+                                                 infcx.tcx,
+                                                 &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,
+                                                 infcx.tcx,
+                                                 &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));
-            ty::note_and_explain_type_err(tcx, terr);
+                      "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, tcx) {
+        Ok(()) => { }
+        Err(errors) => {
+            traits::report_fulfillment_errors(&infcx, &errors);
         }
     }
 
@@ -1356,7 +1457,7 @@ fn check_cast(fcx: &FnCtxt,
         return
     }
 
-    if !ty::type_is_sized(fcx.tcx(), t_1) {
+    if !fcx.type_is_known_to_be_sized(t_1) {
         let tstr = fcx.infcx().ty_to_string(t_1);
         fcx.type_error_message(span, |actual| {
             format!("cast to unsized type: `{}` as `{}`", actual, tstr)
@@ -1510,7 +1611,7 @@ fn check_cast(fcx: &FnCtxt,
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
 
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
+    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
         ty::lookup_item_type(self.tcx(), id)
     }
 
@@ -1526,29 +1627,42 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
         self.infcx().next_ty_var()
     }
 
-    fn associated_types_of_trait_are_valid(&self, _: Ty, _: ast::DefId)
-                                           -> bool {
-        false
+    fn projected_ty_from_poly_trait_ref(&self,
+                                        span: Span,
+                                        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+                                        item_name: ast::Name)
+                                        -> Ty<'tcx>
+    {
+        let (trait_ref, _) =
+            self.infcx().replace_late_bound_regions_with_fresh_var(
+                span,
+                infer::LateBoundRegionConversionTime::AssocTypeProjection(item_name),
+                &poly_trait_ref);
+
+        self.normalize_associated_type(span, trait_ref, item_name)
     }
 
-    fn associated_type_binding(&self,
-                               span: Span,
-                               _: Option<Ty<'tcx>>,
-                               _: ast::DefId,
-                               _: ast::DefId)
-                               -> Option<Ty<'tcx>> {
-        self.tcx().sess.span_err(span, "unsupported associated type binding");
-        Some(ty::mk_err())
+    fn projected_ty(&self,
+                    span: Span,
+                    trait_ref: Rc<ty::TraitRef<'tcx>>,
+                    item_name: ast::Name)
+                    -> Ty<'tcx>
+    {
+        self.normalize_associated_type(span, trait_ref, item_name)
     }
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
 
-    pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a, 'tcx> {
+    pub fn infcx(&self) -> &infer::InferCtxt<'a, 'tcx> {
         &self.inh.infcx
     }
 
+    pub fn param_env(&self) -> &ty::ParameterEnvironment<'tcx> {
+        &self.inh.param_env
+    }
+
     pub fn sess(&self) -> &Session {
         &self.tcx().sess
     }
@@ -1556,22 +1670,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn err_count_since_creation(&self) -> uint {
         self.ccx.tcx.sess.err_count() - self.err_count_on_creation
     }
-}
-
-impl<'a, 'tcx> RegionScope for infer::InferCtxt<'a, 'tcx> {
-    fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
-        Some(self.next_region_var(infer::MiscVariable(span)))
-    }
-
-    fn anon_regions(&self, span: Span, count: uint)
-                    -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
-        Ok(Vec::from_fn(count, |_| {
-            self.next_region_var(infer::MiscVariable(span))
-        }))
-    }
-}
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn tag(&self) -> String {
         format!("{}", self as *const FnCtxt)
     }
@@ -1588,10 +1687,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn default_diverging_type_variables_to_nil(&self) {
+    /// Apply "fallbacks" to some types
+    /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
+    pub fn default_type_parameters(&self) {
+        use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
         for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
-            if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(ty)) {
+            let resolved = self.infcx().resolve_type_vars_if_possible(ty);
+            if self.infcx().type_var_diverges(resolved) {
                 demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
+            } else {
+                match self.infcx().type_is_unconstrained_numeric(resolved) {
+                    UnconstrainedInt => {
+                        demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
+                    },
+                    UnconstrainedFloat => {
+                        demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
+                    }
+                    Neither => { }
+                }
             }
         }
     }
@@ -1605,7 +1718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn write_object_cast(&self,
                              key: ast::NodeId,
-                             trait_ref: Rc<ty::PolyTraitRef<'tcx>>) {
+                             trait_ref: ty::PolyTraitRef<'tcx>) {
         debug!("write_object_cast key={} trait_ref={}",
                key, trait_ref.repr(self.tcx()));
         self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
@@ -1656,6 +1769,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.inh.adjustments.borrow_mut().insert(node_id, adj);
     }
 
+    /// Basically whenever we are converting from a type scheme into
+    /// the fn body space, we always want to normalize associated
+    /// types as well. This function combines the two.
+    fn instantiate_type_scheme<T>(&self,
+                                  span: Span,
+                                  substs: &Substs<'tcx>,
+                                  value: &T)
+                                  -> T
+        where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
+    {
+        let value = value.subst(self.tcx(), substs);
+        let result = self.normalize_associated_types_in(span, &value);
+        debug!("instantiate_type_scheme(value={}, substs={}) = {}",
+               value.repr(self.tcx()),
+               substs.repr(self.tcx()),
+               result.repr(self.tcx()));
+        result
+    }
+
+    /// As `instantiate_type_scheme`, but for the bounds found in a
+    /// generic type scheme.
+    fn instantiate_bounds(&self,
+                          span: Span,
+                          substs: &Substs<'tcx>,
+                          generics: &ty::Generics<'tcx>)
+                          -> ty::GenericBounds<'tcx>
+    {
+        ty::GenericBounds {
+            predicates: self.instantiate_type_scheme(span, substs, &generics.predicates)
+        }
+    }
+
+
+    fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
+        where T : TypeFoldable<'tcx> + Clone + HasProjectionTypes + Repr<'tcx>
+    {
+        self.inh.normalize_associated_types_in(self, span, self.body_id, value)
+    }
+
+    fn normalize_associated_type(&self,
+                                 span: Span,
+                                 trait_ref: Rc<ty::TraitRef<'tcx>>,
+                                 item_name: ast::Name)
+                                 -> Ty<'tcx>
+    {
+        let cause = traits::ObligationCause::new(span,
+                                                 self.body_id,
+                                                 traits::ObligationCauseCode::MiscObligation);
+        self.inh.fulfillment_cx
+            .borrow_mut()
+            .normalize_projection_type(self.infcx(),
+                                       &self.inh.param_env,
+                                       self,
+                                       ty::ProjectionTy {
+                                           trait_ref: trait_ref,
+                                           item_name: item_name,
+                                       },
+                                       cause)
+    }
+
     fn register_adjustment_obligations(&self,
                                        span: Span,
                                        adj: &ty::AutoAdjustment<'tcx>) {
@@ -1728,21 +1901,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Also returns the substitution from the type parameters on `def_id` to the fresh variables.
     /// Registers any trait obligations specified on `def_id` at the same time.
     ///
-    /// Note that function is only intended to be used with types (notably, not impls). This is
+    /// Note that function is only intended to be used with types (notably, not fns). This is
     /// because it doesn't do any instantiation of late-bound regions.
     pub fn instantiate_type(&self,
                             span: Span,
                             def_id: ast::DefId)
                             -> TypeAndSubsts<'tcx>
     {
-        let polytype =
+        let type_scheme =
             ty::lookup_item_type(self.tcx(), def_id);
         let substs =
             self.infcx().fresh_substs_for_generics(
                 span,
-                &polytype.generics);
+                &type_scheme.generics);
         let bounds =
-            polytype.generics.to_bounds(self.tcx(), &substs);
+            self.instantiate_bounds(span, &substs, &type_scheme.generics);
         self.add_obligations_for_parameters(
             traits::ObligationCause::new(
                 span,
@@ -1750,7 +1923,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 traits::ItemObligation(def_id)),
             &bounds);
         let monotype =
-            polytype.ty.subst(self.tcx(), &substs);
+            self.instantiate_type_scheme(span, &substs, &type_scheme.ty);
 
         TypeAndSubsts {
             ty: monotype,
@@ -1762,7 +1935,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.write_ty(node_id, ty::mk_nil(self.tcx()));
     }
     pub fn write_error(&self, node_id: ast::NodeId) {
-        self.write_ty(node_id, ty::mk_err());
+        self.write_ty(node_id, self.tcx().types.err);
     }
 
     pub fn require_type_meets(&self,
@@ -1792,13 +1965,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
     }
 
+    pub fn type_is_known_to_be_sized(&self,
+                                     ty: Ty<'tcx>)
+                                     -> bool
+    {
+        traits::type_known_to_meet_builtin_bound(self.infcx(),
+                                                 self.param_env(),
+                                                 ty,
+                                                 ty::BoundSized)
+    }
+
     pub fn register_builtin_bound(&self,
                                   ty: Ty<'tcx>,
                                   builtin_bound: ty::BuiltinBound,
                                   cause: traits::ObligationCause<'tcx>)
     {
         self.inh.fulfillment_cx.borrow_mut()
-            .register_builtin_bound(self.tcx(), ty, builtin_bound, cause);
+            .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
     }
 
     pub fn register_predicate(&self,
@@ -1809,11 +1992,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.inh.fulfillment_cx
             .borrow_mut()
-            .register_predicate(self.tcx(), obligation);
+            .register_predicate_obligation(self.infcx(), obligation);
     }
 
     pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
-        let t = ast_ty_to_ty(self, self.infcx(), ast_t);
+        let t = ast_ty_to_ty(self, self, ast_t);
 
         let mut bounds_checker = wf::BoundsChecker::new(self,
                                                         ast_t.span,
@@ -1953,7 +2136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                       cause: traits::ObligationCause<'tcx>)
     {
         let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
-        fulfillment_cx.register_region_obligation(self.tcx(), ty, region, cause);
+        fulfillment_cx.register_region_obligation(self.infcx(), ty, region, cause);
     }
 
     pub fn add_default_region_param_bounds(&self,
@@ -2003,7 +2186,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 }
 
-#[deriving(Copy, Show)]
+impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
+    fn default_region_bound(&self, span: Span) -> Option<ty::Region> {
+        Some(self.infcx().next_region_var(infer::MiscVariable(span)))
+    }
+
+    fn anon_regions(&self, span: Span, count: uint)
+                    -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
+        Ok(range(0, count).map(|_| {
+            self.infcx().next_region_var(infer::MiscVariable(span))
+        }).collect())
+    }
+}
+
+#[deriving(Copy, Show, PartialEq, Eq)]
 pub enum LvaluePreference {
     PreferMutLvalue,
     NoPreference
@@ -2058,7 +2254,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     span_err!(fcx.tcx().sess, sp, E0055,
         "reached the recursion limit while auto-dereferencing {}",
         base_ty.repr(fcx.tcx()));
-    (ty::mk_err(), 0, None)
+    (fcx.tcx().types.err, 0, None)
 }
 
 /// Attempts to resolve a call expression as an overloaded call.
@@ -2214,58 +2410,6 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
     }
 }
 
-/// Autoderefs `base_expr`, looking for a `Slice` impl. If it finds one, installs the relevant
-/// method info and returns the result type (else None).
-fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                  method_call: MethodCall,
-                                  expr: &ast::Expr,
-                                  base_expr: &ast::Expr,
-                                  base_ty: Ty<'tcx>,
-                                  start_expr: &Option<P<ast::Expr>>,
-                                  end_expr: &Option<P<ast::Expr>>,
-                                  mutbl: ast::Mutability)
-                                  -> Option<Ty<'tcx>> // return type is result of slice
-{
-    let lvalue_pref = match mutbl {
-        ast::MutMutable => PreferMutLvalue,
-        ast::MutImmutable => NoPreference
-    };
-
-    let opt_method_ty =
-        autoderef_for_index(fcx, base_expr, base_ty, lvalue_pref, |adjusted_ty, autoderefref| {
-            try_overloaded_slice_step(fcx, method_call, expr, base_expr,
-                                      adjusted_ty, autoderefref, mutbl,
-                                      start_expr, end_expr)
-        });
-
-    // Regardless of whether the lookup succeeds, check the method arguments
-    // so that we have *some* type for each argument.
-    let method_ty_or_err = opt_method_ty.unwrap_or(ty::mk_err());
-
-    let mut args = vec![];
-    start_expr.as_ref().map(|x| args.push(x));
-    end_expr.as_ref().map(|x| args.push(x));
-
-    check_method_argument_types(fcx,
-                                expr.span,
-                                method_ty_or_err,
-                                expr,
-                                args.as_slice(),
-                                AutorefArgs::Yes,
-                                DontTupleArguments);
-
-    opt_method_ty.map(|method_ty| {
-        let result_ty = ty::ty_fn_ret(method_ty);
-        match result_ty {
-            ty::FnConverging(result_ty) => result_ty,
-            ty::FnDiverging => {
-                fcx.tcx().sess.span_bug(expr.span,
-                                        "slice trait does not define a `!` return")
-            }
-        }
-    })
-}
-
 /// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one,
 /// installs method info and returns type of method (else None).
 fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@@ -2274,65 +2418,79 @@ fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                        base_expr: &ast::Expr,
                                        base_ty: Ty<'tcx>, // autoderef'd type
                                        autoderefref: ty::AutoDerefRef<'tcx>,
-                                       mutbl: ast::Mutability,
+                                       lvalue_pref: LvaluePreference,
                                        start_expr: &Option<P<ast::Expr>>,
                                        end_expr: &Option<P<ast::Expr>>)
-                                       // result type is type of method being called
-                                       -> Option<Ty<'tcx>>
+                                       -> Option<(Ty<'tcx>, /* index type */
+                                                  Ty<'tcx>)> /* return type */
 {
-    let method = if mutbl == ast::MutMutable {
-        // Try `SliceMut` first, if preferred.
-        match fcx.tcx().lang_items.slice_mut_trait() {
-            Some(trait_did) => {
-                let method_name = match (start_expr, end_expr) {
-                    (&Some(_), &Some(_)) => "slice_or_fail_mut",
-                    (&Some(_), &None) => "slice_from_or_fail_mut",
-                    (&None, &Some(_)) => "slice_to_or_fail_mut",
-                    (&None, &None) => "as_mut_slice_",
-                };
+    let input_ty = fcx.infcx().next_ty_var();
+    let return_ty = fcx.infcx().next_ty_var();
 
-                method::lookup_in_trait_adjusted(fcx,
-                                                 expr.span,
-                                                 Some(&*base_expr),
-                                                 token::intern(method_name),
-                                                 trait_did,
-                                                 autoderefref,
-                                                 base_ty,
-                                                 None)
+    let method = match lvalue_pref {
+        PreferMutLvalue => {
+            // Try `SliceMut` first, if preferred.
+            match fcx.tcx().lang_items.slice_mut_trait() {
+                Some(trait_did) => {
+                    let method_name = match (start_expr, end_expr) {
+                        (&Some(_), &Some(_)) => "slice_or_fail_mut",
+                        (&Some(_), &None) => "slice_from_or_fail_mut",
+                        (&None, &Some(_)) => "slice_to_or_fail_mut",
+                        (&None, &None) => "as_mut_slice_",
+                    };
+
+                    method::lookup_in_trait_adjusted(fcx,
+                                                     expr.span,
+                                                     Some(&*base_expr),
+                                                     token::intern(method_name),
+                                                     trait_did,
+                                                     autoderefref,
+                                                     base_ty,
+                                                     Some(vec![input_ty, return_ty]))
+                }
+                _ => None,
             }
-            _ => None,
         }
-    } else {
-        // Otherwise, fall back to `Slice`.
-        // FIXME(#17293) this will not coerce base_expr, so we miss the Slice
-        // trait for `&mut [T]`.
-        match fcx.tcx().lang_items.slice_trait() {
-            Some(trait_did) => {
-                let method_name = match (start_expr, end_expr) {
-                    (&Some(_), &Some(_)) => "slice_or_fail",
-                    (&Some(_), &None) => "slice_from_or_fail",
-                    (&None, &Some(_)) => "slice_to_or_fail",
-                    (&None, &None) => "as_slice_",
-                };
+        NoPreference => {
+            // Otherwise, fall back to `Slice`.
+            match fcx.tcx().lang_items.slice_trait() {
+                Some(trait_did) => {
+                    let method_name = match (start_expr, end_expr) {
+                        (&Some(_), &Some(_)) => "slice_or_fail",
+                        (&Some(_), &None) => "slice_from_or_fail",
+                        (&None, &Some(_)) => "slice_to_or_fail",
+                        (&None, &None) => "as_slice_",
+                    };
 
-                method::lookup_in_trait_adjusted(fcx,
-                                                 expr.span,
-                                                 Some(&*base_expr),
-                                                 token::intern(method_name),
-                                                 trait_did,
-                                                 autoderefref,
-                                                 base_ty,
-                                                 None)
+                    method::lookup_in_trait_adjusted(fcx,
+                                                     expr.span,
+                                                     Some(&*base_expr),
+                                                     token::intern(method_name),
+                                                     trait_did,
+                                                     autoderefref,
+                                                     base_ty,
+                                                     Some(vec![input_ty, return_ty]))
+                }
+                _ => None,
             }
-            _ => None,
         }
     };
 
     // If some lookup succeeded, install method in table
     method.map(|method| {
-        let ty = method.ty;
-        fcx.inh.method_map.borrow_mut().insert(method_call, method);
-        ty
+        let method_ty = method.ty;
+        make_overloaded_lvalue_return_type(fcx, Some(method_call), Some(method));
+
+        let result_ty = ty::ty_fn_ret(method_ty);
+        let result_ty = match result_ty {
+            ty::FnConverging(result_ty) => result_ty,
+            ty::FnDiverging => {
+                fcx.tcx().sess.span_bug(expr.span,
+                "slice trait does not define a `!` return")
+            }
+        };
+
+        (input_ty, result_ty)
     })
 }
 
@@ -2359,7 +2517,7 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match ty::index(adjusted_ty) {
         Some(ty) => {
             fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
-            return Some((ty::mk_uint(), ty));
+            return Some((fcx.tcx().types.uint, ty));
         }
 
         None => { }
@@ -2421,7 +2579,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         Err(ref err_string) => {
             fcx.tcx().sess.span_err(iterator_expr.span,
                                     err_string[]);
-            return ty::mk_err()
+            return fcx.tcx().types.err
         }
     };
 
@@ -2449,7 +2607,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                 maybe try .iter()",
                                                 ty_string)[]);
             }
-            ty::mk_err()
+            fcx.tcx().types.err
         }
     };
     let return_type = check_method_argument_types(fcx,
@@ -2470,7 +2628,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let return_type = match return_type {
                 ty::FnConverging(return_type) =>
                     structurally_resolved_type(fcx, iterator_expr.span, return_type),
-                ty::FnDiverging => ty::mk_err()
+                ty::FnDiverging => fcx.tcx().types.err
             };
             match return_type.sty {
                 ty::ty_enum(_, ref substs)
@@ -2478,7 +2636,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     *substs.types.get(subst::TypeSpace, 0)
                 }
                 ty::ty_err => {
-                    ty::mk_err()
+                    fcx.tcx().types.err
                 }
                 _ => {
                     fcx.tcx().sess.span_err(iterator_expr.span,
@@ -2486,11 +2644,11 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                     trait has an unexpected type `{}`",
                                                     fcx.infcx().ty_to_string(return_type))
                                             []);
-                    ty::mk_err()
+                    fcx.tcx().types.err
                 }
             }
         }
-        None => ty::mk_err()
+        None => fcx.tcx().types.err
     }
 }
 
@@ -2503,7 +2661,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          tuple_arguments: TupleArgumentsFlag)
                                          -> ty::FnOutput<'tcx> {
     if ty::type_is_error(method_fn_ty) {
-        let err_inputs = err_args(args_no_rcvr.len());
+        let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
 
         let err_inputs = match tuple_arguments {
             DontTupleArguments => err_inputs,
@@ -2518,7 +2676,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              autoref_args,
                              false,
                              tuple_arguments);
-        ty::FnConverging(ty::mk_err())
+        ty::FnConverging(fcx.tcx().types.err)
     } else {
         match method_fn_ty.sty {
             ty::ty_bare_fn(_, ref fty) => {
@@ -2573,7 +2731,7 @@ 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"});
-                    err_args(args.len())
+                    err_args(fcx.tcx(), args.len())
                 } else {
                     (*arg_types).clone()
                 }
@@ -2582,7 +2740,7 @@ 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");
-                err_args(args.len())
+                err_args(fcx.tcx(), args.len())
             }
         }
     } else if expected_arg_count == supplied_arg_count {
@@ -2598,7 +2756,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"});
-            err_args(supplied_arg_count)
+            err_args(fcx.tcx(), supplied_arg_count)
         }
     } else {
         span_err!(tcx.sess, sp, E0061,
@@ -2607,7 +2765,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"});
-        err_args(supplied_arg_count)
+        err_args(fcx.tcx(), supplied_arg_count)
     };
 
     debug!("check_argument_types: formal_tys={}",
@@ -2663,7 +2821,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                 // mismatch impl/trait method phase no need to
                                 // ICE here.
                                 // See: #11450
-                                formal_ty = ty::mk_err();
+                                formal_ty = tcx.types.err;
                             }
                         }
                     }
@@ -2714,8 +2872,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
-fn err_args<'tcx>(len: uint) -> Vec<Ty<'tcx>> {
-    Vec::from_fn(len, |_| ty::mk_err())
+fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
+    range(0, len).map(|_| tcx.types.err).collect()
 }
 
 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@@ -2738,27 +2896,28 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match lit.node {
         ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
         ast::LitBinary(..) => {
-            ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic),
-                         ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
-        }
-        ast::LitByte(_) => ty::mk_u8(),
-        ast::LitChar(_) => ty::mk_char(),
-        ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
-        ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
+            ty::mk_slice(tcx,
+                         tcx.mk_region(ty::ReStatic),
+                         ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
+        }
+        ast::LitByte(_) => tcx.types.u8,
+        ast::LitChar(_) => tcx.types.char,
+        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| {
                 match ty.sty {
                     ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
-                    ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
-                    ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
-                    ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
+                    ty::ty_char => Some(tcx.types.u8),
+                    ty::ty_ptr(..) => Some(tcx.types.uint),
+                    ty::ty_bare_fn(..) => Some(tcx.types.uint),
                     _ => None
                 }
             });
             opt_ty.unwrap_or_else(
                 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
         }
-        ast::LitFloat(_, t) => ty::mk_mach_float(t),
+        ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
         ast::LitFloatUnsuffixed(_) => {
             let opt_ty = expected.map_to_option(fcx, |ty| {
                 match ty.sty {
@@ -2769,7 +2928,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             opt_ty.unwrap_or_else(
                 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
         }
-        ast::LitBool(_) => ty::mk_bool()
+        ast::LitBool(_) => tcx.types.bool
     }
 }
 
@@ -2850,7 +3009,7 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let rps = fcx.inh.infcx.region_vars_for_defs(span, rps);
     let tps = fcx.inh.infcx.next_ty_vars(n_tps);
     let substs = subst::Substs::new_type(tps, rps);
-    let substd_ty = raw_ty.subst(tcx, &substs);
+    let substd_ty = fcx.instantiate_type_scheme(span, &substs, &raw_ty);
 
     TypeAndSubsts { substs: substs, ty: substd_ty }
 }
@@ -2944,8 +3103,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         // In that case, we check each argument against "error" in order to
         // set up all the node type bindings.
         let error_fn_sig = ty::Binder(FnSig {
-            inputs: err_args(args.len()),
-            output: ty::FnConverging(ty::mk_err()),
+            inputs: err_args(fcx.tcx(), args.len()),
+            output: ty::FnConverging(fcx.tcx().types.err),
             variadic: false
         });
 
@@ -2960,12 +3119,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             }
         };
 
-        // Replace any bound regions that appear in the function
-        // signature with region variables
+        // Replace any late-bound regions that appear in the function
+        // signature with region variables. We also have to
+        // renormalize the associated types at this point, since they
+        // previously appeared within a `Binder<>` and hence would not
+        // have been normalized before.
         let fn_sig =
             fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
                                                                   infer::FnCall,
                                                                   fn_sig).0;
+        let fn_sig =
+            fcx.normalize_associated_types_in(call_expr.span,
+                                              &fn_sig);
 
         // Call the generic checker.
         check_argument_types(fcx,
@@ -3012,7 +3177,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             Err(error) => {
                 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
                 fcx.write_error(expr.id);
-                ty::mk_err()
+                fcx.tcx().types.err
             }
         };
 
@@ -3038,7 +3203,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                  id: ast::NodeId,
                                  sp: Span,
                                  expected: Expectation<'tcx>) {
-        check_expr_has_type(fcx, cond_expr, ty::mk_bool());
+        check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
 
         let expected = expected.adjust_for_branches(fcx);
         check_block_with_expected(fcx, then_blk, expected);
@@ -3065,7 +3230,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         let cond_ty = fcx.expr_ty(cond_expr);
         let if_ty = if ty::type_is_error(cond_ty) {
-            ty::mk_err()
+            fcx.tcx().types.err
         } else {
             branches_ty
         };
@@ -3137,14 +3302,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                             autoref_args,
                                             DontTupleArguments) {
                     ty::FnConverging(result_type) => result_type,
-                    ty::FnDiverging => ty::mk_err()
+                    ty::FnDiverging => fcx.tcx().types.err
                 }
             }
             None => {
                 unbound_method();
                 // Check the args anyway
                 // so we get all the error messages
-                let expected_ty = ty::mk_err();
+                let expected_ty = fcx.tcx().types.err;
                 check_method_argument_types(fcx,
                                             op_ex.span,
                                             expected_ty,
@@ -3152,7 +3317,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                             args.as_slice(),
                                             autoref_args,
                                             DontTupleArguments);
-                ty::mk_err()
+                fcx.tcx().types.err
             }
         }
     }
@@ -3178,7 +3343,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
             // Shift is a special case: rhs must be uint, no matter what lhs is
-            check_expr_has_type(fcx, &**rhs, ty::mk_uint());
+            check_expr_has_type(fcx, &**rhs, fcx.tcx().types.uint);
             fcx.write_ty(expr.id, lhs_t);
             return;
         }
@@ -3205,12 +3370,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                 lhs_t,
                                 None
                             );
-                            ty::mk_err()
+                            fcx.tcx().types.err
                         } else {
                             lhs_t
                         }
                     } else {
-                        ty::mk_bool()
+                        fcx.tcx().types.bool
                     }
                 },
                 _ => lhs_t,
@@ -3252,7 +3417,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                    lhs_t,
                                    None);
             check_expr(fcx, &**rhs);
-            ty::mk_err()
+            fcx.tcx().types.err
         };
 
         fcx.write_ty(expr.id, result_t);
@@ -3288,7 +3453,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             ast::BiNe => ("ne", lang.eq_trait()),
             ast::BiAnd | ast::BiOr => {
                 check_expr(fcx, &**rhs);
-                return ty::mk_err();
+                return tcx.types.err;
             }
         };
         lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
@@ -3461,7 +3626,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         // Typecheck each field.
         for field in ast_fields.iter() {
-            let mut expected_field_type = ty::mk_err();
+            let mut expected_field_type = tcx.types.err;
 
             let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
             match pair {
@@ -3568,7 +3733,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                        base_expr.is_none(),
                                        None);
         if ty::type_is_error(fcx.node_ty(id)) {
-            struct_type = ty::mk_err();
+            struct_type = tcx.types.err;
         }
 
         // Check the base expression if necessary.
@@ -3657,7 +3822,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           if !checked {
               span_err!(tcx.sess, expr.span, E0066,
                   "only the managed heap and exchange heap are currently supported");
-              fcx.write_ty(id, ty::mk_err());
+              fcx.write_ty(id, tcx.types.err);
           }
       }
 
@@ -3757,7 +3922,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                 dereferenced", actual)
                                     }, oprnd_t, None);
                                 }
-                                ty::mk_err()
+                                tcx.types.err
                             }
                         }
                     };
@@ -3814,7 +3979,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
         let oprnd_t = if ty::type_is_error(tm.ty) {
-            ty::mk_err()
+            tcx.types.err
         } else {
             // Note: at this point, we cannot say what the best lifetime
             // is to use for resulting pointer.  We want to use the
@@ -3852,7 +4017,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
       }
       ast::ExprPath(ref pth) => {
           let defn = lookup_def(fcx, pth.span, id);
-          let pty = polytype_for_def(fcx, expr.span, defn);
+          let pty = type_scheme_for_def(fcx, expr.span, defn);
           instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
 
           // We always require that the type provided as the value for
@@ -3932,7 +4097,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
       }
       ast::ExprWhile(ref cond, ref body, _) => {
-        check_expr_has_type(fcx, &**cond, ty::mk_bool());
+        check_expr_has_type(fcx, &**cond, tcx.types.bool);
         check_block_no_value(fcx, &**body);
         let cond_ty = fcx.expr_ty(&**cond);
         let body_ty = fcx.node_ty(body.id);
@@ -4012,7 +4177,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
       }
       ast::ExprCast(ref e, ref t) => {
         if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
-            check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
+            check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
         }
         check_cast(fcx, expr, &**e, &**t);
       }
@@ -4043,7 +4208,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         fcx.write_ty(id, typ);
       }
       ast::ExprRepeat(ref element, ref count_expr) => {
-        check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
+        check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
         let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
 
         let uty = match expected {
@@ -4173,7 +4338,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let actual_structure_type = fcx.expr_ty(&*expr);
         if !ty::type_is_error(actual_structure_type) {
             let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
-                                                                  fcx.infcx(),
+                                                                  fcx,
                                                                   struct_id,
                                                                   path);
             match fcx.mk_subty(false,
@@ -4211,155 +4376,173 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
       }
       ast::ExprIndex(ref base, ref idx) => {
           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
-          check_expr(fcx, &**idx);
           let base_t = fcx.expr_ty(&**base);
-          let idx_t = fcx.expr_ty(&**idx);
           if ty::type_is_error(base_t) {
               fcx.write_ty(id, base_t);
-          } else if ty::type_is_error(idx_t) {
-              fcx.write_ty(id, idx_t);
           } else {
-              let base_t = structurally_resolved_type(fcx, expr.span, base_t);
-
-              let result =
-                  autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
-                      try_index_step(fcx,
-                                     MethodCall::expr(expr.id),
-                                     expr,
-                                     &**base,
-                                     adj_ty,
-                                     adj,
-                                     lvalue_pref)
-                  });
-
-              match result {
-                  Some((index_ty, element_ty)) => {
-                      check_expr_has_type(fcx, &**idx, index_ty);
-                      fcx.write_ty(id, element_ty);
-                  }
-                  _ => {
-                      check_expr_has_type(fcx, &**idx, ty::mk_err());
-                      fcx.type_error_message(
-                          expr.span,
-                          |actual| {
-                              format!("cannot index a value of type `{}`",
-                                      actual)
-                          },
-                          base_t,
-                          None);
-                      fcx.write_ty(id, ty::mk_err())
-                  }
-              }
-          }
-       }
-       ast::ExprSlice(ref base, ref start, ref end, mutbl) => {
-          check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
-          let raw_base_t = fcx.expr_ty(&**base);
-
-          let mut some_err = false;
-          if ty::type_is_error(raw_base_t) {
-              fcx.write_ty(id, raw_base_t);
-              some_err = true;
-          }
-
-          {
-              let check_slice_idx = |e: &ast::Expr| {
-                  check_expr(fcx, e);
-                  let e_t = fcx.expr_ty(e);
-                  if ty::type_is_error(e_t) {
-                    fcx.write_ty(e.id, e_t);
-                    some_err = true;
+              match idx.node {
+                ast::ExprRange(ref start, ref end) => {
+                  // A slice, rather than an index. Special cased for now (KILLME).
+                  let base_t = structurally_resolved_type(fcx, expr.span, base_t);
+
+                  let result =
+                      autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
+                          try_overloaded_slice_step(fcx,
+                                                    MethodCall::expr(expr.id),
+                                                    expr,
+                                                    &**base,
+                                                    adj_ty,
+                                                    adj,
+                                                    lvalue_pref,
+                                                    start,
+                                                    end)
+                      });
+
+                  let mut args = vec![];
+                  start.as_ref().map(|x| args.push(x));
+                  end.as_ref().map(|x| args.push(x));
+
+                  match result {
+                      Some((index_ty, element_ty)) => {
+                          for a in args.iter() {
+                            check_expr_has_type(fcx, &***a, index_ty);
+                          }
+                          fcx.write_ty(idx.id, element_ty);
+                          fcx.write_ty(id, element_ty)
+                      }
+                      _ => {
+                          for a in args.iter() {
+                            check_expr(fcx, &***a);
+                          }
+                          fcx.type_error_message(expr.span,
+                             |actual| {
+                                  format!("cannot take a slice of a value with type `{}`",
+                                          actual)
+                             },
+                             base_t,
+                             None);
+                          fcx.write_ty(idx.id, fcx.tcx().types.err);
+                          fcx.write_ty(id, fcx.tcx().types.err);
+                      }
                   }
-              };
-              start.as_ref().map(|e| check_slice_idx(&**e));
-              end.as_ref().map(|e| check_slice_idx(&**e));
-          }
-
-          if !some_err {
-              let base_t = structurally_resolved_type(fcx,
-                                                      expr.span,
-                                                      raw_base_t);
-              let method_call = MethodCall::expr(expr.id);
-              match try_overloaded_slice(fcx,
-                                         method_call,
-                                         expr,
-                                         &**base,
-                                         base_t,
-                                         start,
-                                         end,
-                                         mutbl) {
-                  Some(ty) => fcx.write_ty(id, ty),
-                  None => {
-                        fcx.type_error_message(expr.span,
-                           |actual| {
-                                format!("cannot take a {}slice of a value with type `{}`",
-                                        if mutbl == ast::MutMutable {
-                                            "mutable "
-                                        } else {
-                                            ""
-                                        },
-                                        actual)
-                           },
-                           base_t,
-                           None);
-                        fcx.write_ty(id, ty::mk_err())
+                }
+                _ => {
+                  check_expr(fcx, &**idx);
+                  let idx_t = fcx.expr_ty(&**idx);
+                  if ty::type_is_error(idx_t) {
+                      fcx.write_ty(id, idx_t);
+                  } else {
+                      let base_t = structurally_resolved_type(fcx, expr.span, base_t);
+
+                      let result =
+                          autoderef_for_index(fcx, &**base, base_t, lvalue_pref, |adj_ty, adj| {
+                              try_index_step(fcx,
+                                             MethodCall::expr(expr.id),
+                                             expr,
+                                             &**base,
+                                             adj_ty,
+                                             adj,
+                                             lvalue_pref)
+                          });
+
+                      match result {
+                          Some((index_ty, element_ty)) => {
+                              check_expr_has_type(fcx, &**idx, index_ty);
+                              fcx.write_ty(id, element_ty);
+                          }
+                          _ => {
+                              check_expr_has_type(fcx, &**idx, fcx.tcx().types.err);
+                              fcx.type_error_message(
+                                  expr.span,
+                                  |actual| {
+                                      format!("cannot index a value of type `{}`",
+                                              actual)
+                                  },
+                                  base_t,
+                                  None);
+                              fcx.write_ty(id, fcx.tcx().types.err);
+                          }
+                      }
                   }
+                }
               }
           }
        }
        ast::ExprRange(ref start, ref end) => {
-          check_expr(fcx, &**start);
-          let t_start = fcx.expr_ty(&**start);
-
-          let idx_type = if let &Some(ref e) = end {
+          let t_start = start.as_ref().map(|e| {
             check_expr(fcx, &**e);
-            let t_end = fcx.expr_ty(&**e);
-            if ty::type_is_error(t_end) {
-                ty::mk_err()
-            } else if t_start == ty::mk_err() {
-                ty::mk_err()
-            } else {
-                infer::common_supertype(fcx.infcx(),
-                                        infer::RangeExpression(expr.span),
-                                        true,
-                                        t_start,
-                                        t_end)
-            }
-          } else {
-            t_start
+            fcx.expr_ty(&**e)
+          });
+          let t_end = end.as_ref().map(|e| {
+            check_expr(fcx, &**e);
+            fcx.expr_ty(&**e)
+          });
+
+          let idx_type = match (t_start, t_end) {
+              (Some(ty), None) | (None, Some(ty)) => {
+                  Some(ty)
+              }
+              (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
+                                               ty::type_is_error(t_end)) => {
+                  Some(fcx.tcx().types.err)
+              }
+              (Some(t_start), Some(t_end)) => {
+                  Some(infer::common_supertype(fcx.infcx(),
+                                               infer::RangeExpression(expr.span),
+                                               true,
+                                               t_start,
+                                               t_end))
+              }
+              _ => None
           };
 
           // Note that we don't check the type of start/end satisfy any
           // bounds because right the range structs do not have any. If we add
           // some bounds, then we'll need to check `t_start` against them here.
 
-          let range_type = if idx_type == ty::mk_err() {
-            ty::mk_err()
-          } else {
-            // Find the did from the appropriate lang item.
-            let did = if end.is_some() {
-                // Range
-                tcx.lang_items.range_struct()
-            } else {
-                // RangeFrom
-                tcx.lang_items.range_from_struct()
-            };
+          let range_type = match idx_type {
+            Some(idx_type) if ty::type_is_error(idx_type) => {
+                fcx.tcx().types.err
+            }
+            Some(idx_type) => {
+                // Find the did from the appropriate lang item.
+                let did = match (start, end) {
+                    (&Some(_), &Some(_)) => tcx.lang_items.range_struct(),
+                    (&Some(_), &None) => tcx.lang_items.range_from_struct(),
+                    (&None, &Some(_)) => tcx.lang_items.range_to_struct(),
+                    (&None, &None) => {
+                        tcx.sess.span_bug(expr.span, "full range should be dealt with above")
+                    }
+                };
 
-            if let Some(did) = did {
-                let polytype = ty::lookup_item_type(tcx, did);
-                let substs = Substs::new_type(vec![idx_type], vec![]);
-                let bounds = polytype.generics.to_bounds(tcx, &substs);
-                fcx.add_obligations_for_parameters(
-                    traits::ObligationCause::new(expr.span,
-                                                 fcx.body_id,
-                                                 traits::ItemObligation(did)),
-                    &bounds);
-
-                ty::mk_struct(tcx, did, tcx.mk_substs(substs))
-            } else {
-                ty::mk_err()
+                if let Some(did) = did {
+                    let polytype = ty::lookup_item_type(tcx, did);
+                    let substs = Substs::new_type(vec![idx_type], vec![]);
+                    let bounds = fcx.instantiate_bounds(expr.span, &substs, &polytype.generics);
+                    fcx.add_obligations_for_parameters(
+                        traits::ObligationCause::new(expr.span,
+                                                     fcx.body_id,
+                                                     traits::ItemObligation(did)),
+                        &bounds);
+
+                    ty::mk_struct(tcx, did, tcx.mk_substs(substs))
+                } else {
+                    tcx.sess.span_err(expr.span, "No lang item for range syntax");
+                    fcx.tcx().types.err
+                }
+            }
+            None => {
+                // Neither start nor end => FullRange
+                if let Some(did) = tcx.lang_items.full_range_struct() {
+                    let substs = Substs::new_type(vec![], vec![]);
+                    ty::mk_struct(tcx, did, tcx.mk_substs(substs))
+                } else {
+                    tcx.sess.span_err(expr.span, "No lang item for range syntax");
+                    fcx.tcx().types.err
+                }
             }
           };
+
           fcx.write_ty(id, range_type);
        }
 
@@ -4396,7 +4579,7 @@ impl<'tcx> Expectation<'tcx> {
     /// In this case, the expected type for the `&[1, 2, 3]` expression is
     /// `&[int]`. If however we were to say that `[1, 2, 3]` has the
     /// expectation `ExpectHasType([int])`, that would be too strong --
-    /// `[1, 2, 3]` does not have the type `[int]` but rather `[int, ..3]`.
+    /// `[1, 2, 3]` does not have the type `[int]` but rather `[int; 3]`.
     /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
     /// to the type `&[int]`. Therefore, we propagate this more limited hint,
     /// which still is useful, because it informs integer literals and the like.
@@ -4831,12 +5014,12 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
                     let inh = static_inherited_fields(ccx);
                     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
                     let declty = match hint {
-                        attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
+                        attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
                         attr::ReprInt(_, attr::SignedInt(ity)) => {
-                            ty::mk_mach_int(ity)
+                            ty::mk_mach_int(fcx.tcx(), ity)
                         }
                         attr::ReprInt(_, attr::UnsignedInt(ity)) => {
-                            ty::mk_mach_uint(ity)
+                            ty::mk_mach_uint(fcx.tcx(), ity)
                         },
                     };
                     check_const_with_ty(&fcx, e.span, &**e, declty);
@@ -4929,10 +5112,10 @@ pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
 }
 
 // Returns the type parameter count and the type for the given definition.
-pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                  sp: Span,
-                                  defn: def::Def)
-                                  -> Polytype<'tcx> {
+pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                     sp: Span,
+                                     defn: def::Def)
+                                     -> TypeScheme<'tcx> {
     match defn {
       def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
           let typ = fcx.local_ty(sp, nid);
@@ -4948,7 +5131,7 @@ pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
       def::DefAssociatedTy(..) |
       def::DefAssociatedPath(..) |
       def::DefPrimTy(_) |
-      def::DefTyParam(..)=> {
+      def::DefTyParam(..) => {
         fcx.ccx.tcx.sess.span_bug(sp, "expected value, found type");
       }
       def::DefMod(..) | def::DefForeignMod(..) => {
@@ -4976,15 +5159,15 @@ pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 // number of type parameters and type.
 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   path: &ast::Path,
-                                  polytype: Polytype<'tcx>,
+                                  type_scheme: TypeScheme<'tcx>,
                                   def: def::Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
-    debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
+    debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
            path.repr(fcx.tcx()),
            def.repr(fcx.tcx()),
            node_id,
-           polytype.repr(fcx.tcx()));
+           type_scheme.repr(fcx.tcx()));
 
     // We need to extract the type parameters supplied by the user in
     // the path `path`. Due to the current setup, this is a bit of a
@@ -5046,7 +5229,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // The first step then is to categorize the segments appropriately.
 
     assert!(path.segments.len() >= 1);
-    let mut segment_spaces;
+    let mut segment_spaces: Vec<_>;
     match def {
         // Case 1 and 1b. Reference to a *type* or *enum variant*.
         def::DefSelfTy(..) |
@@ -5061,7 +5244,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefTyParam(..) => {
             // Everything but the final segment should have no
             // parameters at all.
-            segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
+            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
             segment_spaces.push(Some(subst::TypeSpace));
         }
 
@@ -5069,7 +5252,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefFn(..) |
         def::DefConst(..) |
         def::DefStatic(..) => {
-            segment_spaces = Vec::from_elem(path.segments.len() - 1, None);
+            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
             segment_spaces.push(Some(subst::FnSpace));
         }
 
@@ -5085,7 +5268,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 def::FromImpl(_) => {}
             }
 
-            segment_spaces = Vec::from_elem(path.segments.len() - 2, None);
+            segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
             segment_spaces.push(Some(subst::TypeSpace));
             segment_spaces.push(Some(subst::FnSpace));
         }
@@ -5100,7 +5283,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefRegion(..) |
         def::DefLabel(..) |
         def::DefUpvar(..) => {
-            segment_spaces = Vec::from_elem(path.segments.len(), None);
+            segment_spaces = repeat(None).take(path.segments.len()).collect();
         }
     }
     assert_eq!(segment_spaces.len(), path.segments.len());
@@ -5109,8 +5292,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     // Next, examine the definition, and determine how many type
     // parameters we expect from each space.
-    let type_defs = &polytype.generics.types;
-    let region_defs = &polytype.generics.regions;
+    let type_defs = &type_scheme.generics.types;
+    let region_defs = &type_scheme.generics.regions;
 
     // Now that we have categorized what space the parameters for each
     // segment belong to, let's sort out the parameters that the user
@@ -5150,33 +5333,20 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     }
 
     // The things we are substituting into the type should not contain
-    // escaping late-bound regions.
+    // escaping late-bound regions, and nor should the base type scheme.
     assert!(!substs.has_regions_escaping_depth(0));
+    assert!(!type_scheme.has_escaping_regions());
 
-    // In the case of static items taken from impls, there may be
-    // late-bound regions associated with the impl (not declared on
-    // the fn itself). Those should be replaced with fresh variables
-    // now. These can appear either on the type being referenced, or
-    // on the associated bounds.
-    let bounds = polytype.generics.to_bounds(fcx.tcx(), &substs);
-    let (ty_late_bound, bounds) =
-        fcx.infcx().replace_late_bound_regions_with_fresh_var(
-            span,
-            infer::FnCall,
-            &ty::Binder((polytype.ty, bounds))).0;
-
-    debug!("after late-bounds have been replaced: ty_late_bound={}", ty_late_bound.repr(fcx.tcx()));
-    debug!("after late-bounds have been replaced: bounds={}", bounds.repr(fcx.tcx()));
-
+    // Add all the obligations that are required, substituting and
+    // normalized appropriately.
+    let bounds = fcx.instantiate_bounds(span, &substs, &type_scheme.generics);
     fcx.add_obligations_for_parameters(
         traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def.def_id())),
         &bounds);
 
     // Substitute the values for the type parameters into the type of
     // the referenced item.
-    let ty_substituted = ty_late_bound.subst(fcx.tcx(), &substs);
-
-    debug!("ty_substituted: ty_substituted={}", ty_substituted.repr(fcx.tcx()));
+    let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
 
     fcx.write_ty(node_id, ty_substituted);
     fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
@@ -5264,7 +5434,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             span_err!(fcx.tcx().sess, data.bindings[0].span, E0182,
                       "unexpected binding of associated item in expression path \
                        (only allowed in type paths)");
-            substs.types.truncate(subst::ParamSpace::AssocSpace, 0);
         }
 
         {
@@ -5372,8 +5541,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 "too few type parameters provided: expected {}{} parameter(s) \
                 , found {} parameter(s)",
                 qualifier, required_len, provided_len);
-            substs.types.replace(space,
-                                 Vec::from_elem(desired.len(), ty::mk_err()));
+            substs.types.replace(space, repeat(fcx.tcx().types.err).take(desired.len()).collect());
             return;
         }
 
@@ -5457,8 +5625,8 @@ pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
             "the type of this value must be known in this \
              context".to_string()
         }, ty, None);
-        demand::suptype(fcx, sp, ty::mk_err(), ty);
-        ty = ty::mk_err();
+        demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
+        ty = fcx.tcx().types.err;
     }
 
     ty
@@ -5497,7 +5665,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     // make a vector of booleans initially false, set to true when used
     if tps.len() == 0u { return; }
-    let mut tps_used = Vec::from_elem(tps.len(), false);
+    let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
 
     ty::walk_ty(ty, |t| {
             match t.sty {
@@ -5520,7 +5688,8 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
     fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
-        ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
+        let name = token::intern(format!("P{}", n).as_slice());
+        ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
     }
 
     let tcx = ccx.tcx;
@@ -5561,7 +5730,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
         let (n_tps, inputs, output) = match name.get() {
             "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
             "size_of" |
-            "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
+            "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
             "init" => (1u, Vec::new(), param(ccx, 0)),
             "uninit" => (1u, Vec::new(), param(ccx, 0)),
             "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
@@ -5577,8 +5746,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                   ),
                ty::mk_nil(tcx))
             }
-            "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
-            "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
+            "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
+            "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
 
             "get_tydesc" => {
               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
@@ -5610,7 +5779,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
-                  ty::mk_int()
+                  ccx.tcx.types.int
                ),
                ty::mk_ptr(tcx, ty::mt {
                    ty: param(ccx, 0),
@@ -5629,7 +5798,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
-                  ty::mk_uint()
+                  tcx.types.uint,
                ),
                ty::mk_nil(tcx))
             }
@@ -5640,88 +5809,88 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutMutable
                   }),
-                  ty::mk_u8(),
-                  ty::mk_uint()
+                  tcx.types.u8,
+                  tcx.types.uint,
                ),
                ty::mk_nil(tcx))
             }
-            "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
+            "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
             "powif32" => {
                (0,
-                vec!( ty::mk_f32(), ty::mk_i32() ),
-                ty::mk_f32())
+                vec!( tcx.types.f32, tcx.types.i32 ),
+                tcx.types.f32)
             }
             "powif64" => {
                (0,
-                vec!( ty::mk_f64(), ty::mk_i32() ),
-                ty::mk_f64())
+                vec!( tcx.types.f64, tcx.types.i32 ),
+                tcx.types.f64)
             }
-            "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
+            "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
             "powf32" => {
                (0,
-                vec!( ty::mk_f32(), ty::mk_f32() ),
-                ty::mk_f32())
+                vec!( tcx.types.f32, tcx.types.f32 ),
+                tcx.types.f32)
             }
             "powf64" => {
                (0,
-                vec!( ty::mk_f64(), ty::mk_f64() ),
-                ty::mk_f64())
+                vec!( tcx.types.f64, tcx.types.f64 ),
+                tcx.types.f64)
             }
-            "expf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "expf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "exp2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "exp2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "logf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "logf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "log2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "log2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
+            "expf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "expf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "exp2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "exp2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "logf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "logf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "log2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "log2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
             "fmaf32" => {
                 (0,
-                 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
-                 ty::mk_f32())
+                 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
+                 tcx.types.f32)
             }
             "fmaf64" => {
                 (0,
-                 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
-                 ty::mk_f64())
+                 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
+                 tcx.types.f64)
             }
-            "fabsf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "fabsf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "copysignf32"  => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
-            "copysignf64"  => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
-            "floorf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "floorf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "ceilf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "ceilf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "truncf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "truncf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "rintf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "rintf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "roundf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "roundf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "ctpop8"       => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
-            "ctpop16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "ctpop32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "ctpop64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
-            "ctlz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
-            "ctlz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "ctlz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "ctlz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
-            "cttz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
-            "cttz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "cttz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "cttz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
-            "bswap16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "bswap32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "bswap64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
+            "fabsf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "fabsf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "copysignf32"  => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
+            "copysignf64"  => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
+            "floorf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "floorf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "ceilf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "ceilf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "truncf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "truncf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "rintf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "rintf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "roundf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "roundf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "ctpop8"       => (0, vec!( tcx.types.u8  ), tcx.types.u8),
+            "ctpop16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "ctpop32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "ctpop64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
+            "ctlz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
+            "ctlz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "ctlz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "ctlz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
+            "cttz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
+            "cttz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "cttz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "cttz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
+            "bswap16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "bswap32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "bswap64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
 
             "volatile_load" =>
                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
@@ -5729,40 +5898,40 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
 
             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
-                (0, vec!(ty::mk_i8(), ty::mk_i8()),
-                ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i8, tcx.types.i8),
+                ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
 
             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
-                (0, vec!(ty::mk_i16(), ty::mk_i16()),
-                ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i16, tcx.types.i16),
+                ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
 
             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
-                (0, vec!(ty::mk_i32(), ty::mk_i32()),
-                ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i32, tcx.types.i32),
+                ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
 
             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
-                (0, vec!(ty::mk_i64(), ty::mk_i64()),
-                ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i64, tcx.types.i64),
+                ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
 
             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
-                (0, vec!(ty::mk_u8(), ty::mk_u8()),
-                ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u8, tcx.types.u8),
+                ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
 
             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
-                (0, vec!(ty::mk_u16(), ty::mk_u16()),
-                ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u16, tcx.types.u16),
+                ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
 
             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
-                (0, vec!(ty::mk_u32(), ty::mk_u32()),
-                ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u32, tcx.types.u32),
+                ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
 
             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
-                (0, vec!(ty::mk_u64(), ty::mk_u64()),
-                ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u64, tcx.types.u64),
+                ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
 
-            "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
+            "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
 
-            "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)),
+            "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
 
             ref other => {
                 span_err!(tcx.sess, it.span, E0093,
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index b8cf215f89e..d01b79068aa 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -768,7 +768,7 @@ fn constrain_cast(rcx: &mut Rcx,
             }
 
             /*From:*/ (_,
-            /*To:  */  &ty::ty_trait(box ty::TyTrait { bounds, .. })) => {
+            /*To:  */  &ty::ty_trait(box ty::TyTrait { ref bounds, .. })) => {
                 // When T is existentially quantified as a trait
                 // `Foo+'to`, it must outlive the region bound `'to`.
                 type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
@@ -851,7 +851,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     }
 
     match function_type.sty {
-        ty::ty_closure(box ty::ClosureTy {bounds, ..}) => {
+        ty::ty_closure(box ty::ClosureTy {ref bounds, ..}) => {
             ty::with_freevars(tcx, expr.id, |freevars| {
                 ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
             })
@@ -859,7 +859,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
         ty::ty_unboxed_closure(_, region, _) => {
             ty::with_freevars(tcx, expr.id, |freevars| {
                 let bounds = ty::region_existential_bound(*region);
-                ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
+                ensure_free_variable_types_outlive_closure_bound(rcx, &bounds, expr, freevars);
             })
         }
         _ => {}
@@ -870,7 +870,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     /// over values outliving the object's lifetime bound.
     fn ensure_free_variable_types_outlive_closure_bound(
         rcx: &mut Rcx,
-        bounds: ty::ExistentialBounds,
+        bounds: &ty::ExistentialBounds,
         expr: &ast::Expr,
         freevars: &[ty::Freevar])
     {
@@ -1848,11 +1848,9 @@ fn param_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
     // well-formed, then, A must be lower-bounded by `'a`, but we
     // don't know that this holds from first principles.
     for &(ref r, ref p) in rcx.region_param_pairs.iter() {
-        debug!("param_ty={}/{} p={}/{}",
+        debug!("param_ty={} p={}",
                param_ty.repr(rcx.tcx()),
-               param_ty.def_id,
-               p.repr(rcx.tcx()),
-               p.def_id);
+               p.repr(rcx.tcx()));
         if param_ty == *p {
             param_bounds.push(*r);
         }
diff --git a/src/librustc_typeck/check/regionmanip.rs b/src/librustc_typeck/check/regionmanip.rs
index ea70b9d9e2e..42ffe2d5327 100644
--- a/src/librustc_typeck/check/regionmanip.rs
+++ b/src/librustc_typeck/check/regionmanip.rs
@@ -104,7 +104,8 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
 
             ty::ty_enum(def_id, substs) |
             ty::ty_struct(def_id, substs) => {
-                self.accumulate_from_adt(ty, def_id, substs)
+                let item_scheme = ty::lookup_item_type(self.tcx, def_id);
+                self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs)
             }
 
             ty::ty_vec(t, _) |
@@ -121,6 +122,18 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
                 self.push_param_constraint_from_top(p);
             }
 
+            ty::ty_projection(ref data) => {
+                // `<T as TraitRef<..>>::Name`
+
+                // FIXME(#20303) -- gain ability to require that ty_projection : in-scope region,
+                // like a type parameter
+
+                // this seems like a minimal requirement:
+                let trait_def = ty::lookup_trait_def(self.tcx, data.trait_ref.def_id);
+                self.accumulate_from_adt(ty, data.trait_ref.def_id,
+                                         &trait_def.generics, data.trait_ref.substs)
+            }
+
             ty::ty_tup(ref tuptys) => {
                 for &tupty in tuptys.iter() {
                     self.accumulate_from_ty(tupty);
@@ -213,14 +226,12 @@ impl<'a, 'tcx> Wf<'a, 'tcx> {
     fn accumulate_from_adt(&mut self,
                            ty: Ty<'tcx>,
                            def_id: ast::DefId,
+                           generics: &ty::Generics<'tcx>,
                            substs: &Substs<'tcx>)
     {
         // The generic declarations from the type, appropriately
         // substituted for the actual substitutions.
-        let generics =
-            ty::lookup_item_type(self.tcx, def_id)
-            .generics
-            .subst(self.tcx, substs);
+        let generics = generics.subst(self.tcx, substs);
 
         // Variance of each type/region parameter.
         let variances = ty::item_variances(self.tcx, def_id);
@@ -398,4 +409,3 @@ impl<'tcx> Repr<'tcx> for WfConstraint<'tcx> {
         }
     }
 }
-
diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs
index ff16568aa63..c85b542b6ca 100644
--- a/src/librustc_typeck/check/vtable.rs
+++ b/src/librustc_typeck/check/vtable.rs
@@ -9,16 +9,16 @@
 // except according to those terms.
 
 use check::{FnCtxt, structurally_resolved_type};
-use middle::subst::{FnSpace};
+use middle::subst::{FnSpace, SelfSpace};
 use middle::traits;
 use middle::traits::{Obligation, ObligationCause};
 use middle::traits::report_fulfillment_errors;
-use middle::ty::{mod, Ty};
+use middle::ty::{mod, Ty, AsPredicate};
 use middle::infer;
-use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::Span;
-use util::ppaux::{Repr, ty_to_string};
+use util::nodemap::FnvHashSet;
+use util::ppaux::{Repr, UserString};
 
 pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                    cast_expr: &ast::Expr,
@@ -133,22 +133,46 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
                                  object_trait: &ty::TyTrait<'tcx>,
                                  span: Span)
 {
-    let object_trait_ref = object_trait.principal_trait_ref_with_self_ty(tcx, ty::mk_err());
-    for tr in traits::supertraits(tcx, object_trait_ref) {
-        check_object_safety_inner(tcx, &*tr, span);
+    // Also check that the type `object_trait` specifies all
+    // associated types for all supertraits.
+    let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> = FnvHashSet::new();
+
+    let object_trait_ref =
+        object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
+    for tr in traits::supertraits(tcx, object_trait_ref.clone()) {
+        check_object_safety_inner(tcx, &tr, span);
+
+        let trait_def = ty::lookup_trait_def(tcx, object_trait_ref.def_id());
+        for &associated_type_name in trait_def.associated_type_names.iter() {
+            associated_types.insert((object_trait_ref.def_id(), associated_type_name));
+        }
+    }
+
+    for projection_bound in object_trait.bounds.projection_bounds.iter() {
+        let pair = (projection_bound.0.projection_ty.trait_ref.def_id,
+                    projection_bound.0.projection_ty.item_name);
+        associated_types.remove(&pair);
+    }
+
+    for (trait_def_id, name) in associated_types.into_iter() {
+        tcx.sess.span_err(
+            span,
+            format!("the value of the associated type `{}` (from the trait `{}`) must be specified",
+                    name.user_string(tcx),
+                    ty::item_path_str(tcx, trait_def_id)).as_slice());
     }
 }
 
 fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                 object_trait: &ty::PolyTraitRef<'tcx>,
-                                 span: Span) {
+                                   object_trait: &ty::PolyTraitRef<'tcx>,
+                                   span: Span) {
     let trait_items = ty::trait_items(tcx, object_trait.def_id());
 
     let mut errors = Vec::new();
     for item in trait_items.iter() {
         match *item {
             ty::MethodTraitItem(ref m) => {
-                errors.push(check_object_safety_of_method(tcx, &**m))
+                errors.push(check_object_safety_of_method(tcx, object_trait, &**m))
             }
             ty::TypeTraitItem(_) => {}
         }
@@ -166,12 +190,15 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
         }
     }
 
-    /// Returns a vec of error messages. If hte vec is empty - no errors!
+    /// Returns a vec of error messages. If the vec is empty - no errors!
     ///
     /// There are some limitations to calling functions through an object, because (a) the self
     /// type is not known (that's the whole point of a trait instance, after all, to obscure the
-    /// self type) and (b) the call must go through a vtable and hence cannot be monomorphized.
+    /// self type), (b) the call must go through a vtable and hence cannot be monomorphized and
+    /// (c) the trait contains static methods which can't be called because we don't know the
+    /// concrete type.
     fn check_object_safety_of_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                           object_trait: &ty::PolyTraitRef<'tcx>,
                                            method: &ty::Method<'tcx>)
                                            -> Vec<String> {
         let mut msgs = Vec::new();
@@ -185,21 +212,23 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
             }
 
             ty::StaticExplicitSelfCategory => {
-                // Static methods are always object-safe since they
-                // can't be called through a trait object
-                return msgs
+                // Static methods are never object safe (reason (c)).
+                msgs.push(format!("cannot call a static method (`{}`) \
+                                   through a trait object",
+                                  method_name));
+                return msgs;
             }
             ty::ByReferenceExplicitSelfCategory(..) |
             ty::ByBoxExplicitSelfCategory => {}
         }
 
         // reason (a) above
-        let check_for_self_ty = |ty| {
-            if ty::type_has_self(ty) {
+        let check_for_self_ty = |&: ty| {
+            if contains_illegal_self_type_reference(tcx, object_trait.def_id(), ty) {
                 Some(format!(
                     "cannot call a method (`{}`) whose type contains \
                      a self-type (`{}`) through a trait object",
-                    method_name, ty_to_string(tcx, ty)))
+                    method_name, ty.user_string(tcx)))
             } else {
                 None
             }
@@ -224,13 +253,105 @@ fn check_object_safety_inner<'tcx>(tcx: &ty::ctxt<'tcx>,
 
         msgs
     }
+
+    fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                                  trait_def_id: ast::DefId,
+                                                  ty: Ty<'tcx>)
+                                                  -> bool
+    {
+        // This is somewhat subtle. In general, we want to forbid
+        // references to `Self` in the argument and return types,
+        // since the value of `Self` is erased. However, there is one
+        // exception: it is ok to reference `Self` in order to access
+        // an associated type of the current trait, since we retain
+        // the value of those associated types in the object type
+        // itself.
+        //
+        // ```rust
+        // trait SuperTrait {
+        //     type X;
+        // }
+        //
+        // trait Trait : SuperTrait {
+        //     type Y;
+        //     fn foo(&self, x: Self) // bad
+        //     fn foo(&self) -> Self // bad
+        //     fn foo(&self) -> Option<Self> // bad
+        //     fn foo(&self) -> Self::Y // OK, desugars to next example
+        //     fn foo(&self) -> <Self as Trait>::Y // OK
+        //     fn foo(&self) -> Self::X // OK, desugars to next example
+        //     fn foo(&self) -> <Self as SuperTrait>::X // OK
+        // }
+        // ```
+        //
+        // However, it is not as simple as allowing `Self` in a projected
+        // type, because there are illegal ways to use `Self` as well:
+        //
+        // ```rust
+        // trait Trait : SuperTrait {
+        //     ...
+        //     fn foo(&self) -> <Self as SomeOtherTrait>::X;
+        // }
+        // ```
+        //
+        // Here we will not have the type of `X` recorded in the
+        // object type, and we cannot resolve `Self as SomeOtherTrait`
+        // without knowing what `Self` is.
+
+        let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
+        let mut error = false;
+        ty::maybe_walk_ty(ty, |ty| {
+            match ty.sty {
+                ty::ty_param(ref param_ty) => {
+                    if param_ty.space == SelfSpace {
+                        error = true;
+                    }
+
+                    false // no contained types to walk
+                }
+
+                ty::ty_projection(ref data) => {
+                    // This is a projected type `<Foo as SomeTrait>::X`.
+
+                    // Compute supertraits of current trait lazilly.
+                    if supertraits.is_none() {
+                        let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+                        let trait_ref = ty::Binder(trait_def.trait_ref.clone());
+                        supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
+                    }
+
+                    // Determine whether the trait reference `Foo as
+                    // SomeTrait` is in fact a supertrait of the
+                    // current trait. In that case, this type is
+                    // legal, because the type `X` will be specified
+                    // in the object type.  Note that we can just use
+                    // direct equality here because all of these types
+                    // are part of the formal parameter listing, and
+                    // hence there should be no inference variables.
+                    let projection_trait_ref = ty::Binder(data.trait_ref.clone());
+                    let is_supertrait_of_current_trait =
+                        supertraits.as_ref().unwrap().contains(&projection_trait_ref);
+
+                    if is_supertrait_of_current_trait {
+                        false // do not walk contained types, do not report error, do collect $200
+                    } else {
+                        true // DO walk contained types, POSSIBLY reporting an error
+                    }
+                }
+
+                _ => true, // walk contained types, if any
+            }
+        });
+
+        error
+    }
 }
 
 pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                   span: Span,
                                                   object_trait: &ty::TyTrait<'tcx>,
                                                   referent_ty: Ty<'tcx>)
-                                                  -> Rc<ty::PolyTraitRef<'tcx>>
+                                                  -> ty::PolyTraitRef<'tcx>
 {
     // We can only make objects from sized types.
     fcx.register_builtin_bound(
@@ -243,21 +364,21 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let object_trait_ty =
         ty::mk_trait(fcx.tcx(),
                      object_trait.principal.clone(),
-                     object_trait.bounds);
+                     object_trait.bounds.clone());
 
     debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
            referent_ty.repr(fcx.tcx()),
            object_trait_ty.repr(fcx.tcx()));
 
+    let cause = ObligationCause::new(span,
+                                     fcx.body_id,
+                                     traits::ObjectCastObligation(object_trait_ty));
+
     // Create the obligation for casting from T to Trait.
     let object_trait_ref =
         object_trait.principal_trait_ref_with_self_ty(fcx.tcx(), referent_ty);
     let object_obligation =
-        Obligation::new(
-            ObligationCause::new(span,
-                                 fcx.body_id,
-                                 traits::ObjectCastObligation(object_trait_ty)),
-            ty::Predicate::Trait(object_trait_ref.clone()));
+        Obligation::new(cause.clone(), object_trait_ref.as_predicate());
     fcx.register_predicate(object_obligation);
 
     // Create additional obligations for all the various builtin
@@ -268,7 +389,16 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         fcx.register_builtin_bound(
             referent_ty,
             builtin_bound,
-            ObligationCause::new(span, fcx.body_id, traits::ObjectCastObligation(object_trait_ty)));
+            cause.clone());
+    }
+
+    // Finally, create obligations for the projection predicates.
+    let projection_bounds =
+        object_trait.projection_bounds_with_self_ty(fcx.tcx(), referent_ty);
+    for projection_bound in projection_bounds.iter() {
+        let projection_obligation =
+            Obligation::new(cause.clone(), projection_bound.as_predicate());
+        fcx.register_predicate(projection_obligation);
     }
 
     object_trait_ref
@@ -277,6 +407,9 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
     debug!("select_all_fcx_obligations_or_error");
 
+    select_fcx_obligations_where_possible(fcx);
+    fcx.default_type_parameters();
+
     let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
     let r = fulfillment_cx.select_all_or_error(fcx.infcx(),
                                                &fcx.inh.param_env,
@@ -313,3 +446,4 @@ pub fn select_new_fcx_obligations(fcx: &FnCtxt) {
         Err(errors) => { report_fulfillment_errors(fcx.infcx(), &errors); }
     }
 }
+
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 258177bb720..410697b0aca 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -13,7 +13,6 @@ use check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck};
 use CrateCtxt;
 use middle::region;
 use middle::subst;
-use middle::subst::{Subst};
 use middle::traits;
 use middle::ty::{mod, Ty};
 use middle::ty::liberate_late_bound_regions;
@@ -147,8 +146,10 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                                         item.span,
                                                         region::CodeExtent::from_node_id(item.id),
                                                         Some(&mut this.cache));
-            let polytype = ty::lookup_item_type(fcx.tcx(), local_def(item.id));
-            let item_ty = polytype.ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
+            let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id));
+            let item_ty = fcx.instantiate_type_scheme(item.span,
+                                                      &fcx.inh.param_env.free_substs,
+                                                      &type_scheme.ty);
             bounds_checker.check_traits_in_ty(item_ty);
         });
     }
@@ -168,7 +169,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             // that is, with all type parameters converted from bound
             // to free.
             let self_ty = ty::node_id_to_type(fcx.tcx(), item.id);
-            let self_ty = self_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
+            let self_ty = fcx.instantiate_type_scheme(item.span,
+                                                      &fcx.inh.param_env.free_substs,
+                                                      &self_ty);
 
             bounds_checker.check_traits_in_ty(self_ty);
 
@@ -178,7 +181,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 None => { return; }
                 Some(t) => { t }
             };
-            let trait_ref = (*trait_ref).subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
+            let trait_ref = fcx.instantiate_type_scheme(item.span,
+                                                        &fcx.inh.param_env.free_substs,
+                                                        &trait_ref);
 
             // There are special rules that apply to drop.
             if
@@ -209,7 +214,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             // trait reference. Instead, this is done at the impl site.
             // Arguably this is wrong and we should treat the trait-reference
             // the same way as we treat the self-type.
-            bounds_checker.check_trait_ref(&trait_ref);
+            bounds_checker.check_trait_ref(&*trait_ref);
 
             let cause =
                 traits::ObligationCause::new(
@@ -264,7 +269,8 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
     pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
         let trait_def = ty::lookup_trait_def(self.fcx.tcx(), trait_ref.def_id);
 
-        let bounds = trait_def.generics.to_bounds(self.tcx(), trait_ref.substs);
+        let bounds = self.fcx.instantiate_bounds(self.span, trait_ref.substs, &trait_def.generics);
+
         self.fcx.add_obligations_for_parameters(
             traits::ObligationCause::new(
                 self.span,
@@ -313,14 +319,15 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
         match t.sty{
             ty::ty_struct(type_id, substs) |
             ty::ty_enum(type_id, substs) => {
-                let polytype = ty::lookup_item_type(self.fcx.tcx(), type_id);
+                let type_scheme = ty::lookup_item_type(self.fcx.tcx(), type_id);
+                let bounds = self.fcx.instantiate_bounds(self.span, substs, &type_scheme.generics);
 
                 if self.binding_count == 0 {
                     self.fcx.add_obligations_for_parameters(
                         traits::ObligationCause::new(self.span,
                                                      self.fcx.body_id,
                                                      traits::ItemObligation(type_id)),
-                        &polytype.generics.to_bounds(self.tcx(), substs));
+                        &bounds);
                 } else {
                     // There are two circumstances in which we ignore
                     // region obligations.
@@ -344,7 +351,6 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
                     //
                     // (I believe we should do the same for traits, but
                     // that will require an RFC. -nmatsakis)
-                    let bounds = polytype.generics.to_bounds(self.tcx(), substs);
                     let bounds = filter_to_trait_obligations(bounds);
                     self.fcx.add_obligations_for_parameters(
                         traits::ObligationCause::new(self.span,
@@ -397,7 +403,9 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         .iter()
         .map(|field| {
             let field_ty = ty::node_id_to_type(fcx.tcx(), field.node.id);
-            let field_ty = field_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
+            let field_ty = fcx.instantiate_type_scheme(field.span,
+                                                       &fcx.inh.param_env.free_substs,
+                                                       &field_ty);
             AdtField { ty: field_ty, span: field.span }
         })
         .collect();
@@ -416,7 +424,10 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     AdtVariant {
                         fields: args.iter().enumerate().map(|(index, arg)| {
                             let arg_ty = arg_tys[index];
-                            let arg_ty = arg_ty.subst(fcx.tcx(), &fcx.inh.param_env.free_substs);
+                            let arg_ty =
+                                fcx.instantiate_type_scheme(variant.span,
+                                                            &fcx.inh.param_env.free_substs,
+                                                            &arg_ty);
                             AdtField {
                                 ty: arg_ty,
                                 span: arg.ty.span
@@ -443,7 +454,8 @@ fn filter_to_trait_obligations<'tcx>(bounds: ty::GenericBounds<'tcx>)
     let mut result = ty::GenericBounds::empty();
     for (space, _, predicate) in bounds.predicates.iter_enumerated() {
         match *predicate {
-            ty::Predicate::Trait(..) => {
+            ty::Predicate::Trait(..) |
+            ty::Predicate::Projection(..) => {
                 result.predicates.push(space, predicate.clone())
             }
             ty::Predicate::Equate(..) |
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index b123d97d897..5ef9757b91a 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -169,7 +169,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         match t.node {
             ast::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&**ty);
-                write_ty_to_tcx(self.tcx(), count_expr.id, ty::mk_uint());
+                write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.uint);
             }
             _ => visit::walk_ty(self, t)
         }
@@ -441,7 +441,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
                 debug!("Resolver::fold_ty: input type `{}` not fully resolvable",
                        t.repr(self.tcx));
                 self.report_error(e);
-                ty::mk_err()
+                self.tcx().types.err
             }
         }
     }
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index f92c7764a69..79e1efa618f 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -23,10 +23,11 @@ use middle::ty::RegionEscape;
 use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
 use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
 use middle::ty::{Ty, ty_bool, ty_char, ty_closure, ty_enum, ty_err};
-use middle::ty::{ty_param, Polytype, ty_ptr};
+use middle::ty::{ty_param, TypeScheme, ty_ptr};
 use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
 use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open};
 use middle::ty::{ty_uint, ty_unboxed_closure, ty_uniq, ty_bare_fn};
+use middle::ty::{ty_projection};
 use middle::ty;
 use CrateCtxt;
 use middle::infer::combine::Combine;
@@ -64,13 +65,13 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
         }
 
         ty_trait(ref t) => {
-            Some(t.principal.def_id())
+            Some(t.principal_def_id())
         }
 
         ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
         ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
         ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) |
-        ty_ptr(_) | ty_rptr(_, _) => {
+        ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => {
             None
         }
 
@@ -206,7 +207,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         debug!("instantiate_default_methods(impl_id={}, trait_ref={})",
                impl_id, trait_ref.repr(tcx));
 
-        let impl_poly_type = ty::lookup_item_type(tcx, impl_id);
+        let impl_type_scheme = ty::lookup_item_type(tcx, impl_id);
 
         let prov = ty::provided_trait_methods(tcx, trait_ref.def_id);
         for trait_method in prov.iter() {
@@ -221,7 +222,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 Rc::new(subst_receiver_types_in_method_ty(
                     tcx,
                     impl_id,
-                    &impl_poly_type,
+                    &impl_type_scheme,
                     trait_ref,
                     new_did,
                     &**trait_method,
@@ -233,7 +234,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             // construct the polytype for the method based on the
             // method_ty.  it will have all the generics from the
             // impl, plus its own.
-            let new_polytype = ty::Polytype {
+            let new_polytype = ty::TypeScheme {
                 generics: new_method_ty.generics.clone(),
                 ty: ty::mk_bare_fn(tcx, Some(new_did),
                                    tcx.mk_bare_fn(new_method_ty.fty.clone()))
@@ -275,7 +276,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     }
 
     fn get_self_type_for_implementation(&self, impl_did: DefId)
-                                        -> Polytype<'tcx> {
+                                        -> TypeScheme<'tcx> {
         self.crate_context.tcx.tcache.borrow()[impl_did].clone()
     }
 
@@ -535,7 +536,7 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id:
 
 fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
                                            impl_id: ast::DefId,
-                                           impl_poly_type: &ty::Polytype<'tcx>,
+                                           impl_type_scheme: &ty::TypeScheme<'tcx>,
                                            trait_ref: &ty::TraitRef<'tcx>,
                                            new_def_id: ast::DefId,
                                            method: &ty::Method<'tcx>,
@@ -554,10 +555,10 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
     for &space in [subst::TypeSpace, subst::SelfSpace].iter() {
         method_generics.types.replace(
             space,
-            impl_poly_type.generics.types.get_slice(space).to_vec());
+            impl_type_scheme.generics.types.get_slice(space).to_vec());
         method_generics.regions.replace(
             space,
-            impl_poly_type.generics.regions.get_slice(space).to_vec());
+            impl_type_scheme.generics.regions.get_slice(space).to_vec());
     }
 
     debug!("subst_receiver_types_in_method_ty: method_generics={}",
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index bb8efd29910..79443200ddf 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -54,8 +54,8 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
                     ty::ty_struct(def_id, _) => {
                         self.check_def_id(item.span, def_id);
                     }
-                    ty::ty_trait(box ty::TyTrait{ ref principal, ..}) => {
-                        self.check_def_id(item.span, principal.def_id());
+                    ty::ty_trait(ref data) => {
+                        self.check_def_id(item.span, data.principal_def_id());
                     }
                     _ => {
                         span_err!(self.tcx.sess, item.span, E0118,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 793c5f5b4a0..9e184db3b84 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -23,31 +23,25 @@ Unlike most of the types that are present in Rust, the types computed
 for each item are in fact polytypes.  In "layman's terms", this means
 that they are generic types that may have type parameters (more
 mathematically phrased, they are universally quantified over a set of
-type parameters).  Polytypes are represented by an instance of
-`ty::Polytype`.  This combines the core type along with a list of the
+type parameters).  TypeSchemes are represented by an instance of
+`ty::TypeScheme`.  This combines the core type along with a list of the
 bounds for each parameter.  Type parameters themselves are represented
 as `ty_param()` instances.
 
 */
-use self::ConvertMethodContext::*;
-use self::CreateTypeParametersForAssociatedTypesFlag::*;
-
-use astconv::{AstConv, ty_of_arg, AllowEqConstraints};
-use astconv::{ast_ty_to_ty, ast_region_to_region};
-use astconv;
+use astconv::{mod, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
 use metadata::csearch;
-use middle::def;
 use middle::lang_items::SizedTraitLangItem;
 use middle::region;
 use middle::resolve_lifetime;
 use middle::subst;
 use middle::subst::{Substs};
 use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
-use middle::ty::{mod, RegionEscape, Ty, Polytype};
+use middle::ty::{mod, RegionEscape, Ty, TypeScheme};
 use middle::ty_fold::{mod, TypeFolder, TypeFoldable};
 use middle::infer;
 use rscope::*;
-use {CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
+use {CrateCtxt, no_params, write_ty_to_tcx};
 use util::nodemap::{FnvHashMap, FnvHashSet};
 use util::ppaux;
 use util::ppaux::{Repr,UserString};
@@ -70,8 +64,8 @@ use syntax::visit;
 pub fn collect_item_types(ccx: &CrateCtxt) {
     fn collect_intrinsic_type(ccx: &CrateCtxt,
                               lang_item: ast::DefId) {
-        let ty::Polytype { ty, .. } =
-            ccx.get_item_ty(lang_item);
+        let ty::TypeScheme { ty, .. } =
+            ccx.get_item_type_scheme(lang_item);
         ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
     }
 
@@ -139,12 +133,6 @@ pub trait ToTy<'tcx> {
     fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
 }
 
-impl<'a,'tcx> ToTy<'tcx> for ImplCtxt<'a,'tcx> {
-    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
-        ast_ty_to_ty(self, rs, ast_ty)
-    }
-}
-
 impl<'a,'tcx> ToTy<'tcx> for CrateCtxt<'a,'tcx> {
     fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
         ast_ty_to_ty(self, rs, ast_ty)
@@ -154,7 +142,7 @@ impl<'a,'tcx> ToTy<'tcx> for CrateCtxt<'a,'tcx> {
 impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
 
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
+    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
         if id.krate != ast::LOCAL_CRATE {
             return csearch::get_type(self.tcx, id)
         }
@@ -165,13 +153,10 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
                 let abi = self.tcx.map.get_foreign_abi(id.node);
                 ty_of_foreign_item(self, &*foreign_item, abi)
             }
-            Some(ast_map::NodeTraitItem(trait_item)) => {
-                ty_of_trait_item(self, &*trait_item)
-            }
             x => {
                 self.tcx.sess.bug(format!("unexpected sort of node \
-                                           in get_item_ty(): {}",
-                                          x)[]);
+                                           in get_item_type_scheme(): {}",
+                                          x).as_slice());
             }
         }
     }
@@ -183,23 +168,16 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
     fn ty_infer(&self, span: Span) -> Ty<'tcx> {
         span_err!(self.tcx.sess, span, E0121,
                   "the type placeholder `_` is not allowed within types on item signatures");
-        ty::mk_err()
-    }
-
-    fn associated_types_of_trait_are_valid(&self, _: Ty<'tcx>, _: ast::DefId)
-                                           -> bool {
-        false
+        self.tcx().types.err
     }
 
-    fn associated_type_binding(&self,
-                               span: Span,
-                               _: Option<Ty<'tcx>>,
-                               _: ast::DefId,
-                               _: ast::DefId)
-                               -> Option<Ty<'tcx>> {
-        self.tcx().sess.span_err(span, "associated types may not be \
-                                        referenced here");
-        Some(ty::mk_err())
+    fn projected_ty(&self,
+                    _span: Span,
+                    trait_ref: Rc<ty::TraitRef<'tcx>>,
+                    item_name: ast::Name)
+                    -> Ty<'tcx>
+    {
+        ty::mk_projection(self.tcx, trait_ref, item_name)
     }
 }
 
@@ -227,28 +205,22 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             }
 
             ast::StructVariantKind(ref struct_def) => {
-                let pty = Polytype {
-                    generics: ty_generics_for_type_or_impl(
-                        ccx,
-                        generics,
-                        DontCreateTypeParametersForAssociatedTypes),
+                let scheme = TypeScheme {
+                    generics: ty_generics_for_type_or_impl(ccx, generics),
                     ty: enum_ty
                 };
 
-                convert_struct(ccx, &**struct_def, pty, variant.node.id);
+                convert_struct(ccx, &**struct_def, scheme, variant.node.id);
                 enum_ty
             }
         };
 
-        let pty = Polytype {
-            generics: ty_generics_for_type_or_impl(
-                          ccx,
-                          generics,
-                          DontCreateTypeParametersForAssociatedTypes),
+        let scheme = TypeScheme {
+            generics: ty_generics_for_type_or_impl(ccx, generics),
             ty: result_ty
         };
 
-        tcx.tcache.borrow_mut().insert(variant_def_id, pty);
+        tcx.tcache.borrow_mut().insert(variant_def_id, scheme);
 
         write_ty_to_tcx(tcx, variant.node.id, result_ty);
     }
@@ -259,7 +231,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    trait_def: &ty::TraitDef<'tcx>) {
     let tcx = ccx.tcx;
     if let ast_map::NodeItem(item) = tcx.map.get(trait_id) {
-        if let ast::ItemTrait(_, _, _, _, ref trait_items) = item.node {
+        if let ast::ItemTrait(_, _, _, ref trait_items) = item.node {
             // For each method, construct a suitable ty::Method and
             // store it into the `tcx.impl_or_trait_items` table:
             for trait_item in trait_items.iter() {
@@ -353,7 +325,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
         ccx.tcx.tcache.borrow_mut().insert(
             m.def_id,
-            Polytype {
+            TypeScheme {
                 generics: m.generics.clone(),
                 ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), ccx.tcx.mk_bare_fn(m.fty.clone())) });
     }
@@ -361,7 +333,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                            trait_id: ast::NodeId,
                                            trait_generics: &ty::Generics<'tcx>,
-                                           trait_items: &[ast::TraitItem],
+                                           _trait_items: &[ast::TraitItem],
                                            m_id: &ast::NodeId,
                                            m_name: &ast::Name,
                                            m_explicit_self: &ast::ExplicitSelf,
@@ -374,19 +346,11 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ty_generics_for_fn_or_method(
                 ccx,
                 m_generics,
-                (*trait_generics).clone(),
-                DontCreateTypeParametersForAssociatedTypes);
+                (*trait_generics).clone());
 
         let (fty, explicit_self_category) = {
-            let tmcx = TraitMethodCtxt {
-                ccx: ccx,
-                trait_id: local_def(trait_id),
-                trait_items: trait_items[],
-                method_generics: &ty_generics,
-            };
-            let trait_self_ty = ty::mk_self_type(tmcx.tcx(),
-                                                 local_def(trait_id));
-            astconv::ty_of_method(&tmcx,
+            let trait_self_ty = ty::mk_self_type(ccx.tcx);
+            astconv::ty_of_method(ccx,
                                   *m_unsafety,
                                   trait_self_ty,
                                   m_explicit_self,
@@ -416,7 +380,7 @@ pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     write_ty_to_tcx(ccx.tcx, v.node.id, tt);
     /* add the field to the tcache */
     ccx.tcx.tcache.borrow_mut().insert(local_def(v.node.id),
-                                       ty::Polytype {
+                                       ty::TypeScheme {
                                            generics: struct_generics.clone(),
                                            ty: tt
                                        });
@@ -444,36 +408,7 @@ pub fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      trait_def: &ty::TraitDef<'tcx>,
                                      associated_type: &ast::AssociatedType)
-                                     -> ty::Polytype<'tcx> {
-    // Find the type parameter ID corresponding to this
-    // associated type.
-    let type_parameter_def = trait_def.generics
-                                      .types
-                                      .get_slice(subst::AssocSpace)
-                                      .iter()
-                                      .find(|def| {
-        def.def_id == local_def(associated_type.ty_param.id)
-    });
-    let type_parameter_def = match type_parameter_def {
-        Some(type_parameter_def) => type_parameter_def,
-        None => {
-            ccx.tcx().sess.span_bug(associated_type.ty_param.span,
-                                    "`convert_associated_type()` didn't find \
-                                     a type parameter ID corresponding to \
-                                     this type")
-        }
-    };
-    let param_type = ty::mk_param(ccx.tcx,
-                                  type_parameter_def.space,
-                                  type_parameter_def.index,
-                                  local_def(associated_type.ty_param.id));
-    ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.ty_param.id),
-                                       Polytype {
-                                        generics: ty::Generics::empty(),
-                                        ty: param_type,
-                                       });
-    write_ty_to_tcx(ccx.tcx, associated_type.ty_param.id, param_type);
-
+{
     let associated_type = Rc::new(ty::AssociatedType {
         name: associated_type.ty_param.ident.name,
         vis: ast::Public,
@@ -485,32 +420,16 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
        .borrow_mut()
        .insert(associated_type.def_id,
                ty::TypeTraitItem(associated_type));
-
-    Polytype {
-        generics: ty::Generics::empty(),
-        ty: param_type,
-    }
-}
-
-#[deriving(Copy)]
-enum ConvertMethodContext<'a> {
-    /// Used when converting implementation methods.
-    ImplConvertMethodContext,
-    /// Used when converting method signatures. The def ID is the def ID of
-    /// the trait we're translating.
-    TraitConvertMethodContext(ast::DefId, &'a [ast::TraitItem]),
 }
 
 fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
-                                 convert_method_context: ConvertMethodContext,
                                  container: ImplOrTraitItemContainer,
                                  mut ms: I,
                                  untransformed_rcvr_ty: Ty<'tcx>,
                                  rcvr_ty_generics: &ty::Generics<'tcx>,
                                  rcvr_visibility: ast::Visibility)
                                  where I: Iterator<&'i ast::Method> {
-    debug!("convert_methods(untransformed_rcvr_ty={}, \
-            rcvr_ty_generics={})",
+    debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})",
            untransformed_rcvr_ty.repr(ccx.tcx),
            rcvr_ty_generics.repr(ccx.tcx));
 
@@ -523,7 +442,6 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
 
         let m_def_id = local_def(m.id);
         let mty = Rc::new(ty_of_method(ccx,
-                                       convert_method_context,
                                        container,
                                        m,
                                        untransformed_rcvr_ty,
@@ -536,7 +454,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
                 fty.repr(tcx));
         tcx.tcache.borrow_mut().insert(
             m_def_id,
-            Polytype {
+            TypeScheme {
                 generics: mty.generics.clone(),
                 ty: fty
             });
@@ -552,7 +470,6 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 
     fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                    convert_method_context: ConvertMethodContext,
                               container: ImplOrTraitItemContainer,
                               m: &ast::Method,
                               untransformed_rcvr_ty: Ty<'tcx>,
@@ -563,37 +480,14 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
             ty_generics_for_fn_or_method(
                 ccx,
                 m.pe_generics(),
-                (*rcvr_ty_generics).clone(),
-                CreateTypeParametersForAssociatedTypes);
-
-        let (fty, explicit_self_category) = match convert_method_context {
-            ImplConvertMethodContext => {
-                let imcx = ImplMethodCtxt {
-                    ccx: ccx,
-                    method_generics: &m_ty_generics,
-                };
-                astconv::ty_of_method(&imcx,
-                                      m.pe_unsafety(),
-                                      untransformed_rcvr_ty,
-                                      m.pe_explicit_self(),
-                                      &*m.pe_fn_decl(),
-                                      m.pe_abi())
-            }
-            TraitConvertMethodContext(trait_id, trait_items) => {
-                let tmcx = TraitMethodCtxt {
-                    ccx: ccx,
-                    trait_id: trait_id,
-                    trait_items: trait_items,
-                    method_generics: &m_ty_generics,
-                };
-                astconv::ty_of_method(&tmcx,
-                                      m.pe_unsafety(),
-                                      untransformed_rcvr_ty,
-                                      m.pe_explicit_self(),
-                                      &*m.pe_fn_decl(),
-                                      m.pe_abi())
-            }
-        };
+                (*rcvr_ty_generics).clone());
+
+        let (fty, explicit_self_category) = astconv::ty_of_method(ccx,
+                                                                  m.pe_unsafety(),
+                                                                  untransformed_rcvr_ty,
+                                                                  m.pe_explicit_self(),
+                                                                  &*m.pe_fn_decl(),
+                                                                  m.pe_abi());
 
         // if the method specifies a visibility, use that, otherwise
         // inherit the visibility from the impl (so `foo` in `pub impl
@@ -627,11 +521,6 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
                 ast::RegionTyParamBound(..) => { }
             }
         }
-
-        match ty_param.unbound {
-            Some(_) => { warn = true; }
-            None => { }
-        }
     }
 
     if warn {
@@ -646,392 +535,6 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
     }
 }
 
-fn is_associated_type_valid_for_param(ty: Ty,
-                                      trait_id: ast::DefId,
-                                      generics: &ty::Generics)
-                                      -> bool {
-    if let ty::ty_param(param_ty) = ty.sty {
-        let type_parameter = generics.types.get(param_ty.space, param_ty.idx as uint);
-        for trait_bound in type_parameter.bounds.trait_bounds.iter() {
-            if trait_bound.def_id() == trait_id {
-                return true
-            }
-        }
-    }
-
-    false
-}
-
-fn find_associated_type_in_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                          span: Span,
-                                          self_ty: Option<Ty<'tcx>>,
-                                          associated_type_id: ast::DefId,
-                                          generics: &ty::Generics<'tcx>)
-                                          -> Option<Ty<'tcx>>
-{
-    debug!("find_associated_type_in_generics(ty={}, associated_type_id={}, generics={}",
-           self_ty.repr(tcx), associated_type_id.repr(tcx), generics.repr(tcx));
-
-    let self_ty = match self_ty {
-        None => {
-            return None;
-        }
-        Some(ty) => ty,
-    };
-
-    match self_ty.sty {
-        ty::ty_param(ref param_ty) => {
-            let param_id = param_ty.def_id;
-            for type_parameter in generics.types.iter() {
-                if type_parameter.def_id == associated_type_id
-                    && type_parameter.associated_with == Some(param_id) {
-                    return Some(ty::mk_param_from_def(tcx, type_parameter));
-                }
-            }
-
-            tcx.sess.span_err(
-                span,
-                format!("no suitable bound on `{}`",
-                        self_ty.user_string(tcx))[]);
-            Some(ty::mk_err())
-        }
-        _ => {
-            tcx.sess.span_err(
-                span,
-                "it is currently unsupported to access associated types except \
-                 through a type parameter; this restriction will be lifted in time");
-            Some(ty::mk_err())
-        }
-    }
-}
-
-fn type_is_self(ty: Ty) -> bool {
-    match ty.sty {
-        ty::ty_param(ref param_ty) if param_ty.is_self() => true,
-        _ => false,
-    }
-}
-
-struct ImplCtxt<'a,'tcx:'a> {
-    ccx: &'a CrateCtxt<'a,'tcx>,
-    opt_trait_ref_id: Option<ast::DefId>,
-    impl_items: &'a [ast::ImplItem],
-    impl_generics: &'a ty::Generics<'tcx>,
-}
-
-impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> {
-        self.ccx.tcx
-    }
-
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
-        self.ccx.get_item_ty(id)
-    }
-
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        self.ccx.get_trait_def(id)
-    }
-
-    fn ty_infer(&self, span: Span) -> Ty<'tcx> {
-        self.ccx.ty_infer(span)
-    }
-
-    fn associated_types_of_trait_are_valid(&self,
-                                           ty: Ty<'tcx>,
-                                           trait_id: ast::DefId)
-                                           -> bool {
-        // OK if the trait with the associated type is the trait we're
-        // implementing.
-        match self.opt_trait_ref_id {
-            Some(trait_ref_id) if trait_ref_id == trait_id => {
-                if type_is_self(ty) {
-                    return true
-                }
-            }
-            Some(_) | None => {}
-        }
-
-        // OK if the trait with the associated type is one of the traits in
-        // our bounds.
-        is_associated_type_valid_for_param(ty, trait_id, self.impl_generics)
-    }
-
-    fn associated_type_binding(&self,
-                               span: Span,
-                               self_ty: Option<Ty<'tcx>>,
-                               trait_id: ast::DefId,
-                               associated_type_id: ast::DefId)
-                               -> Option<Ty<'tcx>>
-    {
-        match self.opt_trait_ref_id {
-            // It's an associated type on the trait that we're
-            // implementing.
-            Some(trait_ref_id) if trait_ref_id == trait_id => {
-                let trait_def = ty::lookup_trait_def(self.tcx(), trait_id);
-                assert!(trait_def.generics.types
-                        .get_slice(subst::AssocSpace)
-                        .iter()
-                        .any(|type_param_def| type_param_def.def_id == associated_type_id));
-                let associated_type = ty::impl_or_trait_item(self.ccx.tcx, associated_type_id);
-                for impl_item in self.impl_items.iter() {
-                    match *impl_item {
-                        ast::MethodImplItem(_) => {}
-                        ast::TypeImplItem(ref typedef) => {
-                            if associated_type.name() == typedef.ident.name {
-                                return Some(self.ccx.to_ty(&ExplicitRscope, &*typedef.typ))
-                            }
-                        }
-                    }
-                }
-                self.ccx
-                    .tcx
-                    .sess
-                    .span_bug(span,
-                              "ImplCtxt::associated_type_binding(): didn't \
-                               find associated type")
-            }
-            Some(_) | None => {}
-        }
-
-        // OK then, it should be an associated type on one of the traits in
-        // our bounds.
-        find_associated_type_in_generics(self.ccx.tcx,
-                                         span,
-                                         self_ty,
-                                         associated_type_id,
-                                         self.impl_generics)
-    }
-}
-
-struct FnCtxt<'a,'tcx:'a> {
-    ccx: &'a CrateCtxt<'a,'tcx>,
-    generics: &'a ty::Generics<'tcx>,
-}
-
-impl<'a,'tcx> AstConv<'tcx> for FnCtxt<'a,'tcx> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> {
-        self.ccx.tcx
-    }
-
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
-        self.ccx.get_item_ty(id)
-    }
-
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        self.ccx.get_trait_def(id)
-    }
-
-    fn ty_infer(&self, span: Span) -> Ty<'tcx> {
-        self.ccx.ty_infer(span)
-    }
-
-    fn associated_types_of_trait_are_valid(&self,
-                                           ty: Ty<'tcx>,
-                                           trait_id: ast::DefId)
-                                           -> bool {
-        // OK if the trait with the associated type is one of the traits in
-        // our bounds.
-        is_associated_type_valid_for_param(ty, trait_id, self.generics)
-    }
-
-    fn associated_type_binding(&self,
-                               span: Span,
-                               self_ty: Option<Ty<'tcx>>,
-                               _: ast::DefId,
-                               associated_type_id: ast::DefId)
-                               -> Option<Ty<'tcx>> {
-        debug!("collect::FnCtxt::associated_type_binding()");
-
-        // The ID should map to an associated type on one of the traits in
-        // our bounds.
-        find_associated_type_in_generics(self.ccx.tcx,
-                                         span,
-                                         self_ty,
-                                         associated_type_id,
-                                         self.generics)
-    }
-}
-
-struct ImplMethodCtxt<'a,'tcx:'a> {
-    ccx: &'a CrateCtxt<'a,'tcx>,
-    method_generics: &'a ty::Generics<'tcx>,
-}
-
-impl<'a,'tcx> AstConv<'tcx> for ImplMethodCtxt<'a,'tcx> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> {
-        self.ccx.tcx
-    }
-
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
-        self.ccx.get_item_ty(id)
-    }
-
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        self.ccx.get_trait_def(id)
-    }
-
-    fn ty_infer(&self, span: Span) -> Ty<'tcx> {
-        self.ccx.ty_infer(span)
-    }
-
-    fn associated_types_of_trait_are_valid(&self,
-                                           ty: Ty<'tcx>,
-                                           trait_id: ast::DefId)
-                                           -> bool {
-        is_associated_type_valid_for_param(ty, trait_id, self.method_generics)
-    }
-
-    fn associated_type_binding(&self,
-                               span: Span,
-                               self_ty: Option<Ty<'tcx>>,
-                               _: ast::DefId,
-                               associated_type_id: ast::DefId)
-                               -> Option<Ty<'tcx>> {
-        debug!("collect::ImplMethodCtxt::associated_type_binding()");
-
-        // The ID should map to an associated type on one of the traits in
-        // our bounds.
-        find_associated_type_in_generics(self.ccx.tcx,
-                                         span,
-                                         self_ty,
-                                         associated_type_id,
-                                         self.method_generics)
-    }
-}
-
-struct TraitMethodCtxt<'a,'tcx:'a> {
-    ccx: &'a CrateCtxt<'a,'tcx>,
-    trait_id: ast::DefId,
-    trait_items: &'a [ast::TraitItem],
-    method_generics: &'a ty::Generics<'tcx>,
-}
-
-impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> {
-        self.ccx.tcx
-    }
-
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
-        self.ccx.get_item_ty(id)
-    }
-
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        self.ccx.get_trait_def(id)
-    }
-
-    fn ty_infer(&self, span: Span) -> Ty<'tcx> {
-        self.ccx.ty_infer(span)
-    }
-
-    fn associated_types_of_trait_are_valid(&self,
-                                           ty: Ty<'tcx>,
-                                           trait_id: ast::DefId)
-                                           -> bool {
-        // OK if the trait with the associated type is this trait.
-        if self.trait_id == trait_id && type_is_self(ty) {
-            return true
-        }
-
-        // OK if the trait with the associated type is one of the traits in
-        // our bounds.
-        is_associated_type_valid_for_param(ty, trait_id, self.method_generics)
-    }
-
-    fn associated_type_binding(&self,
-                               span: Span,
-                               self_ty: Option<Ty<'tcx>>,
-                               trait_id: ast::DefId,
-                               associated_type_id: ast::DefId)
-                               -> Option<Ty<'tcx>> {
-        debug!("collect::TraitMethodCtxt::associated_type_binding()");
-
-        // If this is one of our own associated types, return it.
-        if trait_id == self.trait_id {
-            let mut index = 0;
-            for item in self.trait_items.iter() {
-                match *item {
-                    ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
-                    ast::TypeTraitItem(ref item) => {
-                        if local_def(item.ty_param.id) == associated_type_id {
-                            return Some(ty::mk_param(self.tcx(),
-                                                     subst::AssocSpace,
-                                                     index,
-                                                     associated_type_id))
-                        }
-                        index += 1;
-                    }
-                }
-            }
-            self.ccx
-                .tcx
-                .sess
-                .span_bug(span,
-                          "TraitMethodCtxt::associated_type_binding(): \
-                           didn't find associated type anywhere in the item \
-                           list")
-        }
-
-        // The ID should map to an associated type on one of the traits in
-        // our bounds.
-        find_associated_type_in_generics(self.ccx.tcx,
-                                         span,
-                                         self_ty,
-                                         associated_type_id,
-                                         self.method_generics)
-    }
-}
-
-struct GenericsCtxt<'a,'tcx:'a,AC:'a> {
-    chain: &'a AC,
-    associated_types_generics: &'a ty::Generics<'tcx>,
-}
-
-impl<'a,'tcx,AC:AstConv<'tcx>> AstConv<'tcx> for GenericsCtxt<'a,'tcx,AC> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> {
-        self.chain.tcx()
-    }
-
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
-        self.chain.get_item_ty(id)
-    }
-
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        self.chain.get_trait_def(id)
-    }
-
-    fn ty_infer(&self, span: Span) -> Ty<'tcx> {
-        self.chain.ty_infer(span)
-    }
-
-    fn associated_types_of_trait_are_valid(&self,
-                                           ty: Ty<'tcx>,
-                                           trait_id: ast::DefId)
-                                           -> bool {
-        // OK if the trait with the associated type is one of the traits in
-        // our bounds.
-        is_associated_type_valid_for_param(ty,
-                                           trait_id,
-                                           self.associated_types_generics)
-    }
-
-    fn associated_type_binding(&self,
-                               span: Span,
-                               self_ty: Option<Ty<'tcx>>,
-                               _: ast::DefId,
-                               associated_type_id: ast::DefId)
-                               -> Option<Ty<'tcx>> {
-        debug!("collect::GenericsCtxt::associated_type_binding()");
-
-        // The ID should map to an associated type on one of the traits in
-        // our bounds.
-        find_associated_type_in_generics(self.chain.tcx(),
-                                         span,
-                                         self_ty,
-                                         associated_type_id,
-                                         self.associated_types_generics)
-    }
-}
-
 pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
     let tcx = ccx.tcx;
     debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
@@ -1039,11 +542,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
         // These don't define types.
         ast::ItemForeignMod(_) | ast::ItemMod(_) | ast::ItemMac(_) => {}
         ast::ItemEnum(ref enum_definition, ref generics) => {
-            let pty = ty_of_item(ccx, it);
-            write_ty_to_tcx(tcx, it.id, pty.ty);
+            let scheme = ty_of_item(ccx, it);
+            write_ty_to_tcx(tcx, it.id, scheme.ty);
             get_enum_variant_types(ccx,
-                                   pty.ty,
-                                   enum_definition.variants[],
+                                   scheme.ty,
+                                   enum_definition.variants.as_slice(),
                                    generics);
         },
         ast::ItemImpl(_,
@@ -1052,10 +555,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                       ref selfty,
                       ref impl_items) => {
             // Create generics from the generics specified in the impl head.
-            let ty_generics = ty_generics_for_type_or_impl(
-                    ccx,
-                    generics,
-                    CreateTypeParametersForAssociatedTypes);
+            let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
 
             let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
             write_ty_to_tcx(tcx, it.id, selfty);
@@ -1063,7 +563,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
             tcx.tcache
                .borrow_mut()
                .insert(local_def(it.id),
-                       Polytype {
+                       TypeScheme {
                         generics: ty_generics.clone(),
                         ty: selfty,
                        });
@@ -1079,20 +579,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                 it.vis
             };
 
-            let icx = ImplCtxt {
-                ccx: ccx,
-                opt_trait_ref_id: match *opt_trait_ref {
-                    None => None,
-                    Some(ref ast_trait_ref) => {
-                        Some(lookup_def_tcx(tcx,
-                                            ast_trait_ref.path.span,
-                                            ast_trait_ref.ref_id).def_id())
-                    }
-                },
-                impl_items: impl_items[],
-                impl_generics: &ty_generics,
-            };
-
             let mut methods = Vec::new();
             for impl_item in impl_items.iter() {
                 match *impl_item {
@@ -1106,11 +592,11 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                         methods.push(&**method);
                     }
                     ast::TypeImplItem(ref typedef) => {
-                        let typ = icx.to_ty(&ExplicitRscope, &*typedef.typ);
+                        let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
                         tcx.tcache
                            .borrow_mut()
                            .insert(local_def(typedef.id),
-                                   Polytype {
+                                   TypeScheme {
                                     generics: ty::Generics::empty(),
                                     ty: typ,
                                    });
@@ -1131,7 +617,6 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
             }
 
             convert_methods(ccx,
-                            ImplConvertMethodContext,
                             ImplContainer(local_def(it.id)),
                             methods.into_iter(),
                             selfty,
@@ -1139,14 +624,14 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                             parent_visibility);
 
             for trait_ref in opt_trait_ref.iter() {
-                astconv::instantiate_trait_ref(&icx,
+                astconv::instantiate_trait_ref(ccx,
                                                &ExplicitRscope,
                                                trait_ref,
                                                Some(selfty),
-                                               AllowEqConstraints::DontAllow);
+                                               None);
             }
         },
-        ast::ItemTrait(_, _, _, _, ref trait_methods) => {
+        ast::ItemTrait(_, _, _, ref trait_methods) => {
             let trait_def = trait_def_of_item(ccx, it);
 
             debug!("trait_def: ident={} trait_def={}",
@@ -1154,10 +639,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                    trait_def.repr(ccx.tcx()));
 
             for trait_method in trait_methods.iter() {
-                let self_type = ty::mk_param(ccx.tcx,
-                                             subst::SelfSpace,
-                                             0,
-                                             local_def(it.id));
+                let self_type = ty::mk_self_type(tcx);
                 match *trait_method {
                     ast::RequiredMethod(ref type_method) => {
                         let rscope = BindingRscope::new();
@@ -1183,13 +665,8 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
             }
 
             // Run convert_methods on the provided methods.
-            let untransformed_rcvr_ty = ty::mk_self_type(tcx,
-                                                         local_def(it.id));
-            let convert_method_context =
-                TraitConvertMethodContext(local_def(it.id),
-                                          trait_methods[]);
+            let untransformed_rcvr_ty = ty::mk_self_type(tcx);
             convert_methods(ccx,
-                            convert_method_context,
                             TraitContainer(local_def(it.id)),
                             trait_methods.iter().filter_map(|m| match *m {
                                 ast::RequiredMethod(_) => None,
@@ -1207,12 +684,12 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
         },
         ast::ItemStruct(ref struct_def, _) => {
             // Write the class type.
-            let pty = ty_of_item(ccx, it);
-            write_ty_to_tcx(tcx, it.id, pty.ty);
+            let scheme = ty_of_item(ccx, it);
+            write_ty_to_tcx(tcx, it.id, scheme.ty);
 
-            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
+            tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
 
-            convert_struct(ccx, &**struct_def, pty, it.id);
+            convert_struct(ccx, &**struct_def, scheme, it.id);
         },
         ast::ItemTy(_, ref generics) => {
             ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
@@ -1223,22 +700,22 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
             // This call populates the type cache with the converted type
             // of the item in passing. All we have to do here is to write
             // it into the node type table.
-            let pty = ty_of_item(ccx, it);
-            write_ty_to_tcx(tcx, it.id, pty.ty);
+            let scheme = ty_of_item(ccx, it);
+            write_ty_to_tcx(tcx, it.id, scheme.ty);
         },
     }
 }
 
 pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 struct_def: &ast::StructDef,
-                                pty: ty::Polytype<'tcx>,
+                                scheme: ty::TypeScheme<'tcx>,
                                 id: ast::NodeId) {
     let tcx = ccx.tcx;
 
     // Write the type of each of the members and check for duplicate fields.
     let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap::new();
     let field_tys = struct_def.fields.iter().map(|f| {
-        let result = convert_field(ccx, &pty.generics, f, local_def(id));
+        let result = convert_field(ccx, &scheme.generics, f, local_def(id));
 
         if result.name != special_idents::unnamed_field.name {
             let dup = match seen_fields.get(&result.name) {
@@ -1263,7 +740,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
 
-    let substs = mk_item_substs(ccx, &pty.generics);
+    let substs = mk_item_substs(ccx, &scheme.generics);
     let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
 
     // If this struct is enum-like or tuple-like, create the type of its
@@ -1275,7 +752,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 // Enum-like.
                 write_ty_to_tcx(tcx, ctor_id, selfty);
 
-                tcx.tcache.borrow_mut().insert(local_def(ctor_id), pty);
+                tcx.tcache.borrow_mut().insert(local_def(ctor_id), scheme);
             } else if struct_def.fields[0].node.kind.is_unnamed() {
                 // Tuple-like.
                 let inputs: Vec<_> = struct_def.fields.iter().map(
@@ -1287,8 +764,8 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                                 selfty);
                 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
                 tcx.tcache.borrow_mut().insert(local_def(ctor_id),
-                                  Polytype {
-                    generics: pty.generics,
+                                  TypeScheme {
+                    generics: scheme.generics,
                     ty: ctor_fn_ty
                 });
             }
@@ -1307,10 +784,10 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
     // convenient way to extract the ABI. - ndm
     let abi = ccx.tcx.map.get_foreign_abi(i.id);
 
-    let pty = ty_of_foreign_item(ccx, i, abi);
-    write_ty_to_tcx(ccx.tcx, i.id, pty.ty);
+    let scheme = ty_of_foreign_item(ccx, i, abi);
+    write_ty_to_tcx(ccx.tcx, i.id, scheme.ty);
 
-    ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), pty);
+    ccx.tcx.tcache.borrow_mut().insert(local_def(i.id), scheme);
 }
 
 fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
@@ -1331,20 +808,20 @@ fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
 pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    it: &ast::Item)
-                                   -> Rc<ty::TraitDef<'tcx>> {
+                                   -> Rc<ty::TraitDef<'tcx>>
+{
     let def_id = local_def(it.id);
     let tcx = ccx.tcx;
     if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
         return def.clone();
     }
 
-    let (unsafety, generics, unbound, bounds, items) = match it.node {
+    let (unsafety, generics, bounds, items) = match it.node {
         ast::ItemTrait(unsafety,
                        ref generics,
-                       ref unbound,
                        ref supertraits,
                        ref items) => {
-            (unsafety, generics, unbound, supertraits, items.as_slice())
+            (unsafety, generics, supertraits, items.as_slice())
         }
         ref s => {
             tcx.sess.span_bug(
@@ -1353,7 +830,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         }
     };
 
-    let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, it.id, generics, items));
+    let substs = ccx.tcx.mk_substs(mk_trait_substs(ccx, generics));
 
     let ty_generics = ty_generics_for_trait(ccx,
                                             it.id,
@@ -1361,33 +838,41 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                             generics,
                                             items);
 
-    let self_param_ty = ty::ParamTy::for_self(def_id);
+    let self_param_ty = ty::ParamTy::for_self();
 
     let bounds = compute_bounds(ccx,
-                                token::SELF_KEYWORD_NAME,
-                                self_param_ty,
+                                self_param_ty.to_ty(ccx.tcx),
                                 bounds.as_slice(),
-                                unbound,
                                 it.span);
 
-    let substs = mk_item_substs(ccx, &ty_generics);
+    let associated_type_names: Vec<_> =
+        items.iter()
+             .filter_map(|item| {
+                 match *item {
+                     ast::RequiredMethod(_) | ast::ProvidedMethod(_) => None,
+                     ast::TypeTraitItem(ref data) => Some(data.ty_param.ident.name),
+                 }
+             })
+            .collect();
+
+    let trait_ref = Rc::new(ty::TraitRef {
+        def_id: def_id,
+        substs: substs
+    });
+
     let trait_def = Rc::new(ty::TraitDef {
         unsafety: unsafety,
         generics: ty_generics,
         bounds: bounds,
-        trait_ref: Rc::new(ty::TraitRef {
-            def_id: def_id,
-            substs: ccx.tcx.mk_substs(substs)
-        })
+        trait_ref: trait_ref,
+        associated_type_names: associated_type_names,
     });
     tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
 
     return trait_def;
 
     fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                 trait_id: ast::NodeId,
-                                 generics: &ast::Generics,
-                                 items: &[ast::TraitItem])
+                                 generics: &ast::Generics)
                                  -> subst::Substs<'tcx>
     {
         // Creates a no-op substitution for the trait's type parameters.
@@ -1407,127 +892,92 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     .iter()
                     .enumerate()
                     .map(|(i, def)| ty::mk_param(ccx.tcx, subst::TypeSpace,
-                                                 i as u32, local_def(def.id)))
+                                                 i as u32, def.ident.name))
                     .collect();
 
-        // ...and also create generics synthesized from the associated types.
-        let mut index = 0;
-        let assoc_types: Vec<_> =
-            items.iter()
-            .flat_map(|item| match *item {
-                ast::TypeTraitItem(ref trait_item) => {
-                    index += 1;
-                    Some(ty::mk_param(ccx.tcx,
-                                      subst::AssocSpace,
-                                      index - 1,
-                                      local_def(trait_item.ty_param.id))).into_iter()
-                }
-                ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {
-                    None.into_iter()
-                }
-            })
-            .collect();
-
-        let self_ty =
-            ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
+        // ...and also create the `Self` parameter.
+        let self_ty = ty::mk_self_type(ccx.tcx);
 
-        subst::Substs::new_trait(types, regions, assoc_types, self_ty)
+        subst::Substs::new_trait(types, regions, self_ty)
     }
 }
 
 pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
-                            -> ty::Polytype<'tcx> {
+                            -> ty::TypeScheme<'tcx> {
     let def_id = local_def(it.id);
     let tcx = ccx.tcx;
-    if let Some(pty) = tcx.tcache.borrow().get(&def_id) {
-        return pty.clone();
+    if let Some(scheme) = tcx.tcache.borrow().get(&def_id) {
+        return scheme.clone();
     }
     match it.node {
         ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
             let typ = ccx.to_ty(&ExplicitRscope, &**t);
-            let pty = no_params(typ);
+            let scheme = no_params(typ);
 
-            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
-            return pty;
+            tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
+            return scheme;
         }
         ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
-            let ty_generics = ty_generics_for_fn_or_method(
-                ccx,
-                generics,
-                ty::Generics::empty(),
-                CreateTypeParametersForAssociatedTypes);
-            let tofd = {
-                let fcx = FnCtxt {
-                    ccx: ccx,
-                    generics: &ty_generics,
-                };
-                astconv::ty_of_bare_fn(&fcx, unsafety, abi, &**decl)
-            };
-            let pty = Polytype {
+            let ty_generics = ty_generics_for_fn_or_method(ccx,
+                                                           generics,
+                                                           ty::Generics::empty());
+            let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
+            let scheme = TypeScheme {
                 generics: ty_generics,
                 ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), ccx.tcx.mk_bare_fn(tofd))
             };
             debug!("type of {} (id {}) is {}",
                     token::get_ident(it.ident),
                     it.id,
-                    pty.repr(tcx));
+                    scheme.repr(tcx));
 
-            ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
-            return pty;
+            ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
+            return scheme;
         }
         ast::ItemTy(ref t, ref generics) => {
             match tcx.tcache.borrow_mut().get(&local_def(it.id)) {
-                Some(pty) => return pty.clone(),
+                Some(scheme) => return scheme.clone(),
                 None => { }
             }
 
-            let pty = {
+            let scheme = {
                 let ty = ccx.to_ty(&ExplicitRscope, &**t);
-                Polytype {
-                    generics: ty_generics_for_type_or_impl(
-                                  ccx,
-                                  generics,
-                                  DontCreateTypeParametersForAssociatedTypes),
+                TypeScheme {
+                    generics: ty_generics_for_type_or_impl(ccx, generics),
                     ty: ty
                 }
             };
 
-            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
-            return pty;
+            tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
+            return scheme;
         }
         ast::ItemEnum(_, ref generics) => {
             // Create a new generic polytype.
-            let ty_generics = ty_generics_for_type_or_impl(
-                ccx,
-                generics,
-                DontCreateTypeParametersForAssociatedTypes);
+            let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
             let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
-            let pty = Polytype {
+            let scheme = TypeScheme {
                 generics: ty_generics,
                 ty: t
             };
 
-            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
-            return pty;
+            tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
+            return scheme;
         }
         ast::ItemTrait(..) => {
             tcx.sess.span_bug(it.span, "invoked ty_of_item on trait");
         }
         ast::ItemStruct(_, ref generics) => {
-            let ty_generics = ty_generics_for_type_or_impl(
-                ccx,
-                generics,
-                DontCreateTypeParametersForAssociatedTypes);
+            let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
             let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
-            let pty = Polytype {
+            let scheme = TypeScheme {
                 generics: ty_generics,
                 ty: t
             };
 
-            tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
-            return pty;
+            tcx.tcache.borrow_mut().insert(local_def(it.id), scheme.clone());
+            return scheme;
         }
         ast::ItemImpl(..) | ast::ItemMod(_) |
         ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
@@ -1536,7 +986,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
 
 pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     it: &ast::ForeignItem,
-                                    abi: abi::Abi) -> ty::Polytype<'tcx>
+                                    abi: abi::Abi) -> ty::TypeScheme<'tcx>
 {
     match it.node {
         ast::ForeignItemFn(ref fn_decl, ref generics) => {
@@ -1547,7 +997,7 @@ pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                   abi)
         }
         ast::ForeignItemStatic(ref t, _) => {
-            ty::Polytype {
+            ty::TypeScheme {
                 generics: ty::Generics::empty(),
                 ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
             }
@@ -1555,81 +1005,34 @@ pub fn ty_of_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn ty_of_trait_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                              trait_item: &ast::TraitItem)
-                              -> ty::Polytype<'tcx> {
-    match *trait_item {
-        ast::RequiredMethod(ref m) => {
-            ccx.tcx.sess.span_bug(m.span,
-                                  "ty_of_trait_item() on required method")
-        }
-        ast::ProvidedMethod(ref m) => {
-            ccx.tcx.sess.span_bug(m.span,
-                                  "ty_of_trait_item() on provided method")
-        }
-        ast::TypeTraitItem(ref associated_type) => {
-            let parent = ccx.tcx.map.get_parent(associated_type.ty_param.id);
-            let trait_def = match ccx.tcx.map.get(parent) {
-                ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
-                _ => {
-                    ccx.tcx.sess.span_bug(associated_type.ty_param.span,
-                                          "associated type's parent wasn't \
-                                           an item?!")
-                }
-            };
-            convert_associated_type(ccx, &*trait_def, &**associated_type)
-        }
-    }
-}
-
 fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                          generics: &ast::Generics,
-                                          create_type_parameters_for_associated_types:
-                                          CreateTypeParametersForAssociatedTypesFlag)
+                                          generics: &ast::Generics)
                                           -> ty::Generics<'tcx> {
     ty_generics(ccx,
                 subst::TypeSpace,
                 generics.lifetimes[],
                 generics.ty_params[],
                 ty::Generics::empty(),
-                &generics.where_clause,
-                create_type_parameters_for_associated_types)
+                &generics.where_clause)
 }
 
 fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
                                    substs: &'tcx subst::Substs<'tcx>,
                                    ast_generics: &ast::Generics,
-                                   items: &[ast::TraitItem])
+                                   trait_items: &[ast::TraitItem])
                                    -> ty::Generics<'tcx>
 {
+    debug!("ty_generics_for_trait(trait_id={}, substs={})",
+           local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
+
     let mut generics =
         ty_generics(ccx,
                     subst::TypeSpace,
                     ast_generics.lifetimes[],
                     ast_generics.ty_params[],
                     ty::Generics::empty(),
-                    &ast_generics.where_clause,
-                    DontCreateTypeParametersForAssociatedTypes);
-
-    // Add in type parameters for any associated types.
-    for item in items.iter() {
-        match *item {
-            ast::TypeTraitItem(ref associated_type) => {
-                let def =
-                    get_or_create_type_parameter_def(
-                        ccx,
-                        subst::AssocSpace,
-                        &associated_type.ty_param,
-                        generics.types.len(subst::AssocSpace) as u32,
-                        Some(local_def(trait_id)));
-                ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
-                                                          def.clone());
-                generics.types.push(subst::AssocSpace, def);
-            }
-            ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {}
-        }
-    }
+                    &ast_generics.where_clause);
 
     // Add in the self type parameter.
     //
@@ -1638,8 +1041,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let param_id = trait_id;
 
     let self_trait_ref =
-        Rc::new(ty::Binder(ty::TraitRef { def_id: local_def(trait_id),
-                                          substs: substs }));
+        Rc::new(ty::TraitRef { def_id: local_def(trait_id),
+                               substs: substs });
 
     let def = ty::TypeParameterDef {
         space: subst::SelfSpace,
@@ -1649,9 +1052,9 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         bounds: ty::ParamBounds {
             region_bounds: vec!(),
             builtin_bounds: ty::empty_builtin_bounds(),
-            trait_bounds: vec!(self_trait_ref.clone()),
+            trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
+            projection_bounds: vec!(),
         },
-        associated_with: None,
         default: None
     };
 
@@ -1659,18 +1062,54 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     generics.types.push(subst::SelfSpace, def);
 
-    generics.predicates.push(subst::SelfSpace,
-                             ty::Predicate::Trait(self_trait_ref));
+    generics.predicates.push(subst::SelfSpace, self_trait_ref.as_predicate());
+
+    let assoc_predicates = predicates_for_associated_types(ccx,
+                                                           &self_trait_ref,
+                                                           trait_items);
+
+    debug!("ty_generics_for_trait: assoc_predicates={}", assoc_predicates.repr(ccx.tcx));
+
+    for assoc_predicate in assoc_predicates.into_iter() {
+        generics.predicates.push(subst::TypeSpace, assoc_predicate);
+    }
+
+    return generics;
 
-    generics
+    fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                                 self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
+                                                 trait_items: &[ast::TraitItem])
+                                                 -> Vec<ty::Predicate<'tcx>>
+    {
+        trait_items
+            .iter()
+            .flat_map(|trait_item| {
+                let assoc_type_def = match *trait_item {
+                    ast::TypeTraitItem(ref assoc_type) => &assoc_type.ty_param,
+                    ast::RequiredMethod(..) | ast::ProvidedMethod(..) => {
+                        return vec!().into_iter();
+                    }
+                };
+
+                let assoc_ty = ty::mk_projection(ccx.tcx,
+                                                 self_trait_ref.clone(),
+                                                 assoc_type_def.ident.name);
+
+                let bounds = compute_bounds(ccx,
+                                            assoc_ty,
+                                            assoc_type_def.bounds.as_slice(),
+                                            assoc_type_def.span);
+
+                ty::predicates(ccx.tcx, assoc_ty, &bounds).into_iter()
+            })
+            .collect()
+    }
 }
 
 fn ty_generics_for_fn_or_method<'tcx,AC>(
         this: &AC,
         generics: &ast::Generics,
-        base_generics: ty::Generics<'tcx>,
-        create_type_parameters_for_associated_types:
-        CreateTypeParametersForAssociatedTypesFlag)
+        base_generics: ty::Generics<'tcx>)
         -> ty::Generics<'tcx>
         where AC: AstConv<'tcx> {
     let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
@@ -1679,33 +1118,40 @@ fn ty_generics_for_fn_or_method<'tcx,AC>(
                 early_lifetimes[],
                 generics.ty_params[],
                 base_generics,
-                &generics.where_clause,
-                create_type_parameters_for_associated_types)
+                &generics.where_clause)
 }
 
-// Add the Sized bound, unless the type parameter is marked as `Sized?`.
+// Add the Sized bound, unless the type parameter is marked as `?Sized`.
 fn add_unsized_bound<'tcx,AC>(this: &AC,
-                              unbound: &Option<ast::TraitRef>,
                               bounds: &mut ty::BuiltinBounds,
-                              desc: &str,
+                              ast_bounds: &[ast::TyParamBound],
                               span: Span)
                               where AC: AstConv<'tcx> {
+    // Try to find an unbound in bounds.
+    let mut unbound = None;
+    for ab in ast_bounds.iter() {
+        if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab  {
+            if unbound.is_none() {
+                assert!(ptr.bound_lifetimes.is_empty());
+                unbound = Some(ptr.trait_ref.clone());
+            } else {
+                this.tcx().sess.span_err(span, "type parameter has more than one relaxed default \
+                                                bound, only one is supported");
+            }
+        }
+    }
+
     let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
     match unbound {
-        &Some(ref tpb) => {
+        Some(ref tpb) => {
             // FIXME(#8559) currently requires the unbound to be built-in.
             let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
             match kind_id {
                 Ok(kind_id) if trait_def_id != kind_id => {
                     this.tcx().sess.span_warn(span,
-                                              format!("default bound relaxed \
-                                                       for a {}, but this \
-                                                       does nothing because \
-                                                       the given bound is not \
-                                                       a default. \
-                                                       Only `Sized?` is \
-                                                       supported",
-                                                      desc)[]);
+                                              "default bound relaxed for a type parameter, but \
+                                               this does nothing because the given bound is not \
+                                               a default. Only `?Sized` is supported");
                     ty::try_add_builtin_trait(this.tcx(),
                                               kind_id,
                                               bounds);
@@ -1717,24 +1163,16 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
             ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
         }
         // No lang item for Sized, so we can't add it as a bound.
-        &None => {}
+        None => {}
     }
 }
 
-#[deriving(Clone, PartialEq, Eq)]
-enum CreateTypeParametersForAssociatedTypesFlag {
-    DontCreateTypeParametersForAssociatedTypes,
-    CreateTypeParametersForAssociatedTypes,
-}
-
 fn ty_generics<'tcx,AC>(this: &AC,
                         space: subst::ParamSpace,
                         lifetime_defs: &[ast::LifetimeDef],
                         types: &[ast::TyParam],
                         base_generics: ty::Generics<'tcx>,
-                        where_clause: &ast::WhereClause,
-                        create_type_parameters_for_associated_types_flag:
-                        CreateTypeParametersForAssociatedTypesFlag)
+                        where_clause: &ast::WhereClause)
                         -> ty::Generics<'tcx>
                         where AC: AstConv<'tcx>
 {
@@ -1755,46 +1193,18 @@ fn ty_generics<'tcx,AC>(this: &AC,
 
     assert!(result.types.is_empty_in(space));
 
-    // First, create the virtual type parameters for associated types if
-    // necessary.
-    let mut associated_types_generics = ty::Generics::empty();
-    match create_type_parameters_for_associated_types_flag {
-        DontCreateTypeParametersForAssociatedTypes => {}
-        CreateTypeParametersForAssociatedTypes => {
-            create_type_parameters_for_associated_types(this, space, types,
-                                                        &mut associated_types_generics);
-        }
-    }
-
     // Now create the real type parameters.
-    let gcx = GenericsCtxt {
-        chain: this,
-        associated_types_generics: &associated_types_generics,
-    };
     for (i, param) in types.iter().enumerate() {
-        let def = get_or_create_type_parameter_def(&gcx,
+        let def = get_or_create_type_parameter_def(this,
                                                    space,
                                                    param,
-                                                   i as u32,
-                                                   None);
+                                                   i as u32);
         debug!("ty_generics: def for type param: {}, {}",
                def.repr(this.tcx()),
                space);
         result.types.push(space, def);
     }
 
-    // Append the associated types to the result.
-    for associated_type_param in associated_types_generics.types
-                                                          .get_slice(space)
-                                                          .iter() {
-        assert!(result.types.get_slice(space).len() ==
-                associated_type_param.index as uint);
-        debug!("ty_generics: def for associated type: {}, {}",
-               associated_type_param.repr(this.tcx()),
-               space);
-        result.types.push(space, (*associated_type_param).clone());
-    }
-
     // Just for fun, also push the bounds from the type parameters
     // into the predicates list. This is currently kind of non-DRY.
     create_predicates(this.tcx(), &mut result, space);
@@ -1807,17 +1217,22 @@ fn ty_generics<'tcx,AC>(this: &AC,
 
                 for bound in bound_pred.bounds.iter() {
                     match bound {
-                        &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref) => {
+                        &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
+                            let mut projections = Vec::new();
+
                             let trait_ref = astconv::instantiate_poly_trait_ref(
                                 this,
                                 &ExplicitRscope,
-                                //@jroesch: for now trait_ref, poly_trait_ref?
                                 poly_trait_ref,
                                 Some(ty),
-                                AllowEqConstraints::Allow
+                                &mut projections,
                             );
 
-                            result.predicates.push(space, ty::Predicate::Trait(trait_ref));
+                            result.predicates.push(space, trait_ref.as_predicate());
+
+                            for projection in projections.iter() {
+                                result.predicates.push(space, projection.as_predicate());
+                            }
                         }
 
                         &ast::TyParamBound::RegionTyParamBound(ref lifetime) => {
@@ -1849,91 +1264,6 @@ fn ty_generics<'tcx,AC>(this: &AC,
 
     return result;
 
-    fn create_type_parameters_for_associated_types<'tcx, AC>(
-        this: &AC,
-        space: subst::ParamSpace,
-        types: &[ast::TyParam],
-        associated_types_generics: &mut ty::Generics<'tcx>)
-        where AC: AstConv<'tcx>
-    {
-        // The idea here is roughly as follows. We start with
-        // an item that is paramerized by various type parameters
-        // with bounds:
-        //
-        //    fn foo<T:Iterator>(t: T) { ... }
-        //
-        // The traits in those bounds declare associated types:
-        //
-        //    trait Iterator { type Elem; ... }
-        //
-        // And we rewrite the original function so that every associated
-        // type is bound to some fresh type parameter:
-        //
-        //    fn foo<A,T:Iterator<Elem=A>>(t: T) { ... }
-
-        // Number of synthetic type parameters created thus far
-        let mut index = 0;
-
-        // Iterate over the each type parameter `T` (from the example)
-        for param in types.iter() {
-            // Iterate over the bound `Iterator`
-            for bound in param.bounds.iter() {
-                // In the above example, `ast_trait_ref` is `Iterator`.
-                let ast_trait_ref = match *bound {
-                    ast::TraitTyParamBound(ref r) => r,
-                    ast::RegionTyParamBound(..) => { continue; }
-                };
-
-                let trait_def_id =
-                    match lookup_def_tcx(this.tcx(),
-                                         ast_trait_ref.trait_ref.path.span,
-                                         ast_trait_ref.trait_ref.ref_id) {
-                        def::DefTrait(trait_def_id) => trait_def_id,
-                        _ => {
-                            this.tcx().sess.span_bug(ast_trait_ref.trait_ref.path.span,
-                                                     "not a trait?!")
-                        }
-                    };
-
-                // trait_def_id is def-id of `Iterator`
-                let trait_def = ty::lookup_trait_def(this.tcx(), trait_def_id);
-                let associated_type_defs = trait_def.generics.types.get_slice(subst::AssocSpace);
-
-                // Find any associated type bindings in the bound.
-                let ref segments = ast_trait_ref.trait_ref.path.segments;
-                let bindings = segments[segments.len() -1].parameters.bindings();
-
-                // Iterate over each associated type `Elem`
-                for associated_type_def in associated_type_defs.iter() {
-                    if bindings.iter().any(|b| associated_type_def.name.ident() == b.ident) {
-                        // Don't add a variable for a bound associated type.
-                        continue;
-                    }
-
-                    // Create the fresh type parameter `A`
-                    let def = ty::TypeParameterDef {
-                        name: associated_type_def.name,
-                        def_id: associated_type_def.def_id,
-                        space: space,
-                        index: types.len() as u32 + index,
-                        bounds: ty::ParamBounds {
-                            builtin_bounds: associated_type_def.bounds.builtin_bounds,
-
-                            // FIXME(#18178) -- we should add the other bounds, but
-                            // that requires subst and more logic
-                            trait_bounds: Vec::new(),
-                            region_bounds: Vec::new(),
-                        },
-                        associated_with: Some(local_def(param.id)),
-                        default: None,
-                    };
-                    associated_types_generics.types.push(space, def);
-                    index += 1;
-                }
-            }
-        }
-    }
-
     fn create_predicates<'tcx>(
         tcx: &ty::ctxt<'tcx>,
         result: &mut ty::Generics<'tcx>,
@@ -1963,8 +1293,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
 fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
                                              space: subst::ParamSpace,
                                              param: &ast::TyParam,
-                                             index: u32,
-                                             associated_with: Option<ast::DefId>)
+                                             index: u32)
                                              -> ty::TypeParameterDef<'tcx>
     where AC: AstConv<'tcx>
 {
@@ -1973,12 +1302,10 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
         None => { }
     }
 
-    let param_ty = ty::ParamTy::new(space, index, local_def(param.id));
+    let param_ty = ty::ParamTy::new(space, index, param.ident.name);
     let bounds = compute_bounds(this,
-                                param.ident.name,
-                                param_ty,
+                                param_ty.to_ty(this.tcx()),
                                 param.bounds[],
-                                &param.unbound,
                                 param.span);
     let default = match param.default {
         None => None,
@@ -2006,7 +1333,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
         index: index,
         name: param.ident.name,
         def_id: local_def(param.id),
-        associated_with: associated_with,
         bounds: bounds,
         default: default
     };
@@ -2020,10 +1346,8 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
 fn compute_bounds<'tcx,AC>(this: &AC,
-                           name_of_bounded_thing: ast::Name,
-                           param_ty: ty::ParamTy,
+                           param_ty: ty::Ty<'tcx>,
                            ast_bounds: &[ast::TyParamBound],
-                           unbound: &Option<ast::TraitRef>,
                            span: Span)
                            -> ty::ParamBounds<'tcx>
                            where AC: AstConv<'tcx> {
@@ -2032,15 +1356,13 @@ fn compute_bounds<'tcx,AC>(this: &AC,
                                              param_ty,
                                              ast_bounds);
 
-
     add_unsized_bound(this,
-                      unbound,
                       &mut param_bounds.builtin_bounds,
-                      "type parameter",
+                      ast_bounds,
                       span);
 
     check_bounds_compatible(this.tcx(),
-                            name_of_bounded_thing,
+                            param_ty,
                             &param_bounds,
                             span);
 
@@ -2050,7 +1372,7 @@ fn compute_bounds<'tcx,AC>(this: &AC,
 }
 
 fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                 name_of_bounded_thing: ast::Name,
+                                 param_ty: Ty<'tcx>,
                                  param_bounds: &ty::ParamBounds<'tcx>,
                                  span: Span) {
     // Currently the only bound which is incompatible with other bounds is
@@ -2063,9 +1385,9 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
                 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id());
                 if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
                     span_err!(tcx.sess, span, E0129,
-                              "incompatible bounds on type parameter `{}`, \
+                              "incompatible bounds on `{}`, \
                                bound `{}` does not allow unsized type",
-                              name_of_bounded_thing.user_string(tcx),
+                              param_ty.user_string(tcx),
                               trait_ref.user_string(tcx));
                 }
                 true
@@ -2075,7 +1397,7 @@ fn check_bounds_compatible<'tcx>(tcx: &ty::ctxt<'tcx>,
 
 fn conv_param_bounds<'tcx,AC>(this: &AC,
                               span: Span,
-                              param_ty: ty::ParamTy,
+                              param_ty: ty::Ty<'tcx>,
                               ast_bounds: &[ast::TyParamBound])
                               -> ty::ParamBounds<'tcx>
                               where AC: AstConv<'tcx>
@@ -2084,14 +1406,17 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
                                      trait_bounds,
                                      region_bounds } =
         astconv::partition_bounds(this.tcx(), span, ast_bounds.as_slice());
-    let trait_bounds: Vec<Rc<ty::PolyTraitRef>> =
+
+    let mut projection_bounds = Vec::new();
+
+    let trait_bounds: Vec<ty::PolyTraitRef> =
         trait_bounds.into_iter()
         .map(|bound| {
             astconv::instantiate_poly_trait_ref(this,
                                                 &ExplicitRscope,
                                                 bound,
-                                                Some(param_ty.to_ty(this.tcx())),
-                                                AllowEqConstraints::Allow)
+                                                Some(param_ty),
+                                                &mut projection_bounds)
         })
         .collect();
     let region_bounds: Vec<ty::Region> =
@@ -2102,6 +1427,7 @@ fn conv_param_bounds<'tcx,AC>(this: &AC,
         region_bounds: region_bounds,
         builtin_bounds: builtin_bounds,
         trait_bounds: trait_bounds,
+        projection_bounds: projection_bounds,
     }
 }
 
@@ -2110,7 +1436,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                        def_id: ast::DefId,
                                        ast_generics: &ast::Generics,
                                        abi: abi::Abi)
-                                       -> ty::Polytype<'tcx> {
+                                       -> ty::TypeScheme<'tcx> {
     for i in decl.inputs.iter() {
         match (*i).pat.node {
             ast::PatIdent(_, _, _) => (),
@@ -2122,11 +1448,9 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         }
     }
 
-    let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(
-            ccx,
-            ast_generics,
-            ty::Generics::empty(),
-            DontCreateTypeParametersForAssociatedTypes);
+    let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx,
+                                                                    ast_generics,
+                                                                    ty::Generics::empty());
     let rb = BindingRscope::new();
     let input_tys = decl.inputs
                         .iter()
@@ -2147,16 +1471,16 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             abi: abi,
             unsafety: ast::Unsafety::Unsafe,
             sig: ty::Binder(ty::FnSig {inputs: input_tys,
-                            output: output,
-                            variadic: decl.variadic})
+                                       output: output,
+                                       variadic: decl.variadic}),
         }));
-    let pty = Polytype {
+    let scheme = TypeScheme {
         generics: ty_generics_for_fn_or_method,
         ty: t_fn
     };
 
-    ccx.tcx.tcache.borrow_mut().insert(def_id, pty.clone());
-    return pty;
+    ccx.tcx.tcache.borrow_mut().insert(def_id, scheme.clone());
+    return scheme;
 }
 
 pub fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 3418cded022..353db82eb02 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -159,8 +159,8 @@ fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
     lookup_def_tcx(ccx.tcx, sp, id)
 }
 
-fn no_params<'tcx>(t: Ty<'tcx>) -> ty::Polytype<'tcx> {
-    ty::Polytype {
+fn no_params<'tcx>(t: Ty<'tcx>) -> ty::TypeScheme<'tcx> {
+    ty::TypeScheme {
         generics: ty::Generics {
             types: VecPerParamSpace::empty(),
             regions: VecPerParamSpace::empty(),
@@ -278,11 +278,11 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: vec!(
-                        ty::mk_int(),
-                        ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8()))
+                        tcx.types.int,
+                        ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, tcx.types.u8))
                     ),
-                    output: ty::FnConverging(ty::mk_int()),
-                    variadic: false
+                    output: ty::FnConverging(tcx.types.int),
+                    variadic: false,
                 }),
             }));
 
diff --git a/src/librustc_typeck/rscope.rs b/src/librustc_typeck/rscope.rs
index a97dce88a57..c62218313f4 100644
--- a/src/librustc_typeck/rscope.rs
+++ b/src/librustc_typeck/rscope.rs
@@ -13,6 +13,7 @@ use middle::ty;
 use middle::ty_fold;
 
 use std::cell::Cell;
+use std::iter::repeat;
 use syntax::codemap::Span;
 
 /// Defines strategies for handling regions that are omitted.  For
@@ -99,7 +100,7 @@ impl RegionScope for SpecificRscope {
                     count: uint)
                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
     {
-        Ok(Vec::from_elem(count, self.default))
+        Ok(repeat(self.default).take(count).collect())
     }
 }
 
@@ -134,7 +135,7 @@ impl RegionScope for BindingRscope {
                     count: uint)
                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
     {
-        Ok(Vec::from_fn(count, |_| self.next_region()))
+        Ok(range(0, count).map(|_| self.next_region()).collect())
     }
 }
 
diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs
index bdd8c7c3da7..a17f3b31be3 100644
--- a/src/librustc_typeck/variance.rs
+++ b/src/librustc_typeck/variance.rs
@@ -199,6 +199,7 @@ use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace}
 use middle::ty::{mod, Ty};
 use std::fmt;
 use std::rc::Rc;
+use std::iter::repeat;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util;
@@ -353,7 +354,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
         match item.node {
             ast::ItemEnum(_, ref generics) |
             ast::ItemStruct(_, ref generics) |
-            ast::ItemTrait(_, ref generics, _, _, _) => {
+            ast::ItemTrait(_, ref generics, _, _) => {
                 for (i, p) in generics.lifetimes.iter().enumerate() {
                     let id = p.lifetime.id;
                     self.add_inferred(item.id, RegionParam, TypeSpace, i, id);
@@ -406,9 +407,9 @@ struct ConstraintContext<'a, 'tcx: 'a> {
     // are indexed by the `ParamKind` (type, lifetime, self). Note
     // that there are no marker types for self, so the entries for
     // self are always None.
-    invariant_lang_items: [Option<ast::DefId>, ..2],
-    covariant_lang_items: [Option<ast::DefId>, ..2],
-    contravariant_lang_items: [Option<ast::DefId>, ..2],
+    invariant_lang_items: [Option<ast::DefId>; 2],
+    covariant_lang_items: [Option<ast::DefId>; 2],
+    contravariant_lang_items: [Option<ast::DefId>; 2],
     unsafe_lang_item: Option<ast::DefId>,
 
     // These are pointers to common `ConstantTerm` instances
@@ -431,9 +432,9 @@ struct Constraint<'a> {
 fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>,
                                         krate: &ast::Crate)
                                         -> ConstraintContext<'a, 'tcx> {
-    let mut invariant_lang_items = [None, ..2];
-    let mut covariant_lang_items = [None, ..2];
-    let mut contravariant_lang_items = [None, ..2];
+    let mut invariant_lang_items = [None; 2];
+    let mut covariant_lang_items = [None; 2];
+    let mut contravariant_lang_items = [None; 2];
 
     covariant_lang_items[TypeParam as uint] =
         terms_cx.tcx.lang_items.covariant_type();
@@ -479,8 +480,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
         let did = ast_util::local_def(item.id);
         let tcx = self.terms_cx.tcx;
 
+        debug!("visit_item item={}",
+               item.repr(tcx));
+
         match item.node {
             ast::ItemEnum(ref enum_definition, _) => {
+                let generics = &ty::lookup_item_type(tcx, did).generics;
+
                 // Hack: If we directly call `ty::enum_variants`, it
                 // annoyingly takes it upon itself to run off and
                 // evaluate the discriminants eagerly (*grumpy* that's
@@ -497,17 +503,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
                                                           &**ast_variant,
                                                           /*discriminant*/ 0);
                     for arg_ty in variant.args.iter() {
-                        self.add_constraints_from_ty(*arg_ty, self.covariant);
+                        self.add_constraints_from_ty(generics, *arg_ty, self.covariant);
                     }
                 }
             }
 
             ast::ItemStruct(..) => {
+                let generics = &ty::lookup_item_type(tcx, did).generics;
                 let struct_fields = ty::lookup_struct_fields(tcx, did);
                 for field_info in struct_fields.iter() {
                     assert_eq!(field_info.id.krate, ast::LOCAL_CRATE);
                     let field_ty = ty::node_id_to_type(tcx, field_info.id.node);
-                    self.add_constraints_from_ty(field_ty, self.covariant);
+                    self.add_constraints_from_ty(generics, field_ty, self.covariant);
                 }
             }
 
@@ -516,7 +523,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
                 for trait_item in trait_items.iter() {
                     match *trait_item {
                         ty::MethodTraitItem(ref method) => {
-                            self.add_constraints_from_sig(&method.fty.sig,
+                            self.add_constraints_from_sig(&method.generics,
+                                                          &method.fty.sig,
                                                           self.covariant);
                         }
                         ty::TypeTraitItem(_) => {}
@@ -585,7 +593,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         // parameter (by inspecting parent of its binding declaration
         // to see if it is introduced by a type or by a fn/impl).
 
-        let check_result = |this:&ConstraintContext| -> bool {
+        let check_result = |&: this:&ConstraintContext| -> bool {
             let tcx = this.terms_cx.tcx;
             let decl_id = this.find_binding_for_lifetime(param_id);
             // Currently only called on lifetimes; double-checking that.
@@ -713,8 +721,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     }
 
     /// Adds constraints appropriate for an instance of `ty` appearing
-    /// in a context with ambient variance `variance`
+    /// in a context with the generics defined in `generics` and
+    /// ambient variance `variance`
     fn add_constraints_from_ty(&mut self,
+                               generics: &ty::Generics<'tcx>,
                                ty: Ty<'tcx>,
                                variance: VarianceTermPtr<'a>) {
         debug!("add_constraints_from_ty(ty={})", ty.repr(self.tcx()));
@@ -732,75 +742,82 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
             ty::ty_rptr(region, ref mt) => {
                 let contra = self.contravariant(variance);
-                self.add_constraints_from_region(*region, contra);
-                self.add_constraints_from_mt(mt, variance);
+                self.add_constraints_from_region(generics, *region, contra);
+                self.add_constraints_from_mt(generics, mt, variance);
             }
 
             ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
-                self.add_constraints_from_ty(typ, variance);
+                self.add_constraints_from_ty(generics, typ, variance);
             }
 
             ty::ty_ptr(ref mt) => {
-                self.add_constraints_from_mt(mt, variance);
+                self.add_constraints_from_mt(generics, mt, variance);
             }
 
             ty::ty_tup(ref subtys) => {
                 for &subty in subtys.iter() {
-                    self.add_constraints_from_ty(subty, variance);
+                    self.add_constraints_from_ty(generics, subty, variance);
                 }
             }
 
             ty::ty_enum(def_id, substs) |
             ty::ty_struct(def_id, substs) => {
                 let item_type = ty::lookup_item_type(self.tcx(), def_id);
-                let generics = &item_type.generics;
 
                 // All type parameters on enums and structs should be
                 // in the TypeSpace.
-                assert!(generics.types.is_empty_in(subst::SelfSpace));
-                assert!(generics.types.is_empty_in(subst::FnSpace));
-                assert!(generics.regions.is_empty_in(subst::SelfSpace));
-                assert!(generics.regions.is_empty_in(subst::FnSpace));
+                assert!(item_type.generics.types.is_empty_in(subst::SelfSpace));
+                assert!(item_type.generics.types.is_empty_in(subst::FnSpace));
+                assert!(item_type.generics.regions.is_empty_in(subst::SelfSpace));
+                assert!(item_type.generics.regions.is_empty_in(subst::FnSpace));
 
                 self.add_constraints_from_substs(
+                    generics,
                     def_id,
-                    generics.types.get_slice(subst::TypeSpace),
-                    generics.regions.get_slice(subst::TypeSpace),
+                    item_type.generics.types.get_slice(subst::TypeSpace),
+                    item_type.generics.regions.get_slice(subst::TypeSpace),
                     substs,
                     variance);
             }
 
-            ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
-                let trait_def = ty::lookup_trait_def(self.tcx(), principal.def_id());
-                let generics = &trait_def.generics;
+            ty::ty_projection(ref data) => {
+                let trait_ref = &data.trait_ref;
+                let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id);
+                self.add_constraints_from_substs(
+                    generics,
+                    trait_ref.def_id,
+                    trait_def.generics.types.as_slice(),
+                    trait_def.generics.regions.as_slice(),
+                    trait_ref.substs,
+                    variance);
+            }
 
-                // Traits DO have a Self type parameter, but it is
-                // erased from object types.
-                assert!(!generics.types.is_empty_in(subst::SelfSpace) &&
-                        principal.substs().types.is_empty_in(subst::SelfSpace));
+            ty::ty_trait(ref data) => {
+                let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(),
+                                                                      self.tcx().types.err);
+                let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id());
 
                 // Traits never declare region parameters in the self
-                // space.
-                assert!(generics.regions.is_empty_in(subst::SelfSpace));
-
-                // Traits never declare type/region parameters in the
-                // fn space.
-                assert!(generics.types.is_empty_in(subst::FnSpace));
-                assert!(generics.regions.is_empty_in(subst::FnSpace));
+                // space nor anything in the fn space.
+                assert!(trait_def.generics.regions.is_empty_in(subst::SelfSpace));
+                assert!(trait_def.generics.types.is_empty_in(subst::FnSpace));
+                assert!(trait_def.generics.regions.is_empty_in(subst::FnSpace));
 
                 // The type `Foo<T+'a>` is contravariant w/r/t `'a`:
                 let contra = self.contravariant(variance);
-                self.add_constraints_from_region(bounds.region_bound, contra);
+                self.add_constraints_from_region(generics, data.bounds.region_bound, contra);
 
                 self.add_constraints_from_substs(
-                    principal.def_id(),
-                    generics.types.get_slice(subst::TypeSpace),
-                    generics.regions.get_slice(subst::TypeSpace),
-                    principal.substs(),
+                    generics,
+                    trait_ref.def_id(),
+                    trait_def.generics.types.get_slice(subst::TypeSpace),
+                    trait_def.generics.regions.get_slice(subst::TypeSpace),
+                    trait_ref.substs(),
                     variance);
             }
 
-            ty::ty_param(ty::ParamTy { ref def_id, .. }) => {
+            ty::ty_param(ref data) => {
+                let def_id = generics.types.get(data.space, data.idx as uint).def_id;
                 assert_eq!(def_id.krate, ast::LOCAL_CRATE);
                 match self.terms_cx.inferred_map.get(&def_id.node) {
                     Some(&index) => {
@@ -821,14 +838,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                     ..
                 }) =>
             {
-                self.add_constraints_from_sig(sig, variance);
+                self.add_constraints_from_sig(generics, sig, variance);
             }
 
             ty::ty_closure(box ty::ClosureTy { ref sig,
                     store: ty::RegionTraitStore(region, _), .. }) => {
                 let contra = self.contravariant(variance);
-                self.add_constraints_from_region(region, contra);
-                self.add_constraints_from_sig(sig, variance);
+                self.add_constraints_from_region(generics, region, contra);
+                self.add_constraints_from_sig(generics, sig, variance);
             }
 
             ty::ty_infer(..) | ty::ty_err => {
@@ -844,6 +861,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     /// Adds constraints appropriate for a nominal type (enum, struct,
     /// object, etc) appearing in a context with ambient variance `variance`
     fn add_constraints_from_substs(&mut self,
+                                   generics: &ty::Generics<'tcx>,
                                    def_id: ast::DefId,
                                    type_param_defs: &[ty::TypeParameterDef<'tcx>],
                                    region_param_defs: &[ty::RegionParameterDef],
@@ -857,7 +875,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                        p.space, p.index as uint);
             let variance_i = self.xform(variance, variance_decl);
             let substs_ty = *substs.types.get(p.space, p.index as uint);
-            self.add_constraints_from_ty(substs_ty, variance_i);
+            self.add_constraints_from_ty(generics, substs_ty, variance_i);
         }
 
         for p in region_param_defs.iter() {
@@ -866,27 +884,29 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                        RegionParam, p.space, p.index as uint);
             let variance_i = self.xform(variance, variance_decl);
             let substs_r = *substs.regions().get(p.space, p.index as uint);
-            self.add_constraints_from_region(substs_r, variance_i);
+            self.add_constraints_from_region(generics, substs_r, variance_i);
         }
     }
 
     /// Adds constraints appropriate for a function with signature
     /// `sig` appearing in a context with ambient variance `variance`
     fn add_constraints_from_sig(&mut self,
+                                generics: &ty::Generics<'tcx>,
                                 sig: &ty::PolyFnSig<'tcx>,
                                 variance: VarianceTermPtr<'a>) {
         let contra = self.contravariant(variance);
         for &input in sig.0.inputs.iter() {
-            self.add_constraints_from_ty(input, contra);
+            self.add_constraints_from_ty(generics, input, contra);
         }
         if let ty::FnConverging(result_type) = sig.0.output {
-            self.add_constraints_from_ty(result_type, variance);
+            self.add_constraints_from_ty(generics, result_type, variance);
         }
     }
 
     /// Adds constraints appropriate for a region appearing in a
     /// context with ambient variance `variance`
     fn add_constraints_from_region(&mut self,
+                                   _generics: &ty::Generics<'tcx>,
                                    region: ty::Region,
                                    variance: VarianceTermPtr<'a>) {
         match region {
@@ -920,16 +940,17 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     /// Adds constraints appropriate for a mutability-type pair
     /// appearing in a context with ambient variance `variance`
     fn add_constraints_from_mt(&mut self,
+                               generics: &ty::Generics<'tcx>,
                                mt: &ty::mt<'tcx>,
                                variance: VarianceTermPtr<'a>) {
         match mt.mutbl {
             ast::MutMutable => {
                 let invar = self.invariant(variance);
-                self.add_constraints_from_ty(mt.ty, invar);
+                self.add_constraints_from_ty(generics, mt.ty, invar);
             }
 
             ast::MutImmutable => {
-                self.add_constraints_from_ty(mt.ty, variance);
+                self.add_constraints_from_ty(generics, mt.ty, variance);
             }
         }
     }
@@ -951,7 +972,7 @@ struct SolveContext<'a, 'tcx: 'a> {
 
 fn solve_constraints(constraints_cx: ConstraintContext) {
     let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
-    let solutions = Vec::from_elem(terms_cx.num_inferred(), ty::Bivariant);
+    let solutions: Vec<_> = repeat(ty::Bivariant).take(terms_cx.num_inferred()).collect();
     let mut solutions_cx = SolveContext {
         terms_cx: terms_cx,
         constraints: constraints,
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index cdc51bb801c..3eda39f54a9 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -163,13 +163,12 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt,
         }
     });
     let trait_def = ty::lookup_trait_def(tcx, did);
-    let (bounds, default_unbound) = trait_def.bounds.clean(cx);
+    let bounds = trait_def.bounds.clean(cx);
     clean::Trait {
         unsafety: def.unsafety,
         generics: (&def.generics, subst::TypeSpace).clean(cx),
         items: items.collect(),
         bounds: bounds,
-        default_unbound: default_unbound
     }
 }
 
@@ -328,7 +327,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
             derived: clean::detect_derived(attrs.as_slice()),
             trait_: associated_trait.clean(cx).map(|bound| {
                 match bound {
-                    clean::TraitBound(polyt) => polyt.trait_,
+                    clean::TraitBound(polyt, _) => polyt.trait_,
                     clean::RegionBound(..) => unreachable!(),
                 }
             }),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0308194527e..459d6409f67 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -34,8 +34,7 @@ use syntax::ast_util::PostExpansionMethod;
 use syntax::attr;
 use syntax::attr::{AttributeMethods, AttrMetaMethods};
 use syntax::codemap::{DUMMY_SP, Pos, Spanned};
-use syntax::parse::token::InternedString;
-use syntax::parse::token;
+use syntax::parse::token::{mod, InternedString, special_idents};
 use syntax::ptr::P;
 
 use rustc_trans::back::link;
@@ -458,8 +457,6 @@ pub struct TyParam {
     pub did: ast::DefId,
     pub bounds: Vec<TyParamBound>,
     pub default: Option<Type>,
-    /// An optional default bound on the parameter which is unbound, like `Sized?`
-    pub default_unbound: Option<Type>
 }
 
 impl Clean<TyParam> for ast::TyParam {
@@ -469,7 +466,6 @@ impl Clean<TyParam> for ast::TyParam {
             did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
             bounds: self.bounds.clean(cx),
             default: self.default.clean(cx),
-            default_unbound: self.unbound.clean(cx)
         }
     }
 }
@@ -478,13 +474,12 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
     fn clean(&self, cx: &DocContext) -> TyParam {
         cx.external_typarams.borrow_mut().as_mut().unwrap()
           .insert(self.def_id, self.name.clean(cx));
-        let (bounds, default_unbound) = self.bounds.clean(cx);
+        let bounds = self.bounds.clean(cx);
         TyParam {
             name: self.name.clean(cx),
             did: self.def_id,
             bounds: bounds,
             default: self.default.clean(cx),
-            default_unbound: default_unbound
         }
     }
 }
@@ -492,25 +487,28 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
 #[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)]
 pub enum TyParamBound {
     RegionBound(Lifetime),
-    TraitBound(PolyTrait)
+    TraitBound(PolyTrait, ast::TraitBoundModifier)
 }
 
 impl Clean<TyParamBound> for ast::TyParamBound {
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         match *self {
             ast::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
-            ast::TraitTyParamBound(ref t) => TraitBound(t.clean(cx)),
+            ast::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
         }
     }
 }
 
-impl Clean<Vec<TyParamBound>> for ty::ExistentialBounds {
+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)));
         for bb in self.builtin_bounds.iter() {
             vec.push(bb.clean(cx));
         }
+
+        // FIXME(#20299) -- should do something with projection bounds
+
         vec
     }
 }
@@ -600,7 +598,7 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
                 did: did,
             },
             lifetimes: vec![]
-        })
+        }, ast::TraitBoundModifier::None)
     }
 }
 
@@ -648,37 +646,20 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
         TraitBound(PolyTrait {
             trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, },
             lifetimes: late_bounds
-        })
+        }, ast::TraitBoundModifier::None)
     }
 }
 
-// Returns (bounds, default_unbound)
-impl<'tcx> Clean<(Vec<TyParamBound>, Option<Type>)> for ty::ParamBounds<'tcx> {
-    fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Option<Type>) {
+impl<'tcx> Clean<Vec<TyParamBound>> for ty::ParamBounds<'tcx> {
+    fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
         let mut v = Vec::new();
-        let mut has_sized_bound = false;
-        for b in self.builtin_bounds.iter() {
-            if b != ty::BoundSized {
-                v.push(b.clean(cx));
-            } else {
-                has_sized_bound = true;
-            }
-        }
         for t in self.trait_bounds.iter() {
             v.push(t.clean(cx));
         }
         for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) {
             v.push(RegionBound(r));
         }
-        if has_sized_bound {
-            (v, None)
-        } else {
-            let ty = match ty::BoundSized.clean(cx) {
-                TraitBound(polyt) => polyt.trait_,
-                _ => unreachable!()
-            };
-            (v, Some(ty))
-        }
+        v
     }
 }
 
@@ -689,7 +670,7 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
         v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
             trait_: t.clean(cx),
             lifetimes: vec![]
-        })));
+        }, ast::TraitBoundModifier::None)));
         if v.len() > 0 {Some(v)} else {None}
     }
 }
@@ -1047,8 +1028,6 @@ pub struct Trait {
     pub items: Vec<TraitMethod>,
     pub generics: Generics,
     pub bounds: Vec<TyParamBound>,
-    /// An optional default bound not required for `Self`, like `Sized?`
-    pub default_unbound: Option<Type>
 }
 
 impl Clean<Item> for doctree::Trait {
@@ -1065,7 +1044,6 @@ impl Clean<Item> for doctree::Trait {
                 items: self.items.clean(cx),
                 generics: self.generics.clean(cx),
                 bounds: self.bounds.clean(cx),
-                default_unbound: self.default_unbound.clean(cx)
             }),
         }
     }
@@ -1223,11 +1201,9 @@ pub enum Type {
     },
     // I have no idea how to usefully use this.
     TyParamBinder(ast::NodeId),
-    /// For parameterized types, so the consumer of the JSON don't go looking
-    /// for types which don't exist anywhere.
-    Generic(ast::DefId),
-    /// For references to self
-    Self(ast::DefId),
+    /// For parameterized types, so the consumer of the JSON don't go
+    /// looking for types which don't exist anywhere.
+    Generic(String),
     /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
     Primitive(PrimitiveType),
     Closure(Box<ClosureDecl>),
@@ -1465,18 +1441,11 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 }
             }
             ty::ty_struct(did, substs) |
-            ty::ty_enum(did, substs) |
-            ty::ty_trait(box ty::TyTrait {
-                principal: ty::Binder(ty::TraitRef { def_id: did, substs }),
-                .. }) =>
-            {
+            ty::ty_enum(did, substs) => {
                 let fqn = csearch::get_item_path(cx.tcx(), did);
-                let fqn: Vec<String> = fqn.into_iter().map(|i| {
-                    i.to_string()
-                }).collect();
+                let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
                 let kind = match self.sty {
                     ty::ty_struct(..) => TypeStruct,
-                    ty::ty_trait(..) => TypeTrait,
                     _ => TypeEnum,
                 };
                 let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
@@ -1488,16 +1457,35 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     did: did,
                 }
             }
+            ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
+                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 path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
+                                         Some(did), principal.substs());
+                cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, TypeTrait));
+                ResolvedPath {
+                    path: path,
+                    typarams: Some(bounds.clean(cx)),
+                    did: did,
+                }
+            }
             ty::ty_tup(ref t) => Tuple(t.clean(cx)),
 
-            ty::ty_param(ref p) => {
-                if p.space == subst::SelfSpace {
-                    Self(p.def_id)
-                } else {
-                    Generic(p.def_id)
+            ty::ty_projection(ref data) => {
+                let trait_ref = match data.trait_ref.clean(cx) {
+                    TyParamBound::TraitBound(t, _) => t.trait_,
+                    TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"),
+                };
+                Type::QPath {
+                    name: data.item_name.clean(cx),
+                    self_type: box data.trait_ref.self_ty().clean(cx),
+                    trait_: box trait_ref,
                 }
             }
 
+            ty::ty_param(ref p) => Generic(token::get_name(p.name).to_string()),
+
             ty::ty_unboxed_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
             ty::ty_infer(..) => panic!("ty_infer"),
@@ -2028,7 +2016,7 @@ impl Clean<Vec<Item>> for ast::ViewItem {
                 None => false,
             }
         });
-        let convert = |node: &ast::ViewItem_| {
+        let convert = |&: node: &ast::ViewItem_| {
             Item {
                 name: None,
                 attrs: self.attrs.clean(cx),
@@ -2281,7 +2269,9 @@ fn resolve_type(cx: &DocContext,
     };
 
     match def {
-        def::DefSelfTy(i) => return Self(ast_util::local_def(i)),
+        def::DefSelfTy(..) => {
+            return Generic(token::get_name(special_idents::type_self.name).to_string());
+        }
         def::DefPrimTy(p) => match p {
             ast::TyStr => return Primitive(Str),
             ast::TyBool => return Primitive(Bool),
@@ -2299,7 +2289,7 @@ fn resolve_type(cx: &DocContext,
             ast::TyFloat(ast::TyF32) => return Primitive(F32),
             ast::TyFloat(ast::TyF64) => return Primitive(F64),
         },
-        def::DefTyParam(_, i, _) => return Generic(i),
+        def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()),
         def::DefTyParamBinder(i) => return TyParamBinder(i),
         _ => {}
     };
@@ -2412,7 +2402,6 @@ impl Clean<Item> for ty::AssociatedType {
                 },
                 bounds: vec![],
                 default: None,
-                default_unbound: None
             }),
             visibility: None,
             def_id: self.def_id,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 59883f37737..2416eb2869e 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -11,6 +11,7 @@ pub use self::MaybeTyped::*;
 
 use rustc_driver::driver;
 use rustc::session::{mod, config};
+use rustc::session::search_paths::SearchPaths;
 use rustc::middle::{privacy, ty};
 use rustc::lint;
 use rustc_trans::back::link;
@@ -76,7 +77,7 @@ pub struct CrateAnalysis {
 
 pub type Externs = HashMap<String, Vec<String>>;
 
-pub fn run_core(libs: Vec<Path>, cfgs: Vec<String>, externs: Externs,
+pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
                 cpath: &Path, triple: Option<String>)
                 -> (clean::Crate, CrateAnalysis) {
 
@@ -88,7 +89,7 @@ pub fn run_core(libs: Vec<Path>, cfgs: Vec<String>, externs: Externs,
 
     let sessopts = config::Options {
         maybe_sysroot: None,
-        addl_lib_search_paths: RefCell::new(libs),
+        search_paths: search_paths,
         crate_types: vec!(config::CrateTypeRlib),
         lint_opts: vec!((warning_lint, lint::Allow)),
         externs: externs,
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 7f7c055062a..251ce5aefeb 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -178,7 +178,6 @@ pub struct Trait {
     pub whence: Span,
     pub vis: ast::Visibility,
     pub stab: Option<attr::Stability>,
-    pub default_unbound: Option<ast::TraitRef> // FIXME(tomjakubowski)
 }
 
 pub struct Impl {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 25c4f4e01b6..3c09a10f3d9 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -97,9 +97,6 @@ impl fmt::Show for clean::Generics {
                 if i > 0 {
                     try!(f.write(", ".as_bytes()))
                 }
-                if let Some(ref unbound) = tp.default_unbound {
-                    try!(write!(f, "{}? ", unbound));
-                };
                 try!(f.write(tp.name.as_bytes()));
 
                 if tp.bounds.len() > 0 {
@@ -123,7 +120,7 @@ impl<'a> fmt::Show for WhereClause<'a> {
         if gens.where_predicates.len() == 0 {
             return Ok(());
         }
-        try!(f.write(" where ".as_bytes()));
+        try!(f.write(" <span class='where'>where ".as_bytes()));
         for (i, pred) in gens.where_predicates.iter().enumerate() {
             if i > 0 {
                 try!(f.write(", ".as_bytes()));
@@ -149,6 +146,7 @@ impl<'a> fmt::Show for WhereClause<'a> {
                 }
             }
         }
+        try!(f.write("</span>".as_bytes()));
         Ok(())
     }
 }
@@ -182,8 +180,12 @@ impl fmt::Show for clean::TyParamBound {
             clean::RegionBound(ref lt) => {
                 write!(f, "{}", *lt)
             }
-            clean::TraitBound(ref ty) => {
-                write!(f, "{}", *ty)
+            clean::TraitBound(ref ty, modifier) => {
+                let modifier_str = match modifier {
+                    ast::TraitBoundModifier::None => "",
+                    ast::TraitBoundModifier::Maybe => "?",
+                };
+                write!(f, "{}{}", modifier_str, *ty)
             }
         }
     }
@@ -396,7 +398,7 @@ fn primitive_link(f: &mut fmt::Formatter,
                 Some(root) => {
                     try!(write!(f, "<a href='{}{}/primitive.{}.html'>",
                                 root,
-                                path.0.head().unwrap(),
+                                path.0.first().unwrap(),
                                 prim.to_url_str()));
                     needs_termination = true;
                 }
@@ -433,15 +435,14 @@ impl fmt::Show for clean::Type {
             clean::TyParamBinder(id) => {
                 f.write(cache().typarams[ast_util::local_def(id)].as_bytes())
             }
-            clean::Generic(did) => {
-                f.write(cache().typarams[did].as_bytes())
+            clean::Generic(ref name) => {
+                f.write(name.as_bytes())
             }
             clean::ResolvedPath{ did, ref typarams, ref path } => {
                 try!(resolved_path(f, did, path, false));
                 tybounds(f, typarams)
             }
             clean::Infer => write!(f, "_"),
-            clean::Self(..) => f.write("Self".as_bytes()),
             clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()),
             clean::Closure(ref decl) => {
                 write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}",
@@ -458,12 +459,15 @@ impl fmt::Show for clean::Type {
                            for bound in decl.bounds.iter() {
                                 match *bound {
                                     clean::RegionBound(..) => {}
-                                    clean::TraitBound(ref t) => {
+                                    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());
                                     }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index c936f6a0819..cfaae1a9f80 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -61,7 +61,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
     loop {
         let next = lexer.next_token();
 
-        let snip = |sp| sess.span_diagnostic.cm.span_to_snippet(sp).unwrap();
+        let snip = |&: sp| sess.span_diagnostic.cm.span_to_snippet(sp).unwrap();
 
         if next.tok == token::Eof { break }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index aed8cdfb8b2..468fed1d339 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -81,7 +81,7 @@ struct hoedown_renderer {
     blockhtml: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
                                     *mut libc::c_void)>,
     header: Option<headerfn>,
-    other: [libc::size_t, ..28],
+    other: [libc::size_t; 28],
 }
 
 #[repr(C)]
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index ebdd43b1775..ceb66be2d66 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1680,9 +1680,6 @@ fn item_function(w: &mut fmt::Formatter, it: &clean::Item,
 fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
               t: &clean::Trait) -> fmt::Result {
     let mut bounds = String::new();
-    if let Some(ref ty) = t.default_unbound {
-        bounds.push_str(format!(" for {}?", ty).as_slice());
-    }
     if t.bounds.len() > 0 {
         if bounds.len() > 0 {
             bounds.push(' ');
@@ -1803,7 +1800,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     try!(write!(w, r#"<script type="text/javascript" async
                               src="{root_path}/implementors/{path}/{ty}.{name}.js">
                       </script>"#,
-                root_path = Vec::from_elem(cx.current.len(), "..").connect("/"),
+                root_path = repeat("..").take(cx.current.len()).collect::<Vec<_>>().connect("/"),
                 path = if ast_util::is_local(it.def_id) {
                     cx.current.connect("/")
                 } else {
@@ -2059,7 +2056,8 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
 fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
     match cache().impls.get(&it.def_id) {
         Some(v) => {
-            let (non_trait, traits) = v.partitioned(|i| i.impl_.trait_.is_none());
+            let (non_trait, traits): (Vec<_>, _) = v.iter().cloned()
+                .partition(|i| i.impl_.trait_.is_none());
             if non_trait.len() > 0 {
                 try!(write!(w, "<h2 id='methods'>Methods</h2>"));
                 for i in non_trait.iter() {
@@ -2069,7 +2067,8 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
             if traits.len() > 0 {
                 try!(write!(w, "<h2 id='implementations'>Trait \
                                   Implementations</h2>"));
-                let (derived, manual) = traits.partition(|i| i.impl_.derived);
+                let (derived, manual): (Vec<_>, _) = traits.into_iter()
+                    .partition(|i| i.impl_.derived);
                 for i in manual.iter() {
                     try!(render_impl(w, i));
                 }
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index dc62273364c..9d4f341a30e 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -306,6 +306,11 @@ nav.sub {
     font-size: 1em;
     position: relative;
 }
+/* Shift "where ..." part of method definition down a line */
+.content .method .where { display: block; }
+/* Bit of whitespace to indent it */
+.content .method .where::before { content: '      '; }
+
 .content .methods .docblock { margin-left: 40px; }
 
 .content .impl-items .docblock { margin-left: 40px; }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 8dfb352d028..ccdc8164255 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -43,6 +43,7 @@ use std::rc::Rc;
 use externalfiles::ExternalHtml;
 use serialize::{Decodable, Encodable};
 use serialize::json::{mod, Json};
+use rustc::session::search_paths::SearchPaths;
 
 // reexported from `clean` so it can be easily updated with the mod itself
 pub use clean::SCHEMA_VERSION;
@@ -115,7 +116,8 @@ pub fn opts() -> Vec<getopts::OptGroup> {
     use getopts::*;
     vec!(
         optflag("h", "help", "show this help message"),
-        optflagopt("", "version", "print rustdoc's version", "verbose"),
+        optflag("V", "version", "print rustdoc's version"),
+        optflag("v", "verbose", "use verbose output"),
         optopt("r", "input-format", "the input type of the specified file",
                "[rust|json]"),
         optopt("w", "output-format", "the output type to write",
@@ -200,7 +202,10 @@ pub fn main_args(args: &[String]) -> int {
     }
     let input = matches.free[0].as_slice();
 
-    let libs = matches.opt_strs("L").iter().map(|s| Path::new(s.as_slice())).collect();
+    let mut libs = SearchPaths::new();
+    for s in matches.opt_strs("L").iter() {
+        libs.add_path(s.as_slice());
+    }
     let externs = match parse_externs(&matches) {
         Ok(ex) => ex,
         Err(err) => {
@@ -334,10 +339,10 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
     let mut plugins = matches.opt_strs("plugins");
 
     // First, parse the crate and extract all relevant information.
-    let libs: Vec<Path> = matches.opt_strs("L")
-                                 .iter()
-                                 .map(|s| Path::new(s.as_slice()))
-                                 .collect();
+    let mut paths = SearchPaths::new();
+    for s in matches.opt_strs("L").iter() {
+        paths.add_path(s.as_slice());
+    }
     let cfgs = matches.opt_strs("cfg");
     let triple = matches.opt_str("target");
 
@@ -346,7 +351,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
 
     let (mut krate, analysis) = std::thread::Thread::spawn(move |:| {
         let cr = cr;
-        core::run_core(libs, cfgs, externs, &cr, triple)
+        core::run_core(paths, cfgs, externs, &cr, triple)
     }).join().map_err(|_| "rustc failed").unwrap();
     info!("finished with rustc");
     let mut analysis = Some(analysis);
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 881c7a91d81..ab9c4ef9422 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 use std::io;
-use std::string::String;
 
 use core;
 use getopts;
 use testing;
+use rustc::session::search_paths::SearchPaths;
 
 use externalfiles::ExternalHtml;
 
@@ -135,7 +135,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches,
 }
 
 /// Run any tests/code examples in the markdown file `input`.
-pub fn test(input: &str, libs: Vec<Path>, externs: core::Externs,
+pub fn test(input: &str, libs: SearchPaths, externs: core::Externs,
             mut test_args: Vec<String>) -> int {
     let input_str = load_or_return!(input, 1, 2);
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index a50bfbde0fe..743c8b240d1 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -21,6 +21,7 @@ use std::thunk::Thunk;
 use std::collections::{HashSet, HashMap};
 use testing;
 use rustc::session::{mod, config};
+use rustc::session::search_paths::{SearchPaths, PathKind};
 use rustc_driver::driver;
 use syntax::ast;
 use syntax::codemap::{CodeMap, dummy_spanned};
@@ -38,7 +39,7 @@ use visit_ast::RustdocVisitor;
 
 pub fn run(input: &str,
            cfgs: Vec<String>,
-           libs: Vec<Path>,
+           libs: SearchPaths,
            externs: core::Externs,
            mut test_args: Vec<String>,
            crate_name: Option<String>)
@@ -48,7 +49,7 @@ pub fn run(input: &str,
 
     let sessopts = config::Options {
         maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
-        addl_lib_search_paths: RefCell::new(libs.clone()),
+        search_paths: libs.clone(),
         crate_types: vec!(config::CrateTypeDylib),
         externs: externs.clone(),
         ..config::basic_options().clone()
@@ -107,7 +108,8 @@ pub fn run(input: &str,
     0
 }
 
-fn runtest(test: &str, cratename: &str, libs: Vec<Path>, externs: core::Externs,
+fn runtest(test: &str, cratename: &str, libs: SearchPaths,
+           externs: core::Externs,
            should_fail: bool, no_run: bool, as_test_harness: bool) {
     // the test harness wants its own `main` & top level functions, so
     // never wrap the test in `fn main() { ... }`
@@ -116,7 +118,7 @@ fn runtest(test: &str, cratename: &str, libs: Vec<Path>, externs: core::Externs,
 
     let sessopts = config::Options {
         maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
-        addl_lib_search_paths: RefCell::new(libs),
+        search_paths: libs,
         crate_types: vec!(config::CrateTypeExecutable),
         output_types: vec!(config::OutputTypeExe),
         no_trans: no_run,
@@ -171,7 +173,7 @@ fn runtest(test: &str, cratename: &str, libs: Vec<Path>, externs: core::Externs,
     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().get_lib_path();
+    let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
     driver::compile_input(sess, cfg, &input, &out, &None, None);
 
     if no_run { return }
@@ -242,7 +244,7 @@ pub fn maketest(s: &str, cratename: Option<&str>, lints: bool, dont_insert_main:
 pub struct Collector {
     pub tests: Vec<testing::TestDescAndFn>,
     names: Vec<String>,
-    libs: Vec<Path>,
+    libs: SearchPaths,
     externs: core::Externs,
     cnt: uint,
     use_headers: bool,
@@ -251,7 +253,7 @@ pub struct Collector {
 }
 
 impl Collector {
-    pub fn new(cratename: String, libs: Vec<Path>, externs: core::Externs,
+    pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs,
                use_headers: bool) -> Collector {
         Collector {
             tests: Vec::new(),
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 4374ce5deef..e71711aa8d6 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -322,7 +322,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.constants.push(s);
             },
-            ast::ItemTrait(unsafety, ref gen, ref def_ub, ref b, ref items) => {
+            ast::ItemTrait(unsafety, ref gen, ref b, ref items) => {
                 let t = Trait {
                     unsafety: unsafety,
                     name: name,
@@ -334,7 +334,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     whence: item.span,
                     vis: item.vis,
                     stab: self.stability(item.id),
-                    default_unbound: def_ub.clone()
                 };
                 om.traits.push(t);
             },
diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs
index f1dffa55bb0..54b390e0c3f 100644
--- a/src/libserialize/base64.rs
+++ b/src/libserialize/base64.rs
@@ -314,7 +314,7 @@ mod tests {
 
     #[test]
     fn test_to_base64_crlf_line_break() {
-        assert!(![0u8, ..1000].to_base64(Config {line_length: None, ..STANDARD})
+        assert!(![0u8; 1000].to_base64(Config {line_length: None, ..STANDARD})
                               .contains("\r\n"));
         assert_eq!(b"foobar".to_base64(Config {line_length: Some(4),
                                                ..STANDARD}),
@@ -323,7 +323,7 @@ mod tests {
 
     #[test]
     fn test_to_base64_lf_line_break() {
-        assert!(![0u8, ..1000].to_base64(Config {line_length: None,
+        assert!(![0u8; 1000].to_base64(Config {line_length: None,
                                                  newline: Newline::LF,
                                                  ..STANDARD})
                               .as_slice()
@@ -392,10 +392,10 @@ mod tests {
 
     #[test]
     fn test_base64_random() {
-        use std::rand::{task_rng, random, Rng};
+        use std::rand::{thread_rng, random, Rng};
 
         for _ in range(0u, 1000) {
-            let times = task_rng().gen_range(1u, 100);
+            let times = thread_rng().gen_range(1u, 100);
             let v = Vec::from_fn(times, |_| random::<u8>());
             assert_eq!(v.to_base64(STANDARD)
                         .from_base64()
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index 830d96fe172..8a9c2eebf3a 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -29,7 +29,7 @@
 //! * `String`: equivalent to rust's `String`
 //! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
 //!   same array
-//! * `Object`: equivalent to rust's `Treemap<String, json::Json>`
+//! * `Object`: equivalent to rust's `BTreeMap<String, json::Json>`
 //! * `Null`
 //!
 //! An object is a series of string keys mapping to values, in `"key": value` format.
@@ -392,14 +392,14 @@ fn escape_str(writer: &mut io::Writer, v: &str) -> Result<(), io::IoError> {
 }
 
 fn escape_char(writer: &mut io::Writer, v: char) -> Result<(), io::IoError> {
-    let mut buf = [0, .. 4];
+    let mut buf = [0; 4];
     let len = v.encode_utf8(&mut buf).unwrap();
     escape_bytes(writer, buf[mut ..len])
 }
 
 fn spaces(wr: &mut io::Writer, mut n: uint) -> Result<(), io::IoError> {
     const LEN: uint = 16;
-    static BUF: [u8, ..LEN] = [b' ', ..LEN];
+    static BUF: [u8; LEN] = [b' '; LEN];
 
     while n >= LEN {
         try!(wr.write(&BUF));
@@ -2517,7 +2517,7 @@ mod tests {
     #[test]
     fn test_from_str_trait() {
         let s = "null";
-        assert!(::std::str::from_str::<Json>(s).unwrap() == from_str(s).unwrap());
+        assert!(s.parse::<Json>().unwrap() == s.parse().unwrap());
     }
 
     #[test]
@@ -3729,8 +3729,8 @@ mod tests {
         let array3 = Array(vec!(U64(1), U64(2), U64(3)));
         let object = {
             let mut tree_map = BTreeMap::new();
-            tree_map.insert("a".into_string(), U64(1));
-            tree_map.insert("b".into_string(), U64(2));
+            tree_map.insert("a".to_string(), U64(1));
+            tree_map.insert("b".to_string(), U64(2));
             Object(tree_map)
         };
 
@@ -3762,8 +3762,8 @@ mod tests {
         assert_eq!((vec![1u, 2]).to_json(), array2);
         assert_eq!(vec!(1u, 2, 3).to_json(), array3);
         let mut tree_map = BTreeMap::new();
-        tree_map.insert("a".into_string(), 1u);
-        tree_map.insert("b".into_string(), 2);
+        tree_map.insert("a".to_string(), 1u);
+        tree_map.insert("b".to_string(), 2);
         assert_eq!(tree_map.to_json(), object);
         let mut hash_map = HashMap::new();
         hash_map.insert("a".to_string(), 1u);
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index db01c091dc0..857a7072009 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -234,7 +234,7 @@ pub fn escape_default<F>(c: u8, mut f: F) where
     }
 }
 
-static ASCII_LOWERCASE_MAP: [u8, ..256] = [
+static ASCII_LOWERCASE_MAP: [u8; 256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -273,7 +273,7 @@ static ASCII_LOWERCASE_MAP: [u8, ..256] = [
     0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
 ];
 
-static ASCII_UPPERCASE_MAP: [u8, ..256] = [
+static ASCII_UPPERCASE_MAP: [u8; 256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs
index 4ec329de600..c07531d3f32 100644
--- a/src/libstd/bitflags.rs
+++ b/src/libstd/bitflags.rs
@@ -104,6 +104,10 @@
 /// - `empty`: an empty set of flags
 /// - `all`: the set of all flags
 /// - `bits`: the raw value of the flags currently stored
+/// - `from_bits`: convert from underlying bit representation, unless that
+///                representation contains bits that do not correspond to a flag
+/// - `from_bits_truncate`: convert from underlying bit representation, dropping
+///                         any bits that do not correspond to flags
 /// - `is_empty`: `true` if no flags are currently stored
 /// - `is_all`: `true` if all flags are currently set
 /// - `intersects`: `true` if there are flags common to both `self` and `other`
@@ -237,17 +241,6 @@ macro_rules! bitflags {
             }
         }
 
-        // NOTE(stage0): Remove impl after a snapshot
-        #[cfg(stage0)]
-        impl ::std::ops::Not<$BitFlags> for $BitFlags {
-            /// Returns the complement of this set of flags.
-            #[inline]
-            fn not(&self) -> $BitFlags {
-                $BitFlags { bits: !self.bits } & $BitFlags::all()
-            }
-        }
-
-        #[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
         impl ::std::ops::Not<$BitFlags> for $BitFlags {
             /// Returns the complement of this set of flags.
             #[inline]
diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs
index d096903f9c4..33cf33848f0 100644
--- a/src/libstd/c_str.rs
+++ b/src/libstd/c_str.rs
@@ -77,7 +77,7 @@ use fmt;
 use hash;
 use mem;
 use ptr;
-use slice::{mod, ImmutableIntSlice};
+use slice::{mod, IntSliceExt};
 use str;
 use string::String;
 use core::kinds::marker;
@@ -465,7 +465,7 @@ unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where
     F: FnOnce(*const libc::c_char) -> T,
 {
     let c_str = if v.len() < BUF_LEN {
-        let mut buf: [u8, .. BUF_LEN] = mem::uninitialized();
+        let mut buf: [u8; BUF_LEN] = mem::uninitialized();
         slice::bytes::copy_memory(&mut buf, v);
         buf[v.len()] = 0;
 
@@ -497,6 +497,8 @@ fn check_for_null(v: &[u8], buf: *mut libc::c_char) {
 /// External iterator for a CString's bytes.
 ///
 /// Use with the `std::iter` module.
+#[allow(raw_pointer_deriving)]
+#[deriving(Clone)]
 pub struct CChars<'a> {
     ptr: *const libc::c_char,
     marker: marker::ContravariantLifetime<'a>,
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
index a80659ed937..40942f1b987 100644
--- a/src/libstd/c_vec.rs
+++ b/src/libstd/c_vec.rs
@@ -40,7 +40,7 @@ use mem;
 use ops::{Drop, FnOnce};
 use option::Option;
 use option::Option::{Some, None};
-use ptr::RawPtr;
+use ptr::PtrExt;
 use ptr;
 use raw;
 use slice::AsSlice;
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 8585b4ecf52..4738c830bd3 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -264,30 +264,39 @@ fn test_resize_policy() {
 /// }
 /// ```
 ///
-/// The easiest way to use `HashMap` with a custom type is to derive `Eq` and `Hash`.
+/// The easiest way to use `HashMap` with a custom type as key is to derive `Eq` and `Hash`.
 /// We must also derive `PartialEq`.
 ///
 /// ```
 /// use std::collections::HashMap;
 ///
 /// #[deriving(Hash, Eq, PartialEq, Show)]
-/// struct Viking<'a> {
-///     name: &'a str,
-///     power: uint,
+/// struct Viking {
+///     name: String,
+///     country: String,
 /// }
 ///
+/// impl Viking {
+///     /// Create a new Viking.
+///     fn new(name: &str, country: &str) -> Viking {
+///         Viking { name: name.to_string(), country: country.to_string() }
+///     }
+/// }
+///
+/// // Use a HashMap to store the vikings' health points.
 /// let mut vikings = HashMap::new();
 ///
-/// vikings.insert("Norway", Viking { name: "Einar", power: 9u });
-/// vikings.insert("Denmark", Viking { name: "Olaf", power: 4u });
-/// vikings.insert("Iceland", Viking { name: "Harald", power: 8u });
+/// vikings.insert(Viking::new("Einar", "Norway"), 25u);
+/// vikings.insert(Viking::new("Olaf", "Denmark"), 24u);
+/// vikings.insert(Viking::new("Harald", "Iceland"), 12u);
 ///
-/// // Use derived implementation to print the vikings.
-/// for (land, viking) in vikings.iter() {
-///     println!("{} at {}", viking, land);
+/// // Use derived implementation to print the status of the vikings.
+/// for (viking, health) in vikings.iter() {
+///     println!("{} has {} hp", viking, health);
 /// }
 /// ```
 #[deriving(Clone)]
+#[stable]
 pub struct HashMap<K, V, H = RandomSipHasher> {
     // All hashes are keyed on these values, to prevent hash collision attacks.
     hasher: H,
@@ -500,7 +509,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
     /// let mut map: HashMap<&str, int> = HashMap::new();
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> HashMap<K, V, RandomSipHasher> {
         let hasher = RandomSipHasher::new();
         HashMap::with_hasher(hasher)
@@ -515,7 +524,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
     /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomSipHasher> {
         let hasher = RandomSipHasher::new();
         HashMap::with_capacity_and_hasher(capacity, hasher)
@@ -538,6 +547,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// map.insert(1i, 2u);
     /// ```
     #[inline]
+    #[unstable = "hasher stuff is unclear"]
     pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
         HashMap {
             hasher:        hasher,
@@ -565,6 +575,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// map.insert(1i, 2u);
     /// ```
     #[inline]
+    #[unstable = "hasher stuff is unclear"]
     pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
         let resize_policy = DefaultResizePolicy::new();
         let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity));
@@ -587,7 +598,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert!(map.capacity() >= 100);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint {
         self.resize_policy.usable_capacity(self.table.capacity())
     }
@@ -607,7 +618,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// let mut map: HashMap<&str, int> = HashMap::new();
     /// map.reserve(10);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve(&mut self, additional: uint) {
         let new_size = self.len().checked_add(additional).expect("capacity overflow");
         let min_cap = self.resize_policy.min_capacity(new_size);
@@ -719,7 +730,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// map.shrink_to_fit();
     /// assert!(map.capacity() >= 2);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn shrink_to_fit(&mut self) {
         let min_capacity = self.resize_policy.min_capacity(self.len());
         let min_capacity = max(min_capacity.next_power_of_two(), INITIAL_CAPACITY);
@@ -837,7 +848,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     ///     println!("{}", key);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr
@@ -862,7 +873,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     ///     println!("{}", key);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn values<'a>(&'a self) -> Values<'a, K, V> {
         fn second<A, B>((_, b): (A, B)) -> B { b }
         let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr
@@ -887,9 +898,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter(&self) -> Entries<K, V> {
-        Entries { inner: self.table.iter() }
+    #[stable]
+    pub fn iter(&self) -> Iter<K, V> {
+        Iter { inner: self.table.iter() }
     }
 
     /// An iterator visiting all key-value pairs in arbitrary order,
@@ -915,7 +926,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     ///     println!("key: {} val: {}", key, val);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn iter_mut(&mut self) -> IterMut<K, V> {
         IterMut { inner: self.table.iter_mut() }
     }
@@ -937,7 +948,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// // Not possible with .iter()
     /// let vec: Vec<(&str, int)> = map.into_iter().collect();
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<K, V> {
         fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
         let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
@@ -968,7 +979,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// a.insert(1u, "a");
     /// assert_eq!(a.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint { self.table.size() }
 
     /// Return true if the map contains no elements.
@@ -984,7 +995,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert!(!a.is_empty());
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears the map, returning all key-value pairs as an iterator. Keeps the
@@ -1030,7 +1041,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// a.clear();
     /// assert!(a.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     #[inline]
     pub fn clear(&mut self) {
         self.drain();
@@ -1058,7 +1069,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map.get(&1), Some(&"a"));
     /// assert_eq!(map.get(&2), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get<Sized? Q>(&self, k: &Q) -> Option<&V>
         where Q: Hash<S> + Eq + BorrowFrom<K>
     {
@@ -1081,7 +1092,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map.contains_key(&1), true);
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn contains_key<Sized? Q>(&self, k: &Q) -> bool
         where Q: Hash<S> + Eq + BorrowFrom<K>
     {
@@ -1113,7 +1124,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// }
     /// assert_eq!(map[1], "b");
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn get_mut<Sized? Q>(&mut self, k: &Q) -> Option<&mut V>
         where Q: Hash<S> + Eq + BorrowFrom<K>
     {
@@ -1142,7 +1153,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map.insert(37, "c"), Some("b"));
     /// assert_eq!(map[37], "c");
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         let hash = self.make_hash(&k);
         self.reserve(1);
@@ -1177,7 +1188,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map.remove(&1), Some("a"));
     /// assert_eq!(map.remove(&1), None);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn remove<Sized? Q>(&mut self, k: &Q) -> Option<V>
         where Q: Hash<S> + Eq + BorrowFrom<K>
     {
@@ -1253,6 +1264,7 @@ impl<K: Eq + Hash<S>, V: Clone, S, H: Hasher<S>> HashMap<K, V, H> {
     }
 }
 
+#[stable]
 impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, H> {
     fn eq(&self, other: &HashMap<K, V, H>) -> bool {
         if self.len() != other.len() { return false; }
@@ -1263,8 +1275,10 @@ impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V,
     }
 }
 
+#[stable]
 impl<K: Eq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {}
 
+#[stable]
 impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "{{"));
@@ -1286,6 +1300,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H>
     }
 }
 
+#[stable]
 impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q, V> for HashMap<K, V, H>
     where Q: BorrowFrom<K> + Hash<S> + Eq
 {
@@ -1295,6 +1310,7 @@ impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q, V> for HashMap<K, V
     }
 }
 
+#[stable]
 impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K, V, H>
     where Q: BorrowFrom<K> + Hash<S> + Eq
 {
@@ -1305,16 +1321,28 @@ impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K
 }
 
 /// HashMap iterator
-pub struct Entries<'a, K: 'a, V: 'a> {
-    inner: table::Entries<'a, K, V>
+#[stable]
+pub struct Iter<'a, K: 'a, V: 'a> {
+    inner: table::Iter<'a, K, V>
+}
+
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, K, V> Clone for Iter<'a, K, V> {
+    fn clone(&self) -> Iter<'a, K, V> {
+        Iter {
+            inner: self.inner.clone()
+        }
+    }
 }
 
 /// HashMap mutable values iterator
+#[stable]
 pub struct IterMut<'a, K: 'a, V: 'a> {
     inner: table::IterMut<'a, K, V>
 }
 
 /// HashMap move iterator
+#[stable]
 pub struct IntoIter<K, V> {
     inner: iter::Map<
         (SafeHash, K, V),
@@ -1325,16 +1353,37 @@ pub struct IntoIter<K, V> {
 }
 
 /// HashMap keys iterator
+#[stable]
 pub struct Keys<'a, K: 'a, V: 'a> {
-    inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
+    inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
+}
+
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, K, V> Clone for Keys<'a, K, V> {
+    fn clone(&self) -> Keys<'a, K, V> {
+        Keys {
+            inner: self.inner.clone()
+        }
+    }
 }
 
 /// HashMap values iterator
+#[stable]
 pub struct Values<'a, K: 'a, V: 'a> {
-    inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
+    inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
+}
+
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, K, V> Clone for Values<'a, K, V> {
+    fn clone(&self) -> Values<'a, K, V> {
+        Values {
+            inner: self.inner.clone()
+        }
+    }
 }
 
 /// HashMap drain iterator
+#[unstable = "matches collection reform specification, waiting for dust to settle"]
 pub struct Drain<'a, K: 'a, V: 'a> {
     inner: iter::Map<
         (SafeHash, K, V),
@@ -1373,31 +1422,37 @@ enum VacantEntryState<K, V, M> {
     NoElem(EmptyBucket<K, V, M>),
 }
 
-impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
+#[stable]
+impl<'a, K, V> Iterator<(&'a K, &'a V)> for Iter<'a, K, 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() }
 }
 
+#[stable]
 impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for IterMut<'a, K, 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() }
 }
 
+#[stable]
 impl<K, V> Iterator<(K, V)> for IntoIter<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() }
 }
 
+#[stable]
 impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
     #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
+#[stable]
 impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
     #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
     #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
 }
 
+#[stable]
 impl<'a, K: 'a, V: 'a> Iterator<(K, V)> for Drain<'a, K, V> {
     #[inline]
     fn next(&mut self) -> Option<(K, V)> {
@@ -1454,6 +1509,7 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
     }
 }
 
+#[stable]
 impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
     fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
         let lower = iter.size_hint().0;
@@ -1463,6 +1519,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for Has
     }
 }
 
+#[stable]
 impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Extend<(K, V)> for HashMap<K, V, H> {
     fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
         for (k, v) in iter {
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index e00116344c8..6132d288da2 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -90,6 +90,7 @@ use super::map::{mod, HashMap, Keys, INITIAL_CAPACITY};
 /// }
 /// ```
 #[deriving(Clone)]
+#[stable]
 pub struct HashSet<T, H = RandomSipHasher> {
     map: HashMap<T, (), H>
 }
@@ -104,7 +105,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
     /// let mut set: HashSet<int> = HashSet::new();
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn new() -> HashSet<T, RandomSipHasher> {
         HashSet::with_capacity(INITIAL_CAPACITY)
     }
@@ -119,7 +120,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
     /// let mut set: HashSet<int> = HashSet::with_capacity(10);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> {
         HashSet { map: HashMap::with_capacity(capacity) }
     }
@@ -142,6 +143,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// set.insert(2u);
     /// ```
     #[inline]
+    #[unstable = "hasher stuff is unclear"]
     pub fn with_hasher(hasher: H) -> HashSet<T, H> {
         HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
     }
@@ -165,6 +167,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// set.insert(1i);
     /// ```
     #[inline]
+    #[unstable = "hasher stuff is unclear"]
     pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
         HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
     }
@@ -179,7 +182,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert!(set.capacity() >= 100);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn capacity(&self) -> uint {
         self.map.capacity()
     }
@@ -199,7 +202,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// let mut set: HashSet<int> = HashSet::new();
     /// set.reserve(10);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn reserve(&mut self, additional: uint) {
         self.map.reserve(additional)
     }
@@ -220,7 +223,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// set.shrink_to_fit();
     /// assert!(set.capacity() >= 2);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn shrink_to_fit(&mut self) {
         self.map.shrink_to_fit()
     }
@@ -248,8 +251,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     ///     println!("{}", x);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn iter<'a>(&'a self) -> Iter<'a, T> {
+    #[stable]
+    pub fn iter(&self) -> Iter<T> {
         Iter { iter: self.map.keys() }
     }
 
@@ -273,7 +276,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     ///     println!("{}", x);
     /// }
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn into_iter(self) -> IntoIter<T> {
         fn first<A, B>((a, _): (A, B)) -> A { a }
         let first: fn((T, ())) -> T = first;
@@ -303,7 +306,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// let diff: HashSet<int> = b.difference(&a).map(|&x| x).collect();
     /// assert_eq!(diff, [4i].iter().map(|&x| x).collect());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H> {
         Difference {
             iter: self.iter(),
@@ -331,7 +334,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(diff1, diff2);
     /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
         -> SymmetricDifference<'a, T, H> {
         SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
@@ -354,7 +357,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// let diff: HashSet<int> = a.intersection(&b).map(|&x| x).collect();
     /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a, T, H> {
         Intersection {
             iter: self.iter(),
@@ -379,7 +382,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// let diff: HashSet<int> = a.union(&b).map(|&x| x).collect();
     /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> Union<'a, T, H> {
         Union { iter: self.iter().chain(other.difference(self)) }
     }
@@ -396,7 +399,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// v.insert(1u);
     /// assert_eq!(v.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn len(&self) -> uint { self.map.len() }
 
     /// Returns true if the set contains no elements
@@ -411,7 +414,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// v.insert(1u);
     /// assert!(!v.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_empty(&self) -> bool { self.map.len() == 0 }
 
     /// Clears the set, returning all elements in an iterator.
@@ -436,7 +439,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// v.clear();
     /// assert!(v.is_empty());
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn clear(&mut self) { self.map.clear() }
 
     /// Returns `true` if the set contains a value.
@@ -454,7 +457,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(set.contains(&1), true);
     /// assert_eq!(set.contains(&4), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn contains<Sized? Q>(&self, value: &Q) -> bool
         where Q: BorrowFrom<T> + Hash<S> + Eq
     {
@@ -478,7 +481,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// b.insert(1);
     /// assert_eq!(a.is_disjoint(&b), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
         self.iter().all(|v| !other.contains(v))
     }
@@ -499,7 +502,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// set.insert(4);
     /// assert_eq!(set.is_subset(&sup), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_subset(&self, other: &HashSet<T, H>) -> bool {
         self.iter().all(|v| other.contains(v))
     }
@@ -524,7 +527,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(set.is_superset(&sub), true);
     /// ```
     #[inline]
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn is_superset(&self, other: &HashSet<T, H>) -> bool {
         other.is_subset(self)
     }
@@ -543,7 +546,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(set.insert(2), false);
     /// assert_eq!(set.len(), 1);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() }
 
     /// Removes a value from the set. Returns `true` if the value was
@@ -564,7 +567,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(set.remove(&2), true);
     /// assert_eq!(set.remove(&2), false);
     /// ```
-    #[unstable = "matches collection reform specification, waiting for dust to settle"]
+    #[stable]
     pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool
         where Q: BorrowFrom<T> + Hash<S> + Eq
     {
@@ -572,6 +575,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     }
 }
 
+#[stable]
 impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
     fn eq(&self, other: &HashSet<T, H>) -> bool {
         if self.len() != other.len() { return false; }
@@ -580,8 +584,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
     }
 }
 
+#[stable]
 impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
 
+#[stable]
 impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "{{"));
@@ -595,6 +601,7 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
     }
 }
 
+#[stable]
 impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
     fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> {
         let lower = iter.size_hint().0;
@@ -604,6 +611,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T,
     }
 }
 
+#[stable]
 impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extend<T> for HashSet<T, H> {
     fn extend<I: Iterator<T>>(&mut self, mut iter: I) {
         for k in iter {
@@ -620,7 +628,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
 BitOr<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
     /// Returns the union of `self` and `rhs` as a new `HashSet<T, H>`.
@@ -648,7 +656,7 @@ BitOr<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
 BitAnd<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
     /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, H>`.
@@ -676,7 +684,7 @@ BitAnd<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
 BitXor<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
     /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, H>`.
@@ -704,7 +712,7 @@ BitXor<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
     }
 }
 
-#[unstable = "matches collection reform specification, waiting for dust to settle"]
+#[stable]
 impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default>
 Sub<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
     /// Returns the difference of `self` and `rhs` as a new `HashSet<T, H>`.
@@ -733,21 +741,25 @@ Sub<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> {
 }
 
 /// HashSet iterator
+#[stable]
 pub struct Iter<'a, K: 'a> {
     iter: Keys<'a, K, ()>
 }
 
 /// HashSet move iterator
+#[stable]
 pub struct IntoIter<K> {
     iter: Map<(K, ()), K, map::IntoIter<K, ()>, fn((K, ())) -> K>
 }
 
 /// HashSet drain iterator
+#[stable]
 pub struct Drain<'a, K: 'a> {
     iter: Map<(K, ()), K, map::Drain<'a, K, ()>, fn((K, ())) -> K>,
 }
 
 /// Intersection iterator
+#[stable]
 pub struct Intersection<'a, T: 'a, H: 'a> {
     // iterator of the first set
     iter: Iter<'a, T>,
@@ -756,6 +768,7 @@ pub struct Intersection<'a, T: 'a, H: 'a> {
 }
 
 /// Difference iterator
+#[stable]
 pub struct Difference<'a, T: 'a, H: 'a> {
     // iterator of the first set
     iter: Iter<'a, T>,
@@ -764,30 +777,36 @@ pub struct Difference<'a, T: 'a, H: 'a> {
 }
 
 /// Symmetric difference iterator.
+#[stable]
 pub struct SymmetricDifference<'a, T: 'a, H: 'a> {
     iter: Chain<Difference<'a, T, H>, Difference<'a, T, H>>
 }
 
 /// Set union iterator.
+#[stable]
 pub struct Union<'a, T: 'a, H: 'a> {
     iter: Chain<Iter<'a, T>, Difference<'a, T, H>>
 }
 
+#[stable]
 impl<'a, K> Iterator<&'a K> for Iter<'a, K> {
     fn next(&mut self) -> Option<&'a K> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
+#[stable]
 impl<K> Iterator<K> for IntoIter<K> {
     fn next(&mut self) -> Option<K> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
+#[stable]
 impl<'a, K: 'a> Iterator<K> for Drain<'a, K> {
     fn next(&mut self) -> Option<K> { self.iter.next() }
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
+#[stable]
 impl<'a, T, S, H> Iterator<&'a T> for Intersection<'a, T, H>
     where T: Eq + Hash<S>, H: Hasher<S>
 {
@@ -808,6 +827,7 @@ impl<'a, T, S, H> Iterator<&'a T> for Intersection<'a, T, H>
     }
 }
 
+#[stable]
 impl<'a, T, S, H> Iterator<&'a T> for Difference<'a, T, H>
     where T: Eq + Hash<S>, H: Hasher<S>
 {
@@ -828,6 +848,7 @@ impl<'a, T, S, H> Iterator<&'a T> for Difference<'a, T, H>
     }
 }
 
+#[stable]
 impl<'a, T, S, H> Iterator<&'a T> for SymmetricDifference<'a, T, H>
     where T: Eq + Hash<S>, H: Hasher<S>
 {
@@ -835,6 +856,7 @@ impl<'a, T, S, H> Iterator<&'a T> for SymmetricDifference<'a, T, H>
     fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
 }
 
+#[stable]
 impl<'a, T, S, H> Iterator<&'a T> for Union<'a, T, H>
     where T: Eq + Hash<S>, H: Hasher<S>
 {
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 3ae3a8ffbad..6938ab9b0b6 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -23,7 +23,7 @@ use num::{Int, UnsignedInt};
 use ops::{Deref, DerefMut, Drop};
 use option::Option;
 use option::Option::{Some, None};
-use ptr::{Unique, RawPtr, copy_nonoverlapping_memory, zero_memory};
+use ptr::{Unique, PtrExt, copy_nonoverlapping_memory, zero_memory};
 use ptr;
 use rt::heap::{allocate, deallocate};
 
@@ -657,8 +657,8 @@ impl<K, V> RawTable<K, V> {
         }
     }
 
-    pub fn iter(&self) -> Entries<K, V> {
-        Entries {
+    pub fn iter(&self) -> Iter<K, V> {
+        Iter {
             iter: self.raw_buckets(),
             elems_left: self.size(),
         }
@@ -718,6 +718,18 @@ struct RawBuckets<'a, K, V> {
     marker: marker::ContravariantLifetime<'a>,
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, K, V> Clone for RawBuckets<'a, K, V> {
+    fn clone(&self) -> RawBuckets<'a, K, V> {
+        RawBuckets {
+            raw: self.raw,
+            hashes_end: self.hashes_end,
+            marker: marker::ContravariantLifetime,
+        }
+    }
+}
+
+
 impl<'a, K, V> Iterator<RawBucket<K, V>> for RawBuckets<'a, K, V> {
     fn next(&mut self) -> Option<RawBucket<K, V>> {
         while self.raw.hash != self.hashes_end {
@@ -770,11 +782,22 @@ impl<'a, K, V> Iterator<(K, V)> for RevMoveBuckets<'a, K, V> {
 }
 
 /// Iterator over shared references to entries in a table.
-pub struct Entries<'a, K: 'a, V: 'a> {
+pub struct Iter<'a, K: 'a, V: 'a> {
     iter: RawBuckets<'a, K, V>,
     elems_left: uint,
 }
 
+// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
+impl<'a, K, V> Clone for Iter<'a, K, V> {
+    fn clone(&self) -> Iter<'a, K, V> {
+        Iter {
+            iter: self.iter.clone(),
+            elems_left: self.elems_left
+        }
+    }
+}
+
+
 /// Iterator over mutable references to entries in a table.
 pub struct IterMut<'a, K: 'a, V: 'a> {
     iter: RawBuckets<'a, K, V>,
@@ -793,7 +816,7 @@ pub struct Drain<'a, K: 'a, V: 'a> {
     iter: RawBuckets<'static, K, V>,
 }
 
-impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
+impl<'a, K, V> Iterator<(&'a K, &'a V)> for Iter<'a, K, V> {
     fn next(&mut self) -> Option<(&'a K, &'a V)> {
         self.iter.next().map(|bucket| {
             self.elems_left -= 1;
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
index 956185c6443..32e1922ae74 100644
--- a/src/libstd/error.rs
+++ b/src/libstd/error.rs
@@ -81,6 +81,7 @@
 use prelude::v1::*;
 
 use str::Utf8Error;
+use string::{FromUtf8Error, FromUtf16Error};
 
 /// Base functionality for all errors in Rust.
 pub trait Error: Send {
@@ -117,3 +118,12 @@ impl Error for Utf8Error {
 
     fn detail(&self) -> Option<String> { Some(self.to_string()) }
 }
+
+impl Error for FromUtf8Error {
+    fn description(&self) -> &str { "invalid utf-8" }
+    fn detail(&self) -> Option<String> { Some(self.to_string()) }
+}
+
+impl Error for FromUtf16Error {
+    fn description(&self) -> &str { "invalid utf-16" }
+}
diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs
index b75cf9a196b..957dd54a037 100644
--- a/src/libstd/fmt.rs
+++ b/src/libstd/fmt.rs
@@ -406,8 +406,6 @@ pub use core::fmt::{Argument, Arguments, write, radix, Radix, RadixFmt};
 #[doc(hidden)]
 pub use core::fmt::{argument, argumentuint};
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// The format function takes a precompiled format string and a list of
 /// arguments, to return the resulting formatted string.
 ///
@@ -431,31 +429,6 @@ pub fn format(args: Arguments) -> string::String {
     string::String::from_utf8(output).unwrap()
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-/// The format function takes a precompiled format string and a list of
-/// arguments, to return the resulting formatted string.
-///
-/// # Arguments
-///
-///   * args - a structure of arguments generated via the `format_args!` macro.
-///
-/// # Example
-///
-/// ```rust
-/// use std::fmt;
-///
-/// let s = format_args!(fmt::format, "Hello, {}!", "world");
-/// assert_eq!(s, "Hello, world!".to_string());
-/// ```
-#[experimental = "this is an implementation detail of format! and should not \
-                  be called directly"]
-pub fn format(args: &Arguments) -> string::String {
-    let mut output = Vec::new();
-    let _ = write!(&mut output as &mut Writer, "{}", args);
-    string::String::from_utf8(output).unwrap()
-}
-
 impl<'a> Writer for Formatter<'a> {
     fn write(&mut self, b: &[u8]) -> io::IoResult<()> {
         match (*self).write(b) {
diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs
index 52e3c718b2d..737fef23c74 100644
--- a/src/libstd/hash.rs
+++ b/src/libstd/hash.rs
@@ -79,7 +79,7 @@ impl RandomSipHasher {
     /// Construct a new `RandomSipHasher` that is initialized with random keys.
     #[inline]
     pub fn new() -> RandomSipHasher {
-        let mut r = rand::task_rng();
+        let mut r = rand::thread_rng();
         let r0 = r.gen();
         let r1 = r.gen();
         RandomSipHasher {
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 1679d2e552f..ffd4122492b 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -39,7 +39,7 @@ use kinds::{Send,Sync};
 /// let file = File::open(&Path::new("message.txt"));
 /// let mut reader = BufferedReader::new(file);
 ///
-/// let mut buf = [0, ..100];
+/// let mut buf = [0; 100];
 /// match reader.read(&mut buf) {
 ///     Ok(nread) => println!("Read {} bytes", nread),
 ///     Err(e) => println!("error reading: {}", e)
@@ -104,7 +104,7 @@ impl<R: Reader> BufferedReader<R> {
 impl<R: Reader> Buffer for BufferedReader<R> {
     fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
         if self.pos == self.cap {
-            self.cap = try!(self.inner.read(self.buf[mut]));
+            self.cap = try!(self.inner.read(self.buf.as_mut_slice()));
             self.pos = 0;
         }
         Ok(self.buf[self.pos..self.cap])
@@ -219,7 +219,7 @@ impl<W: Writer> Writer for BufferedWriter<W> {
         if buf.len() > self.buf.len() {
             self.inner.as_mut().unwrap().write(buf)
         } else {
-            let dst = self.buf[mut self.pos..];
+            let dst = self.buf.slice_from_mut(self.pos);
             slice::bytes::copy_memory(dst, buf);
             self.pos += buf.len();
             Ok(())
@@ -326,7 +326,7 @@ impl<W: Reader> Reader for InternalBufferedWriter<W> {
 /// stream.write("hello, world".as_bytes());
 /// stream.flush();
 ///
-/// let mut buf = [0, ..100];
+/// let mut buf = [0; 100];
 /// match stream.read(&mut buf) {
 ///     Ok(nread) => println!("Read {} bytes", nread),
 ///     Err(e) => println!("error reading: {}", e)
@@ -439,9 +439,10 @@ mod test {
 
     impl Reader for ShortReader {
         fn read(&mut self, _: &mut [u8]) -> io::IoResult<uint> {
-            match self.lengths.remove(0) {
-                Some(i) => Ok(i),
-                None => Err(io::standard_error(io::EndOfFile))
+            if self.lengths.is_empty() {
+                Err(io::standard_error(io::EndOfFile))
+            } else {
+                Ok(self.lengths.remove(0))
             }
         }
     }
diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs
index 7b8513ce423..3cdfa8beb07 100644
--- a/src/libstd/io/comm_adapters.rs
+++ b/src/libstd/io/comm_adapters.rs
@@ -30,7 +30,7 @@ use vec::Vec;
 /// # drop(tx);
 /// let mut reader = ChanReader::new(rx);
 ///
-/// let mut buf = [0u8, ..100];
+/// let mut buf = [0u8; 100];
 /// match reader.read(&mut buf) {
 ///     Ok(nread) => println!("Read {} bytes", nread),
 ///     Err(e) => println!("read error: {}", e),
@@ -88,7 +88,7 @@ impl Reader for ChanReader {
         loop {
             let count = match self.fill_buf().ok() {
                 Some(src) => {
-                    let dst = buf[mut num_read..];
+                    let dst = buf.slice_from_mut(num_read);
                     let count = cmp::min(src.len(), dst.len());
                     bytes::copy_memory(dst, src[..count]);
                     count
@@ -175,7 +175,7 @@ mod test {
         }).detach();
 
         let mut reader = ChanReader::new(rx);
-        let mut buf = [0u8, ..3];
+        let mut buf = [0u8; 3];
 
         assert_eq!(Ok(0), reader.read(&mut []));
 
diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs
index dfea9678277..94dba1f7cc7 100644
--- a/src/libstd/io/extensions.rs
+++ b/src/libstd/io/extensions.rs
@@ -22,7 +22,7 @@ use num::Int;
 use ops::FnOnce;
 use option::Option;
 use option::Option::{Some, None};
-use ptr::RawPtr;
+use ptr::PtrExt;
 use result::Result::{Ok, Err};
 use slice::{SliceExt, AsSlice};
 
@@ -86,9 +86,9 @@ pub fn u64_to_le_bytes<T, F>(n: u64, size: uint, f: F) -> T where
     assert!(size <= 8u);
     match size {
       1u => f(&[n as u8]),
-      2u => f(unsafe { & transmute::<_, [u8, ..2]>((n as u16).to_le()) }),
-      4u => f(unsafe { & transmute::<_, [u8, ..4]>((n as u32).to_le()) }),
-      8u => f(unsafe { & transmute::<_, [u8, ..8]>(n.to_le()) }),
+      2u => f(unsafe { & transmute::<_, [u8; 2]>((n as u16).to_le()) }),
+      4u => f(unsafe { & transmute::<_, [u8; 4]>((n as u32).to_le()) }),
+      8u => f(unsafe { & transmute::<_, [u8; 8]>(n.to_le()) }),
       _ => {
 
         let mut bytes = vec!();
@@ -127,9 +127,9 @@ pub fn u64_to_be_bytes<T, F>(n: u64, size: uint, f: F) -> T where
     assert!(size <= 8u);
     match size {
       1u => f(&[n as u8]),
-      2u => f(unsafe { & transmute::<_, [u8, ..2]>((n as u16).to_be()) }),
-      4u => f(unsafe { & transmute::<_, [u8, ..4]>((n as u32).to_be()) }),
-      8u => f(unsafe { & transmute::<_, [u8, ..8]>(n.to_be()) }),
+      2u => f(unsafe { & transmute::<_, [u8; 2]>((n as u16).to_be()) }),
+      4u => f(unsafe { & transmute::<_, [u8; 4]>((n as u32).to_be()) }),
+      8u => f(unsafe { & transmute::<_, [u8; 8]>(n.to_be()) }),
       _ => {
         let mut bytes = vec!();
         let mut i = size;
@@ -164,7 +164,7 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
         panic!("index out of bounds");
     }
 
-    let mut buf = [0u8, ..8];
+    let mut buf = [0u8; 8];
     unsafe {
         let ptr = data.as_ptr().offset(start as int);
         let out = buf.as_mut_ptr();
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index 20920e60561..7fa5b3cfac7 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -558,6 +558,7 @@ pub fn walk_dir(path: &Path) -> IoResult<Directories> {
 }
 
 /// An iterator that walks over a directory
+#[deriving(Clone)]
 pub struct Directories {
     stack: Vec<Path>,
 }
@@ -881,7 +882,7 @@ mod test {
         }
         {
             let mut read_stream = File::open_mode(filename, Open, Read);
-            let mut read_buf = [0, .. 1028];
+            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[..n]).unwrap().to_string()
@@ -921,7 +922,7 @@ mod test {
     #[test]
     fn file_test_io_non_positional_read() {
         let message: &str = "ten-four";
-        let mut read_mem = [0, .. 8];
+        let mut read_mem = [0; 8];
         let tmpdir = tmpdir();
         let filename = &tmpdir.join("file_rt_io_file_test_positional.txt");
         {
@@ -931,11 +932,11 @@ mod test {
         {
             let mut read_stream = File::open_mode(filename, Open, Read);
             {
-                let read_buf = read_mem[mut 0..4];
+                let read_buf = read_mem.slice_mut(0, 4);
                 check!(read_stream.read(read_buf));
             }
             {
-                let read_buf = read_mem[mut 4..8];
+                let read_buf = read_mem.slice_mut(4, 8);
                 check!(read_stream.read(read_buf));
             }
         }
@@ -947,7 +948,7 @@ mod test {
     #[test]
     fn file_test_io_seek_and_tell_smoke_test() {
         let message = "ten-four";
-        let mut read_mem = [0, .. 4];
+        let mut read_mem = [0; 4];
         let set_cursor = 4 as u64;
         let mut tell_pos_pre_read;
         let mut tell_pos_post_read;
@@ -977,7 +978,7 @@ mod test {
         let overwrite_msg =    "-the-bar!!";
         let final_msg =     "foo-the-bar!!";
         let seek_idx = 3i;
-        let mut read_mem = [0, .. 13];
+        let mut read_mem = [0; 13];
         let tmpdir = tmpdir();
         let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt");
         {
@@ -1002,7 +1003,7 @@ mod test {
         let chunk_one: &str = "qwer";
         let chunk_two: &str = "asdf";
         let chunk_three: &str = "zxcv";
-        let mut read_mem = [0, .. 4];
+        let mut read_mem = [0; 4];
         let tmpdir = tmpdir();
         let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
         {
@@ -1104,7 +1105,7 @@ mod test {
             check!(w.write(msg));
         }
         let files = check!(readdir(dir));
-        let mut mem = [0u8, .. 4];
+        let mut mem = [0u8; 4];
         for f in files.iter() {
             {
                 let n = f.filestem_str();
@@ -1136,7 +1137,7 @@ mod test {
         check!(File::create(&dir2.join("14")));
 
         let mut files = check!(walk_dir(dir));
-        let mut cur = [0u8, .. 2];
+        let mut cur = [0u8; 2];
         for f in files {
             let stem = f.filestem_str().unwrap();
             let root = stem.as_bytes()[0] - b'0';
@@ -1149,6 +1150,19 @@ mod test {
     }
 
     #[test]
+    fn mkdir_path_already_exists_error() {
+        use io::{IoError, PathAlreadyExists};
+
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("mkdir_error_twice");
+        check!(mkdir(dir, io::USER_RWX));
+        match mkdir(dir, io::USER_RWX) {
+            Err(IoError{kind:PathAlreadyExists,..}) => (),
+            _ => assert!(false)
+        };
+    }
+
+    #[test]
     fn recursive_mkdir() {
         let tmpdir = tmpdir();
         let dir = tmpdir.join("d1/d2");
@@ -1532,7 +1546,7 @@ mod test {
     fn binary_file() {
         use rand::{StdRng, Rng};
 
-        let mut bytes = [0, ..1024];
+        let mut bytes = [0; 1024];
         StdRng::new().ok().unwrap().fill_bytes(&mut bytes);
 
         let tmpdir = tmpdir();
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index 71c42273c22..e5d95974edb 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -169,7 +169,7 @@ impl Reader for MemReader {
         let write_len = min(buf.len(), self.buf.len() - self.pos);
         {
             let input = self.buf[self.pos.. self.pos + write_len];
-            let output = buf[mut ..write_len];
+            let output = buf.slice_to_mut(write_len);
             assert_eq!(input.len(), output.len());
             slice::bytes::copy_memory(output, input);
         }
@@ -214,7 +214,7 @@ impl<'a> Reader for &'a [u8] {
         let write_len = min(buf.len(), self.len());
         {
             let input = self[..write_len];
-            let output = buf[mut ..write_len];
+            let output = buf.slice_to_mut(write_len);
             slice::bytes::copy_memory(output, input);
         }
 
@@ -252,7 +252,7 @@ impl<'a> Buffer for &'a [u8] {
 /// # #![allow(unused_must_use)]
 /// use std::io::BufWriter;
 ///
-/// let mut buf = [0, ..4];
+/// let mut buf = [0; 4];
 /// {
 ///     let mut w = BufWriter::new(&mut buf);
 ///     w.write(&[0, 1, 2]);
@@ -279,7 +279,7 @@ impl<'a> BufWriter<'a> {
 impl<'a> Writer for BufWriter<'a> {
     #[inline]
     fn write(&mut self, src: &[u8]) -> IoResult<()> {
-        let dst = self.buf[mut self.pos..];
+        let dst = self.buf.slice_from_mut(self.pos);
         let dst_len = dst.len();
 
         if dst_len == 0 {
@@ -359,7 +359,7 @@ impl<'a> Reader for BufReader<'a> {
         let write_len = min(buf.len(), self.buf.len() - self.pos);
         {
             let input = self.buf[self.pos.. self.pos + write_len];
-            let output = buf[mut ..write_len];
+            let output = buf.slice_to_mut(write_len);
             assert_eq!(input.len(), output.len());
             slice::bytes::copy_memory(output, input);
         }
@@ -428,7 +428,7 @@ mod test {
 
     #[test]
     fn test_buf_writer() {
-        let mut buf = [0 as u8, ..9];
+        let mut buf = [0 as u8; 9];
         {
             let mut writer = BufWriter::new(&mut buf);
             assert_eq!(writer.tell(), Ok(0));
@@ -449,7 +449,7 @@ mod test {
 
     #[test]
     fn test_buf_writer_seek() {
-        let mut buf = [0 as u8, ..8];
+        let mut buf = [0 as u8; 8];
         {
             let mut writer = BufWriter::new(&mut buf);
             assert_eq!(writer.tell(), Ok(0));
@@ -478,7 +478,7 @@ mod test {
 
     #[test]
     fn test_buf_writer_error() {
-        let mut buf = [0 as u8, ..2];
+        let mut buf = [0 as u8; 2];
         let mut writer = BufWriter::new(&mut buf);
         writer.write(&[0]).unwrap();
 
@@ -499,7 +499,7 @@ mod test {
         assert_eq!(reader.tell(), Ok(1));
         let b: &[_] = &[0];
         assert_eq!(buf, b);
-        let mut buf = [0, ..4];
+        let mut buf = [0; 4];
         assert_eq!(reader.read(&mut buf), Ok(4));
         assert_eq!(reader.tell(), Ok(5));
         let b: &[_] = &[1, 2, 3, 4];
@@ -525,7 +525,7 @@ mod test {
         assert_eq!(reader.len(), 7);
         let b: &[_] = &[0];
         assert_eq!(buf.as_slice(), b);
-        let mut buf = [0, ..4];
+        let mut buf = [0; 4];
         assert_eq!(reader.read(&mut buf), Ok(4));
         assert_eq!(reader.len(), 3);
         let b: &[_] = &[1, 2, 3, 4];
@@ -552,7 +552,7 @@ mod test {
         assert_eq!(reader.tell(), Ok(1));
         let b: &[_] = &[0];
         assert_eq!(buf, b);
-        let mut buf = [0, ..4];
+        let mut buf = [0; 4];
         assert_eq!(reader.read(&mut buf), Ok(4));
         assert_eq!(reader.tell(), Ok(5));
         let b: &[_] = &[1, 2, 3, 4];
@@ -649,11 +649,11 @@ mod test {
     #[test]
     fn io_read_at_least() {
         let mut r = MemReader::new(vec![1, 2, 3, 4, 5, 6, 7, 8]);
-        let mut buf = [0, ..3];
+        let mut buf = [0; 3];
         assert!(r.read_at_least(buf.len(), &mut buf).is_ok());
         let b: &[_] = &[1, 2, 3];
         assert_eq!(buf, b);
-        assert!(r.read_at_least(0, buf[mut ..0]).is_ok());
+        assert!(r.read_at_least(0, buf.slice_to_mut(0)).is_ok());
         assert_eq!(buf, b);
         assert!(r.read_at_least(buf.len(), &mut buf).is_ok());
         let b: &[_] = &[4, 5, 6];
@@ -722,13 +722,13 @@ mod test {
     #[bench]
     fn bench_mem_reader(b: &mut Bencher) {
         b.iter(|| {
-            let buf = [5 as u8, ..100].to_vec();
+            let buf = [5 as u8; 100].to_vec();
             {
                 let mut rdr = MemReader::new(buf);
                 for _i in range(0u, 10) {
-                    let mut buf = [0 as u8, .. 10];
+                    let mut buf = [0 as u8; 10];
                     rdr.read(&mut buf).unwrap();
-                    assert_eq!(buf.as_slice(), [5, .. 10].as_slice());
+                    assert_eq!(buf.as_slice(), [5; 10].as_slice());
                 }
             }
         });
@@ -737,27 +737,27 @@ mod test {
     #[bench]
     fn bench_buf_writer(b: &mut Bencher) {
         b.iter(|| {
-            let mut buf = [0 as u8, ..100];
+            let mut buf = [0 as u8; 100];
             {
                 let mut wr = BufWriter::new(&mut buf);
                 for _i in range(0u, 10) {
-                    wr.write(&[5, .. 10]).unwrap();
+                    wr.write(&[5; 10]).unwrap();
                 }
             }
-            assert_eq!(buf.as_slice(), [5, .. 100].as_slice());
+            assert_eq!(buf.as_slice(), [5; 100].as_slice());
         });
     }
 
     #[bench]
     fn bench_buf_reader(b: &mut Bencher) {
         b.iter(|| {
-            let buf = [5 as u8, ..100];
+            let buf = [5 as u8; 100];
             {
                 let mut rdr = BufReader::new(&buf);
                 for _i in range(0u, 10) {
-                    let mut buf = [0 as u8, .. 10];
+                    let mut buf = [0 as u8; 10];
                     rdr.read(&mut buf).unwrap();
-                    assert_eq!(buf, [5, .. 10]);
+                    assert_eq!(buf, [5; 10]);
                 }
             }
         });
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 0f8b3de4804..93a9e04501e 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -513,7 +513,7 @@ pub trait Reader {
         while read < min {
             let mut zeroes = 0;
             loop {
-                match self.read(buf[mut read..]) {
+                match self.read(buf.slice_from_mut(read)) {
                     Ok(0) => {
                         zeroes += 1;
                         if zeroes >= NO_PROGRESS_LIMIT {
@@ -935,7 +935,7 @@ impl<'a> Reader for &'a mut (Reader+'a) {
 // API yet. If so, it should be a method on Vec.
 unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -> &'a mut [T] {
     use raw::Slice;
-    use ptr::RawPtr;
+    use ptr::PtrExt;
 
     assert!(start <= end);
     assert!(end <= v.capacity());
@@ -1017,8 +1017,6 @@ pub trait Writer {
     /// decide whether their stream needs to be buffered or not.
     fn flush(&mut self) -> IoResult<()> { Ok(()) }
 
-    // NOTE(stage0): Remove cfg after a snapshot
-    #[cfg(not(stage0))]
     /// Writes a formatted string into this writer, returning any error
     /// encountered.
     ///
@@ -1057,45 +1055,6 @@ pub trait Writer {
     }
 
 
-    // NOTE(stage0): Remove method after a snapshot
-    #[cfg(stage0)]
-    /// Writes a formatted string into this writer, returning any error
-    /// encountered.
-    ///
-    /// This method is primarily used to interface with the `format_args!`
-    /// macro, but it is rare that this should explicitly be called. The
-    /// `write!` macro should be favored to invoke this method instead.
-    ///
-    /// # Errors
-    ///
-    /// This function will return any I/O error reported while formatting.
-    fn write_fmt(&mut self, fmt: &fmt::Arguments) -> IoResult<()> {
-        // Create a shim which translates a Writer to a FormatWriter and saves
-        // off I/O errors. instead of discarding them
-        struct Adaptor<'a, T:'a> {
-            inner: &'a mut T,
-            error: IoResult<()>,
-        }
-
-        impl<'a, T: Writer> fmt::FormatWriter for Adaptor<'a, T> {
-            fn write(&mut self, bytes: &[u8]) -> fmt::Result {
-                match self.inner.write(bytes) {
-                    Ok(()) => Ok(()),
-                    Err(e) => {
-                        self.error = Err(e);
-                        Err(fmt::Error)
-                    }
-                }
-            }
-        }
-
-        let mut output = Adaptor { inner: self, error: Ok(()) };
-        match fmt::write(&mut output, fmt) {
-            Ok(()) => Ok(()),
-            Err(..) => output.error
-        }
-    }
-
     /// Write a rust string into this sink.
     ///
     /// The bytes written will be the UTF-8 encoded version of the input string.
@@ -1122,8 +1081,8 @@ pub trait Writer {
     /// Write a single char, encoded as UTF-8.
     #[inline]
     fn write_char(&mut self, c: char) -> IoResult<()> {
-        let mut buf = [0u8, ..4];
-        let n = c.encode_utf8(buf[mut]).unwrap_or(0);
+        let mut buf = [0u8; 4];
+        let n = c.encode_utf8(buf.as_mut_slice()).unwrap_or(0);
         self.write(buf[..n])
     }
 
@@ -1555,7 +1514,7 @@ pub trait Buffer: Reader {
         {
             let mut start = 1;
             while start < width {
-                match try!(self.read(buf[mut start..width])) {
+                match try!(self.read(buf.slice_mut(start, width))) {
                     n if n == width - start => break,
                     n if n < width - start => { start += n; }
                     _ => return Err(standard_error(InvalidInput)),
@@ -1724,7 +1683,7 @@ pub fn standard_error(kind: IoErrorKind) -> IoError {
 /// A mode specifies how a file should be opened or created. These modes are
 /// passed to `File::open_mode` and are used to control where the file is
 /// positioned when it is initially opened.
-#[deriving(Copy)]
+#[deriving(Copy, Clone, PartialEq, Eq)]
 pub enum FileMode {
     /// Opens a file positioned at the beginning.
     Open,
@@ -1736,7 +1695,7 @@ pub enum FileMode {
 
 /// Access permissions with which the file should be opened. `File`s
 /// opened with `Read` will return an error if written to.
-#[deriving(Copy)]
+#[deriving(Copy, Clone, PartialEq, Eq)]
 pub enum FileAccess {
     /// Read-only access, requests to write will result in an error
     Read,
@@ -2009,7 +1968,7 @@ mod tests {
     fn test_read_at_least() {
         let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
                                    vec![GoodBehavior(uint::MAX)]);
-        let buf = &mut [0u8, ..5];
+        let buf = &mut [0u8; 5];
         assert!(r.read_at_least(1, buf).unwrap() >= 1);
         assert!(r.read_exact(5).unwrap().len() == 5); // read_exact uses read_at_least
         assert!(r.read_at_least(0, buf).is_ok());
diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs
index 18993aaa9d0..d86cb841f96 100644
--- a/src/libstd/io/net/addrinfo.rs
+++ b/src/libstd/io/net/addrinfo.rs
@@ -10,8 +10,8 @@
 
 //! Synchronous DNS Resolution
 //!
-//! Contains the functionality to perform DNS resolution in a style related to
-//! `getaddrinfo()`
+//! Contains the functionality to perform DNS resolution or reverse lookup,
+//! in a style related to `getaddrinfo()` and `getnameinfo()`, respectively.
 
 #![allow(missing_docs)]
 
@@ -24,6 +24,7 @@ use io::{IoResult};
 use io::net::ip::{SocketAddr, IpAddr};
 use option::Option;
 use option::Option::{Some, None};
+use string::String;
 use sys;
 use vec::Vec;
 
@@ -83,6 +84,12 @@ pub fn get_host_addresses(host: &str) -> IoResult<Vec<IpAddr>> {
     lookup(Some(host), None, None).map(|a| a.into_iter().map(|i| i.address.ip).collect())
 }
 
+/// Reverse name resolution. Given an address, returns the corresponding
+/// hostname.
+pub fn get_address_name(addr: IpAddr) -> IoResult<String> {
+    sys::addrinfo::get_address_name(addr)
+}
+
 /// Full-fledged resolution. This function will perform a synchronous call to
 /// getaddrinfo, controlled by the parameters
 ///
diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs
index ce6bac0f8c4..7ce1d1fc13b 100644
--- a/src/libstd/io/net/ip.rs
+++ b/src/libstd/io/net/ip.rs
@@ -223,7 +223,7 @@ impl<'a> Parser<'a> {
     }
 
     fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
-        let mut bs = [0u8, ..4];
+        let mut bs = [0u8; 4];
         let mut i = 0;
         while i < 4 {
             if i != 0 && self.read_given_char('.').is_none() {
@@ -248,13 +248,13 @@ impl<'a> Parser<'a> {
     fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
         fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
             assert!(head.len() + tail.len() <= 8);
-            let mut gs = [0u16, ..8];
+            let mut gs = [0u16; 8];
             gs.clone_from_slice(head);
-            gs[mut 8 - tail.len() .. 8].clone_from_slice(tail);
+            gs.slice_mut(8 - tail.len(), 8).clone_from_slice(tail);
             Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
         }
 
-        fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
+        fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: uint) -> (uint, bool) {
             let mut i = 0;
             while i < limit {
                 if i < limit - 1 {
@@ -291,7 +291,7 @@ impl<'a> Parser<'a> {
             (i, false)
         }
 
-        let mut head = [0u16, ..8];
+        let mut head = [0u16; 8];
         let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
 
         if head_size == 8 {
@@ -310,7 +310,7 @@ impl<'a> Parser<'a> {
             return None;
         }
 
-        let mut tail = [0u16, ..8];
+        let mut tail = [0u16; 8];
         let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
         Some(ipv6_addr_from_head_tail(head[..head_size], tail[..tail_size]))
     }
diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs
index 68f3a8e1836..daefdd28b30 100644
--- a/src/libstd/io/net/pipe.rs
+++ b/src/libstd/io/net/pipe.rs
@@ -676,7 +676,7 @@ mod tests {
 
         s.set_timeout(Some(20));
         for i in range(0u, 1001) {
-            match s.write(&[0, .. 128 * 1024]) {
+            match s.write(&[0; 128 * 1024]) {
                 Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
                 Err(IoError { kind: TimedOut, .. }) => break,
                 Err(e) => panic!("{}", e),
@@ -705,7 +705,7 @@ mod tests {
             rx.recv().unwrap();
             let mut amt = 0;
             while amt < 100 * 128 * 1024 {
-                match s.read(&mut [0, ..128 * 1024]) {
+                match s.read(&mut [0;128 * 1024]) {
                     Ok(n) => { amt += n; }
                     Err(e) => panic!("{}", e),
                 }
@@ -720,7 +720,7 @@ mod tests {
 
         tx.send(()).unwrap();
         for _ in range(0u, 100) {
-            assert!(s.write(&[0, ..128 * 1024]).is_ok());
+            assert!(s.write(&[0;128 * 1024]).is_ok());
         }
     }
 
@@ -739,7 +739,7 @@ mod tests {
         let mut s = a.accept().unwrap();
         s.set_write_timeout(Some(20));
         for i in range(0u, 1001) {
-            match s.write(&[0, .. 128 * 1024]) {
+            match s.write(&[0; 128 * 1024]) {
                 Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
                 Err(IoError { kind: TimedOut, .. }) => break,
                 Err(e) => panic!("{}", e),
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
index 57ffcfaad30..3e59aaa05ef 100644
--- a/src/libstd/io/net/tcp.rs
+++ b/src/libstd/io/net/tcp.rs
@@ -982,7 +982,7 @@ mod test {
 
         rx.recv().unwrap();
         let mut c = TcpStream::connect(addr).unwrap();
-        let mut b = [0, ..10];
+        let mut b = [0; 10];
         assert_eq!(c.read(&mut b), Ok(1));
         c.write(&[1]).unwrap();
         rx.recv().unwrap();
@@ -1259,7 +1259,7 @@ mod test {
 
         s.set_timeout(Some(20));
         for i in range(0i, 1001) {
-            match s.write(&[0, .. 128 * 1024]) {
+            match s.write(&[0; 128 * 1024]) {
                 Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
                 Err(IoError { kind: TimedOut, .. }) => break,
                 Err(e) => panic!("{}", e),
@@ -1283,7 +1283,7 @@ mod test {
             rx.recv().unwrap();
             let mut amt = 0;
             while amt < 100 * 128 * 1024 {
-                match s.read(&mut [0, ..128 * 1024]) {
+                match s.read(&mut [0;128 * 1024]) {
                     Ok(n) => { amt += n; }
                     Err(e) => panic!("{}", e),
                 }
@@ -1298,7 +1298,7 @@ mod test {
 
         tx.send(()).unwrap();
         for _ in range(0i, 100) {
-            assert!(s.write(&[0, ..128 * 1024]).is_ok());
+            assert!(s.write(&[0;128 * 1024]).is_ok());
         }
     }
 
@@ -1317,7 +1317,7 @@ mod test {
         let mut s = a.accept().unwrap();
         s.set_write_timeout(Some(20));
         for i in range(0i, 1001) {
-            match s.write(&[0, .. 128 * 1024]) {
+            match s.write(&[0; 128 * 1024]) {
                 Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
                 Err(IoError { kind: TimedOut, .. }) => break,
                 Err(e) => panic!("{}", e),
diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs
index d6c379cc9f7..6c167359966 100644
--- a/src/libstd/io/net/udp.rs
+++ b/src/libstd/io/net/udp.rs
@@ -45,11 +45,11 @@ use sys_common;
 ///         Err(e) => panic!("couldn't bind socket: {}", e),
 ///     };
 ///
-///     let mut buf = [0, ..10];
+///     let mut buf = [0; 10];
 ///     match socket.recv_from(&mut buf) {
 ///         Ok((amt, src)) => {
 ///             // Send a reply to the socket we received data from
-///             let buf = buf[mut ..amt];
+///             let buf = buf.slice_to_mut(amt);
 ///             buf.reverse();
 ///             socket.send_to(buf, src);
 ///         }
@@ -347,7 +347,7 @@ mod test {
         let (tx2, rx2) = channel();
 
         let _t = Thread::spawn(move|| {
-            let send_as = |ip, val: &[u8]| {
+            let send_as = |&:ip, val: &[u8]| {
                 match UdpSocket::bind(ip) {
                     Ok(client) => {
                         let client = box client;
@@ -602,7 +602,7 @@ mod test {
 
         a.set_write_timeout(Some(1000));
         for _ in range(0u, 100) {
-            match a.send_to(&[0, ..4*1024], addr2) {
+            match a.send_to(&[0;4*1024], addr2) {
                 Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
                 Err(IoError { kind: TimedOut, .. }) => break,
                 Err(e) => panic!("other error: {}", e),
diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs
index ee376658283..09dcafb0218 100644
--- a/src/libstd/io/pipe.rs
+++ b/src/libstd/io/pipe.rs
@@ -132,7 +132,7 @@ mod test {
             rx.recv().unwrap(); // don't close the pipe until the other read has finished
         });
 
-        let mut buf = [0, ..10];
+        let mut buf = [0; 10];
         input.read(&mut buf).unwrap();
         tx.send(()).unwrap();
     }
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
index 1e008287a31..fedc102e45d 100644
--- a/src/libstd/io/process.rs
+++ b/src/libstd/io/process.rs
@@ -1208,6 +1208,7 @@ mod tests {
     #[test]
     #[cfg(windows)]
     fn env_map_keys_ci() {
+        use c_str::ToCStr;
         use super::EnvKey;
         let mut cmd = Command::new("");
         cmd.env("path", "foo");
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 74b0930a145..156c37c3be7 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -146,7 +146,7 @@ impl StdinReader {
     /// ```
     pub fn lock<'a>(&'a mut self) -> StdinReaderGuard<'a> {
         StdinReaderGuard {
-            inner: self.inner.lock()
+            inner: self.inner.lock().unwrap()
         }
     }
 
@@ -155,7 +155,7 @@ impl StdinReader {
     /// The read is performed atomically - concurrent read calls in other
     /// threads will not interleave with this one.
     pub fn read_line(&mut self) -> IoResult<String> {
-        self.inner.lock().0.read_line()
+        self.inner.lock().unwrap().0.read_line()
     }
 
     /// Like `Buffer::read_until`.
@@ -163,7 +163,7 @@ impl StdinReader {
     /// The read is performed atomically - concurrent read calls in other
     /// threads will not interleave with this one.
     pub fn read_until(&mut self, byte: u8) -> IoResult<Vec<u8>> {
-        self.inner.lock().0.read_until(byte)
+        self.inner.lock().unwrap().0.read_until(byte)
     }
 
     /// Like `Buffer::read_char`.
@@ -171,13 +171,13 @@ impl StdinReader {
     /// The read is performed atomically - concurrent read calls in other
     /// threads will not interleave with this one.
     pub fn read_char(&mut self) -> IoResult<char> {
-        self.inner.lock().0.read_char()
+        self.inner.lock().unwrap().0.read_char()
     }
 }
 
 impl Reader for StdinReader {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
-        self.inner.lock().0.read(buf)
+        self.inner.lock().unwrap().0.read(buf)
     }
 
     // We have to manually delegate all of these because the default impls call
@@ -185,23 +185,23 @@ impl Reader for StdinReader {
     // incur the costs of repeated locking).
 
     fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult<uint> {
-        self.inner.lock().0.read_at_least(min, buf)
+        self.inner.lock().unwrap().0.read_at_least(min, buf)
     }
 
     fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> {
-        self.inner.lock().0.push_at_least(min, len, buf)
+        self.inner.lock().unwrap().0.push_at_least(min, len, buf)
     }
 
     fn read_to_end(&mut self) -> IoResult<Vec<u8>> {
-        self.inner.lock().0.read_to_end()
+        self.inner.lock().unwrap().0.read_to_end()
     }
 
     fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
-        self.inner.lock().0.read_le_uint_n(nbytes)
+        self.inner.lock().unwrap().0.read_le_uint_n(nbytes)
     }
 
     fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
-        self.inner.lock().0.read_be_uint_n(nbytes)
+        self.inner.lock().unwrap().0.read_be_uint_n(nbytes)
     }
 }
 
@@ -334,7 +334,7 @@ pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
 //          // io1 aliases io2
 //      })
 //  })
-fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) {
+fn with_task_stdout<F>(f: F) where F: FnOnce(&mut Writer) -> IoResult<()> {
     let mut my_stdout = LOCAL_STDOUT.with(|slot| {
         slot.borrow_mut().take()
     }).unwrap_or_else(|| {
@@ -378,38 +378,18 @@ pub fn println(s: &str) {
     })
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
 /// with the `format_args!` macro.
 pub fn print_args(fmt: fmt::Arguments) {
     with_task_stdout(|io| write!(io, "{}", fmt))
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
-/// with the `format_args!` macro.
-pub fn print_args(fmt: &fmt::Arguments) {
-    with_task_stdout(|io| write!(io, "{}", fmt))
-}
-
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Similar to `println`, but takes a `fmt::Arguments` structure to be
 /// compatible with the `format_args!` macro.
 pub fn println_args(fmt: fmt::Arguments) {
     with_task_stdout(|io| writeln!(io, "{}", fmt))
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-/// Similar to `println`, but takes a `fmt::Arguments` structure to be
-/// compatible with the `format_args!` macro.
-pub fn println_args(fmt: &fmt::Arguments) {
-    with_task_stdout(|io| writeln!(io, "{}", fmt))
-}
-
 /// Representation of a reader of a standard input stream
 pub struct StdReader {
     inner: StdSource
diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs
index 9c6033f37c9..7592e7692db 100644
--- a/src/libstd/io/test.rs
+++ b/src/libstd/io/test.rs
@@ -131,7 +131,7 @@ mod darwin_fd_limit {
         use os::last_os_error;
 
         // Fetch the kern.maxfilesperproc value
-        let mut mib: [libc::c_int, ..2] = [CTL_KERN, KERN_MAXFILESPERPROC];
+        let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC];
         let mut maxfiles: libc::c_int = 0;
         let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
         if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size,
diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs
index e073f76af82..de4270e705b 100644
--- a/src/libstd/io/timer.rs
+++ b/src/libstd/io/timer.rs
@@ -225,6 +225,8 @@ fn in_ms_u64(d: Duration) -> u64 {
 
 #[cfg(test)]
 mod test {
+    use prelude::v1::*;
+
     use super::Timer;
     use thread::Thread;
     use time::Duration;
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index b22090e0f16..38ab71c172c 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -51,7 +51,7 @@ impl<R: Reader> Reader for LimitReader<R> {
         }
 
         let len = cmp::min(self.limit, buf.len());
-        let res = self.inner.read(buf[mut ..len]);
+        let res = self.inner.read(buf.slice_to_mut(len));
         match res {
             Ok(len) => self.limit -= len,
             _ => {}
@@ -103,7 +103,7 @@ impl Reader for ZeroReader {
 
 impl Buffer for ZeroReader {
     fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
-        static DATA: [u8, ..64] = [0, ..64];
+        static DATA: [u8; 64] = [0; 64];
         Ok(DATA.as_slice())
     }
 
@@ -163,6 +163,7 @@ impl Writer for MultiWriter {
 
 /// A `Reader` which chains input from multiple `Reader`s, reading each to
 /// completion before moving onto the next.
+#[deriving(Clone)]
 pub struct ChainedReader<I, R> {
     readers: I,
     cur_reader: Option<R>,
@@ -234,7 +235,7 @@ impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
 
 /// Copies all data from a `Reader` to a `Writer`.
 pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
-    let mut buf = [0, ..super::DEFAULT_BUF_SIZE];
+    let mut buf = [0; super::DEFAULT_BUF_SIZE];
     loop {
         let len = match r.read(&mut buf) {
             Ok(len) => len,
@@ -246,6 +247,7 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
 }
 
 /// An adaptor converting an `Iterator<u8>` to a `Reader`.
+#[deriving(Clone)]
 pub struct IterReader<T> {
     iter: T,
 }
@@ -276,11 +278,11 @@ impl<T: Iterator<u8>> Reader for IterReader<T> {
 
 #[cfg(test)]
 mod test {
+    use prelude::v1::*;
+
     use io::{MemReader, ByRefReader};
     use io;
-    use boxed::Box;
     use super::*;
-    use prelude::v1::*;
 
     #[test]
     fn test_limit_reader_unlimited() {
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index aa1a0add068..6187593afd1 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -158,6 +158,7 @@ pub use alloc::rc;
 pub use core_collections::slice;
 pub use core_collections::str;
 pub use core_collections::string;
+#[stable]
 pub use core_collections::vec;
 
 pub use unicode::char;
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 51a0853687e..47be8b2dcf9 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -17,8 +17,6 @@
 #![experimental]
 #![macro_escape]
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// The entry point for panic of Rust tasks.
 ///
 /// This macro is used to inject panic into a Rust task, causing the task to
@@ -59,63 +57,6 @@ macro_rules! panic {
     });
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// The entry point for panic of Rust tasks.
-///
-/// This macro is used to inject panic into a Rust task, causing the task to
-/// unwind and panic entirely. Each task's panic can be reaped as the
-/// `Box<Any>` type, and the single-argument form of the `panic!` macro will be
-/// the value which is transmitted.
-///
-/// The multi-argument form of this macro panics with a string and has the
-/// `format!` syntax for building a string.
-///
-/// # Example
-///
-/// ```should_fail
-/// # #![allow(unreachable_code)]
-/// panic!();
-/// panic!("this is a terrible mistake!");
-/// panic!(4i); // panic with the value of 4 to be collected elsewhere
-/// panic!("this is a {} {message}", "fancy", message = "message");
-/// ```
-#[macro_export]
-macro_rules! panic {
-    () => ({
-        panic!("explicit panic")
-    });
-    ($msg:expr) => ({
-        // static requires less code at runtime, more constant data
-        static _FILE_LINE: (&'static str, uint) = (file!(), line!());
-        ::std::rt::begin_unwind($msg, &_FILE_LINE)
-    });
-    ($fmt:expr, $($arg:tt)*) => ({
-        // a closure can't have return type !, so we need a full
-        // function to pass to format_args!, *and* we need the
-        // file and line numbers right here; so an inner bare fn
-        // is our only choice.
-        //
-        // LLVM doesn't tend to inline this, presumably because begin_unwind_fmt
-        // is #[cold] and #[inline(never)] and because this is flagged as cold
-        // as returning !. We really do want this to be inlined, however,
-        // because it's just a tiny wrapper. Small wins (156K to 149K in size)
-        // were seen when forcing this to be inlined, and that number just goes
-        // up with the number of calls to panic!()
-        //
-        // The leading _'s are to avoid dead code warnings if this is
-        // used inside a dead function. Just `#[allow(dead_code)]` is
-        // insufficient, since the user may have
-        // `#[forbid(dead_code)]` and which cannot be overridden.
-        #[inline(always)]
-        fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! {
-            static _FILE_LINE: (&'static str, uint) = (file!(), line!());
-            ::std::rt::begin_unwind_fmt(fmt, &_FILE_LINE)
-        }
-        format_args!(_run_fmt, $fmt, $($arg)*)
-    });
-}
-
 /// Ensure that a boolean expression is `true` at runtime.
 ///
 /// This will invoke the `panic!` macro if the provided expression cannot be
@@ -289,8 +230,6 @@ macro_rules! unimplemented {
     () => (panic!("not yet implemented"))
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Use the syntax described in `std::fmt` to create a value of type `String`.
 /// See `std::fmt` for more information.
 ///
@@ -307,28 +246,6 @@ macro_rules! format {
     ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*)))
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// Use the syntax described in `std::fmt` to create a value of type `String`.
-/// See `std::fmt` for more information.
-///
-/// # Example
-///
-/// ```
-/// format!("test");
-/// format!("hello {}", "world!");
-/// format!("x = {}, y = {y}", 10i, y = 30i);
-/// ```
-#[macro_export]
-#[stable]
-macro_rules! format {
-    ($($arg:tt)*) => (
-        format_args!(::std::fmt::format, $($arg)*)
-    )
-}
-
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
 /// See `std::fmt` for more information.
 ///
@@ -347,29 +264,6 @@ macro_rules! write {
     ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*)))
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`.
-/// See `std::fmt` for more information.
-///
-/// # Example
-///
-/// ```
-/// # #![allow(unused_must_use)]
-///
-/// let mut w = Vec::new();
-/// write!(&mut w, "test");
-/// write!(&mut w, "formatted {}", "arguments");
-/// ```
-#[macro_export]
-#[stable]
-macro_rules! write {
-    ($dst:expr, $($arg:tt)*) => ({
-        let dst = &mut *$dst;
-        format_args!(|args| { dst.write_fmt(args) }, $($arg)*)
-    })
-}
-
 /// Equivalent to the `write!` macro, except that a newline is appended after
 /// the message is written.
 #[macro_export]
@@ -380,8 +274,6 @@ macro_rules! writeln {
     )
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Equivalent to the `println!` macro except that a newline is not printed at
 /// the end of the message.
 #[macro_export]
@@ -390,18 +282,6 @@ macro_rules! print {
     ($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*)))
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// Equivalent to the `println!` macro except that a newline is not printed at
-/// the end of the message.
-#[macro_export]
-#[stable]
-macro_rules! print {
-    ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*))
-}
-
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// Macro for printing to a task's stdout handle.
 ///
 /// Each task can override its stdout handle via `std::io::stdio::set_stdout`.
@@ -420,26 +300,6 @@ macro_rules! println {
     ($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*)))
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-/// Macro for printing to a task's stdout handle.
-///
-/// Each task can override its stdout handle via `std::io::stdio::set_stdout`.
-/// The syntax of this macro is the same as that used for `format!`. For more
-/// information, see `std::fmt` and `std::io::stdio`.
-///
-/// # Example
-///
-/// ```
-/// println!("hello there!");
-/// println!("format {} arguments", "some");
-/// ```
-#[macro_export]
-#[stable]
-macro_rules! println {
-    ($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*))
-}
-
 /// Helper macro for unwrapping `Result` values while returning early with an
 /// error if the value of the expression is `Err`. For more information, see
 /// `std::io`.
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index b1f4e5acb93..febdf5f6118 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -104,7 +104,7 @@ fn int_to_str_bytes_common<T, F>(num: T, radix: uint, sign: SignFormat, mut f: F
     // This is just for integral types, the largest of which is a u64. The
     // smallest base that we can have is 2, so the most number of digits we're
     // ever going to have is 64
-    let mut buf = [0u8, ..64];
+    let mut buf = [0u8; 64];
     let mut cur = 0;
 
     // Loop at least once to make sure at least a `0` gets emitted.
@@ -321,10 +321,10 @@ pub fn float_to_str_bytes_common<T: Float>(
         // cut off the one extra digit, and depending on its value
         // round the remaining ones.
         if limit_digits && dig == digit_count {
-            let ascii2value = |chr: u8| {
+            let ascii2value = |&: chr: u8| {
                 (chr as char).to_digit(radix).unwrap()
             };
-            let value2ascii = |val: uint| {
+            let value2ascii = |&: val: uint| {
                 char::from_digit(val, radix).unwrap() as u8
             };
 
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index 61fd754018e..b52e4fda7af 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -38,7 +38,7 @@ pub fn to_str_bytes<U, F>(n: $T, radix: uint, f: F) -> U where
     use io::{Writer, Seek};
     // The radix can be as low as 2, so we need at least 64 characters for a
     // base 2 number, and then we need another for a possible '-' character.
-    let mut buf = [0u8, ..65];
+    let mut buf = [0u8; 65];
     let amt = {
         let mut wr = ::io::BufWriter::new(&mut buf);
         (write!(&mut wr, "{}", ::fmt::radix(n, radix as u8))).unwrap();
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 754b13886af..d115a15cc0b 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -46,7 +46,8 @@ use option::Option;
 use option::Option::{Some, None};
 use path::{Path, GenericPath, BytesContainer};
 use sys;
-use ptr::RawPtr;
+use sys::os as os_imp;
+use ptr::PtrExt;
 use ptr;
 use result::Result;
 use result::Result::{Err, Ok};
@@ -619,10 +620,11 @@ pub fn get_exit_status() -> int {
 unsafe fn load_argc_and_argv(argc: int,
                              argv: *const *const c_char) -> Vec<Vec<u8>> {
     use c_str::CString;
+    use iter::range;
 
-    Vec::from_fn(argc as uint, |i| {
+    range(0, argc as uint).map(|i| {
         CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec()
-    })
+    }).collect()
 }
 
 /// Returns the command line arguments
@@ -714,13 +716,14 @@ fn real_args() -> Vec<String> {
 #[cfg(windows)]
 fn real_args() -> Vec<String> {
     use slice;
+    use iter::range;
 
     let mut nArgs: c_int = 0;
     let lpArgCount: *mut c_int = &mut nArgs;
     let lpCmdLine = unsafe { GetCommandLineW() };
     let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) };
 
-    let args = Vec::from_fn(nArgs as uint, |i| unsafe {
+    let args: Vec<_> = range(0, nArgs as uint).map(|i| unsafe {
         // Determine the length of this argument.
         let ptr = *szArgList.offset(i as int);
         let mut len = 0;
@@ -730,8 +733,8 @@ fn real_args() -> Vec<String> {
         let ptr = ptr as *const u16;
         let buf = slice::from_raw_buf(&ptr, len);
         let opt_s = String::from_utf16(sys::os::truncate_utf16_at_nul(buf));
-        opt_s.expect("CommandLineToArgvW returned invalid UTF-16")
-    });
+        opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16")
+    }).collect();
 
     unsafe {
         LocalFree(szArgList as *mut c_void);
@@ -1439,7 +1442,7 @@ mod tests {
     }
 
     fn make_rand_name() -> String {
-        let mut rng = rand::task_rng();
+        let mut rng = rand::thread_rng();
         let n = format!("TEST{}", rng.gen_ascii_chars().take(10u)
                                      .collect::<String>());
         assert!(getenv(n.as_slice()).is_none());
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 5c415239c5e..102da31a293 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -22,14 +22,14 @@ use option::Option::{None, Some};
 use kinds::Sized;
 use str::{FromStr, Str};
 use str;
-use slice::{CloneSliceExt, Splits, AsSlice, VectorVector,
+use slice::{CloneSliceExt, Split, AsSlice, SliceConcatExt,
             PartialEqSliceExt, SliceExt};
 use vec::Vec;
 
 use super::{BytesContainer, GenericPath, GenericPathUnsafe};
 
 /// Iterator that yields successive components of a Path as &[u8]
-pub type Components<'a> = Splits<'a, u8, fn(&u8) -> bool>;
+pub type Components<'a> = Split<'a, u8, fn(&u8) -> bool>;
 
 /// Iterator that yields successive components of a Path as Option<&str>
 pub type StrComponents<'a> =
@@ -306,7 +306,7 @@ impl GenericPath for Path {
                     }
                 }
             }
-            Some(Path::new(comps.connect_vec(&SEP_BYTE)))
+            Some(Path::new(comps.as_slice().connect(&SEP_BYTE)))
         }
     }
 
@@ -447,8 +447,16 @@ static dot_dot_static: &'static [u8] = b"..";
 
 #[cfg(test)]
 mod tests {
-    use prelude::v1::*;
-    use str;
+    use super::*;
+
+    use clone::Clone;
+    use iter::{IteratorExt, DoubleEndedIteratorExt};
+    use option::Option::{mod, Some, None};
+    use path::GenericPath;
+    use slice::{AsSlice, SliceExt, CloneSliceExt};
+    use str::{mod, Str, StrExt};
+    use string::ToString;
+    use vec::Vec;
 
     macro_rules! t {
         (s: $path:expr, $exp:expr) => (
@@ -1236,7 +1244,7 @@ mod bench {
     extern crate test;
     use self::test::Bencher;
     use super::*;
-    use prelude::v1::*;
+    use prelude::v1::{Clone, GenericPath};
 
     #[bench]
     fn join_home_dir(b: &mut Bencher) {
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 9117827ffc2..e047afc8eee 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -21,12 +21,12 @@ use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
 use hash;
 use io::Writer;
 use iter::{AdditiveIterator, DoubleEndedIteratorExt, Extend};
-use iter::{Iterator, IteratorExt, Map};
+use iter::{Iterator, IteratorExt, Map, repeat};
 use mem;
 use option::Option;
 use option::Option::{Some, None};
-use slice::SliceExt;
-use str::{CharSplits, FromStr, StrVector, StrExt};
+use slice::{SliceExt, SliceConcatExt};
+use str::{SplitTerminator, FromStr, StrExt};
 use string::{String, ToString};
 use unicode::char::UnicodeChar;
 use vec::Vec;
@@ -38,7 +38,7 @@ use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
 /// Each component is yielded as Option<&str> for compatibility with PosixPath, but
 /// every component in WindowsPath is guaranteed to be Some.
 pub type StrComponents<'a> =
-    Map<&'a str, Option<&'a str>, CharSplits<'a, char>, fn(&'a str) -> Option<&'a str>>;
+    Map<&'a str, Option<&'a str>, SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>;
 
 /// Iterator that yields successive components of a Path as &[u8]
 pub type Components<'a> =
@@ -777,7 +777,7 @@ impl Path {
                             }
                         }
                     } else if is_abs && comps.is_empty() {
-                        Some(String::from_char(1, SEP))
+                        Some(repeat(SEP).take(1).collect())
                     } else {
                         let prefix_ = s[0..prefix_len(prefix)];
                         let n = prefix_.len() +
@@ -1127,6 +1127,15 @@ mod tests {
     use super::parse_prefix;
     use super::*;
 
+    use clone::Clone;
+    use iter::{IteratorExt, DoubleEndedIteratorExt};
+    use option::Option::{mod, Some, None};
+    use path::GenericPath;
+    use slice::{AsSlice, SliceExt, CloneSliceExt};
+    use str::Str;
+    use string::ToString;
+    use vec::Vec;
+
     macro_rules! t {
         (s: $path:expr, $exp:expr) => (
             {
diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs
index 8c4189c37e7..33146f5e622 100644
--- a/src/libstd/prelude/v1.rs
+++ b/src/libstd/prelude/v1.rs
@@ -31,14 +31,15 @@
 #[stable] #[doc(no_inline)] pub use iter::ExactSizeIterator;
 #[stable] #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend};
 #[stable] #[doc(no_inline)] pub use iter::{IteratorCloneExt, IteratorOrdExt};
+#[stable] #[doc(no_inline)] pub use iter::IteratorPairExt;
 #[stable] #[doc(no_inline)] pub use option::Option::{mod, Some, None};
-#[stable] #[doc(no_inline)] pub use ptr::{RawPtr, RawMutPtr};
+#[stable] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt};
 #[stable] #[doc(no_inline)] pub use result::Result::{mod, Ok, Err};
 #[stable] #[doc(no_inline)] pub use slice::AsSlice;
 #[stable] #[doc(no_inline)] pub use slice::{BoxedSliceExt, SliceExt};
 #[stable] #[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt};
-#[stable] #[doc(no_inline)] pub use slice::{VectorVector, PartialEqSliceExt};
-#[stable] #[doc(no_inline)] pub use str::{Str, StrVector, StrExt};
+#[stable] #[doc(no_inline)] pub use slice::{PartialEqSliceExt, SliceConcatExt};
+#[stable] #[doc(no_inline)] pub use str::{Str, StrExt};
 #[stable] #[doc(no_inline)] pub use string::{String, ToString};
 #[stable] #[doc(no_inline)] pub use vec::Vec;
 
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index 4371fe7e59a..86b8bfc7370 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -18,10 +18,10 @@
 //! See the `distributions` submodule for sampling random numbers from
 //! distributions like normal and exponential.
 //!
-//! # Task-local RNG
+//! # Thread-local RNG
 //!
-//! There is built-in support for a RNG associated with each task stored
-//! in task-local storage. This RNG can be accessed via `task_rng`, or
+//! There is built-in support for a RNG associated with each thread stored
+//! in thread-local storage. This RNG can be accessed via `thread_rng`, or
 //! used implicitly via `random`. This RNG is normally randomly seeded
 //! from an operating-system source of randomness, e.g. `/dev/urandom` on
 //! Unix systems, and will automatically reseed itself from this source
@@ -61,7 +61,7 @@
 //! use std::rand;
 //! use std::rand::Rng;
 //!
-//! let mut rng = rand::task_rng();
+//! let mut rng = rand::thread_rng();
 //! if rng.gen() { // random bool
 //!     println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>())
 //! }
@@ -97,7 +97,7 @@
 //!
 //! fn main() {
 //!    let between = Range::new(-1f64, 1.);
-//!    let mut rng = rand::task_rng();
+//!    let mut rng = rand::thread_rng();
 //!
 //!    let total = 1_000_000u;
 //!    let mut in_circle = 0u;
@@ -183,7 +183,7 @@
 //!     // The estimation will be more accurate with more simulations
 //!     let num_simulations = 10000u;
 //!
-//!     let mut rng = rand::task_rng();
+//!     let mut rng = rand::thread_rng();
 //!     let random_door = Range::new(0u, 3);
 //!
 //!     let (mut switch_wins, mut switch_losses) = (0u, 0u);
@@ -257,7 +257,7 @@ impl StdRng {
     /// randomness from the operating system and use this in an
     /// expensive seeding operation. If one is only generating a small
     /// number of random numbers, or doesn't need the utmost speed for
-    /// generating each number, `task_rng` and/or `random` may be more
+    /// generating each number, `thread_rng` and/or `random` may be more
     /// appropriate.
     ///
     /// Reading the randomness from the OS may fail, and any error is
@@ -307,28 +307,28 @@ pub fn weak_rng() -> XorShiftRng {
     }
 }
 
-/// Controls how the task-local RNG is reseeded.
-struct TaskRngReseeder;
+/// Controls how the thread-local RNG is reseeded.
+struct ThreadRngReseeder;
 
-impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
+impl reseeding::Reseeder<StdRng> for ThreadRngReseeder {
     fn reseed(&mut self, rng: &mut StdRng) {
         *rng = match StdRng::new() {
             Ok(r) => r,
-            Err(e) => panic!("could not reseed task_rng: {}", e)
+            Err(e) => panic!("could not reseed thread_rng: {}", e)
         }
     }
 }
-static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
-type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
+static THREAD_RNG_RESEED_THRESHOLD: uint = 32_768;
+type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>;
 
-/// The task-local RNG.
-pub struct TaskRng {
-    rng: Rc<RefCell<TaskRngInner>>,
+/// The thread-local RNG.
+pub struct ThreadRng {
+    rng: Rc<RefCell<ThreadRngInner>>,
 }
 
-/// Retrieve the lazily-initialized task-local random number
+/// Retrieve the lazily-initialized thread-local random number
 /// generator, seeded by the system. Intended to be used in method
-/// chaining style, e.g. `task_rng().gen::<int>()`.
+/// chaining style, e.g. `thread_rng().gen::<int>()`.
 ///
 /// The RNG provided will reseed itself from the operating system
 /// after generating a certain amount of randomness.
@@ -337,23 +337,23 @@ pub struct TaskRng {
 /// if the operating system random number generator is rigged to give
 /// the same sequence always. If absolute consistency is required,
 /// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
-pub fn task_rng() -> TaskRng {
+pub fn thread_rng() -> ThreadRng {
     // used to make space in TLS for a random number generator
-    thread_local!(static TASK_RNG_KEY: Rc<RefCell<TaskRngInner>> = {
+    thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = {
         let r = match StdRng::new() {
             Ok(r) => r,
-            Err(e) => panic!("could not initialize task_rng: {}", e)
+            Err(e) => panic!("could not initialize thread_rng: {}", e)
         };
         let rng = reseeding::ReseedingRng::new(r,
-                                               TASK_RNG_RESEED_THRESHOLD,
-                                               TaskRngReseeder);
+                                               THREAD_RNG_RESEED_THRESHOLD,
+                                               ThreadRngReseeder);
         Rc::new(RefCell::new(rng))
     });
 
-    TaskRng { rng: TASK_RNG_KEY.with(|t| t.clone()) }
+    ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) }
 }
 
-impl Rng for TaskRng {
+impl Rng for ThreadRng {
     fn next_u32(&mut self) -> u32 {
         self.rng.borrow_mut().next_u32()
     }
@@ -368,7 +368,7 @@ impl Rng for TaskRng {
     }
 }
 
-/// Generates a random value using the task-local random number generator.
+/// Generates a random value using the thread-local random number generator.
 ///
 /// `random()` can generate various types of random things, and so may require
 /// type hinting to generate the specific type you want.
@@ -390,7 +390,7 @@ impl Rng for TaskRng {
 /// ```
 #[inline]
 pub fn random<T: Rand>() -> T {
-    task_rng().gen()
+    thread_rng().gen()
 }
 
 /// Randomly sample up to `amount` elements from an iterator.
@@ -398,9 +398,9 @@ pub fn random<T: Rand>() -> T {
 /// # Example
 ///
 /// ```rust
-/// use std::rand::{task_rng, sample};
+/// use std::rand::{thread_rng, sample};
 ///
-/// let mut rng = task_rng();
+/// let mut rng = thread_rng();
 /// let sample = sample(&mut rng, range(1i, 100), 5);
 /// println!("{}", sample);
 /// ```
@@ -420,7 +420,7 @@ pub fn sample<T, I: Iterator<T>, R: Rng>(rng: &mut R,
 #[cfg(test)]
 mod test {
     use prelude::v1::*;
-    use super::{Rng, task_rng, random, SeedableRng, StdRng, sample};
+    use super::{Rng, thread_rng, random, SeedableRng, StdRng, sample};
     use iter::order;
 
     struct ConstRng { i: u64 }
@@ -453,7 +453,7 @@ mod test {
 
     #[test]
     fn test_gen_range() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         for _ in range(0u, 1000) {
             let a = r.gen_range(-3i, 42);
             assert!(a >= -3 && a < 42);
@@ -473,20 +473,20 @@ mod test {
     #[test]
     #[should_fail]
     fn test_gen_range_panic_int() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         r.gen_range(5i, -2);
     }
 
     #[test]
     #[should_fail]
     fn test_gen_range_panic_uint() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         r.gen_range(5u, 2u);
     }
 
     #[test]
     fn test_gen_f64() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         let a = r.gen::<f64>();
         let b = r.gen::<f64>();
         debug!("{}", (a, b));
@@ -494,14 +494,14 @@ mod test {
 
     #[test]
     fn test_gen_weighted_bool() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         assert_eq!(r.gen_weighted_bool(0u), true);
         assert_eq!(r.gen_weighted_bool(1u), true);
     }
 
     #[test]
     fn test_gen_ascii_str() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         assert_eq!(r.gen_ascii_chars().take(0).count(), 0u);
         assert_eq!(r.gen_ascii_chars().take(10).count(), 10u);
         assert_eq!(r.gen_ascii_chars().take(16).count(), 16u);
@@ -509,7 +509,7 @@ mod test {
 
     #[test]
     fn test_gen_vec() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         assert_eq!(r.gen_iter::<u8>().take(0).count(), 0u);
         assert_eq!(r.gen_iter::<u8>().take(10).count(), 10u);
         assert_eq!(r.gen_iter::<f64>().take(16).count(), 16u);
@@ -517,7 +517,7 @@ mod test {
 
     #[test]
     fn test_choose() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         assert_eq!(r.choose(&[1i, 1, 1]).map(|&x|x), Some(1));
 
         let v: &[int] = &[];
@@ -526,7 +526,7 @@ mod test {
 
     #[test]
     fn test_shuffle() {
-        let mut r = task_rng();
+        let mut r = thread_rng();
         let empty: &mut [int] = &mut [];
         r.shuffle(empty);
         let mut one = [1i];
@@ -545,8 +545,8 @@ mod test {
     }
 
     #[test]
-    fn test_task_rng() {
-        let mut r = task_rng();
+    fn test_thread_rng() {
+        let mut r = thread_rng();
         r.gen::<int>();
         let mut v = [1i, 1, 1];
         r.shuffle(&mut v);
@@ -574,7 +574,7 @@ mod test {
         let min_val = 1i;
         let max_val = 100i;
 
-        let mut r = task_rng();
+        let mut r = thread_rng();
         let vals = range(min_val, max_val).collect::<Vec<int>>();
         let small_sample = sample(&mut r, vals.iter(), 5);
         let large_sample = sample(&mut r, vals.iter(), vals.len() + 5);
@@ -589,7 +589,7 @@ mod test {
 
     #[test]
     fn test_std_rng_seeded() {
-        let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
+        let s = thread_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
         let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
         let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
         assert!(order::equals(ra.gen_ascii_chars().take(100),
@@ -598,7 +598,7 @@ mod test {
 
     #[test]
     fn test_std_rng_reseed() {
-        let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
+        let s = thread_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>();
         let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
         let string1 = r.gen_ascii_chars().take(100).collect::<String>();
 
@@ -669,7 +669,7 @@ mod bench {
     #[bench]
     fn rand_shuffle_100(b: &mut Bencher) {
         let mut rng = weak_rng();
-        let x : &mut[uint] = &mut [1,..100];
+        let x : &mut[uint] = &mut [1; 100];
         b.iter(|| {
             rng.shuffle(x);
         })
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 0a7b9d07636..6b60bcac9ca 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -55,7 +55,7 @@ mod imp {
         let mut read = 0;
         let len = v.len();
         while read < len {
-            let result = getrandom(v[mut read..]);
+            let result = getrandom(v.slice_from_mut(read));
             if result == -1 {
                 let err = errno() as libc::c_int;
                 if err == libc::EINTR {
@@ -70,15 +70,15 @@ mod imp {
     }
 
     fn getrandom_next_u32() -> u32 {
-        let mut buf: [u8, ..4] = [0u8, ..4];
+        let mut buf: [u8; 4] = [0u8; 4];
         getrandom_fill_bytes(&mut buf);
-        unsafe { mem::transmute::<[u8, ..4], u32>(buf) }
+        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
     }
 
     fn getrandom_next_u64() -> u64 {
-        let mut buf: [u8, ..8] = [0u8, ..8];
+        let mut buf: [u8; 8] = [0u8; 8];
         getrandom_fill_bytes(&mut buf);
-        unsafe { mem::transmute::<[u8, ..8], u64>(buf) }
+        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
     }
 
     #[cfg(all(target_os = "linux",
@@ -90,7 +90,7 @@ mod imp {
         static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;
 
         if !GETRANDOM_CHECKED.load(Relaxed) {
-            let mut buf: [u8, ..0] = [];
+            let mut buf: [u8; 0] = [];
             let result = getrandom(&mut buf);
             let available = if result == -1 {
                 let err = errno() as libc::c_int;
@@ -170,6 +170,7 @@ mod imp {
     extern crate libc;
 
     use io::{IoResult};
+    use kinds::Sync;
     use mem;
     use os;
     use rand::Rng;
@@ -196,6 +197,8 @@ mod imp {
     #[repr(C)]
     struct SecRandom;
 
+    unsafe impl Sync for *const SecRandom {}
+
     #[allow(non_upper_case_globals)]
     static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
 
@@ -214,12 +217,12 @@ mod imp {
 
     impl Rng for OsRng {
         fn next_u32(&mut self) -> u32 {
-            let mut v = [0u8, .. 4];
+            let mut v = [0u8; 4];
             self.fill_bytes(&mut v);
             unsafe { mem::transmute(v) }
         }
         fn next_u64(&mut self) -> u64 {
-            let mut v = [0u8, .. 8];
+            let mut v = [0u8; 8];
             self.fill_bytes(&mut v);
             unsafe { mem::transmute(v) }
         }
@@ -301,12 +304,12 @@ mod imp {
 
     impl Rng for OsRng {
         fn next_u32(&mut self) -> u32 {
-            let mut v = [0u8, .. 4];
+            let mut v = [0u8; 4];
             self.fill_bytes(&mut v);
             unsafe { mem::transmute(v) }
         }
         fn next_u64(&mut self) -> u64 {
-            let mut v = [0u8, .. 8];
+            let mut v = [0u8; 8];
             self.fill_bytes(&mut v);
             unsafe { mem::transmute(v) }
         }
@@ -349,7 +352,7 @@ mod test {
         r.next_u32();
         r.next_u64();
 
-        let mut v = [0u8, .. 1000];
+        let mut v = [0u8; 1000];
         r.fill_bytes(&mut v);
     }
 
@@ -369,7 +372,7 @@ mod test {
                 // as possible (XXX: is this a good test?)
                 let mut r = OsRng::new().unwrap();
                 Thread::yield_now();
-                let mut v = [0u8, .. 1000];
+                let mut v = [0u8; 1000];
 
                 for _ in range(0u, 100) {
                     r.next_u32();
diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs
index 642ab3d1e86..48d7f2e7854 100644
--- a/src/libstd/rand/reader.rs
+++ b/src/libstd/rand/reader.rs
@@ -105,7 +105,7 @@ mod test {
     #[test]
     fn test_reader_rng_fill_bytes() {
         let v = [1u8, 2, 3, 4, 5, 6, 7, 8];
-        let mut w = [0u8, .. 8];
+        let mut w = [0u8; 8];
 
         let mut rng = ReaderRng::new(MemReader::new(v.as_slice().to_vec()));
         rng.fill_bytes(&mut w);
@@ -117,7 +117,7 @@ mod test {
     #[should_fail]
     fn test_reader_rng_insufficient_bytes() {
         let mut rng = ReaderRng::new(MemReader::new(vec!()));
-        let mut v = [0u8, .. 3];
+        let mut v = [0u8; 3];
         rng.fill_bytes(&mut v);
     }
 }
diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs
index 1fedf9652a0..4734a39c835 100644
--- a/src/libstd/rt/args.rs
+++ b/src/libstd/rt/args.rs
@@ -95,14 +95,14 @@ mod imp {
     }
 
     unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
-        Vec::from_fn(argc as uint, |i| {
+        range(0, argc as uint).map(|i| {
             let arg = *argv.offset(i as int);
             let mut len = 0u;
             while *arg.offset(len as int) != 0 {
                 len += 1u;
             }
             slice::from_raw_buf(&arg, len).to_vec()
-        })
+        }).collect()
     }
 
     #[cfg(test)]
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index d4101bb2152..4abef6ee910 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -60,19 +60,19 @@ mod test {
         t!("_ZN4$UP$E", "Box");
         t!("_ZN8$UP$testE", "Boxtest");
         t!("_ZN8$UP$test4foobE", "Boxtest::foob");
-        t!("_ZN8$x20test4foobE", " test::foob");
+        t!("_ZN10$u{20}test4foobE", " test::foob");
     }
 
     #[test]
     fn demangle_many_dollars() {
-        t!("_ZN12test$x20test4foobE", "test test::foob");
+        t!("_ZN14test$u{20}test4foobE", "test test::foob");
         t!("_ZN12test$UP$test4foobE", "testBoxtest::foob");
     }
 
     #[test]
     fn demangle_windows() {
         t!("ZN4testE", "test");
-        t!("ZN12test$x20test4foobE", "test test::foob");
+        t!("ZN14test$u{20}test4foobE", "test test::foob");
         t!("ZN12test$UP$test4foobE", "testBoxtest::foob");
     }
 }
diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs
index 2feea7fa0a4..4dbe878277d 100644
--- a/src/libstd/rt/libunwind.rs
+++ b/src/libstd/rt/libunwind.rs
@@ -82,7 +82,7 @@ pub const unwinder_private_data_size: uint = 2;
 pub struct _Unwind_Exception {
     pub exception_class: _Unwind_Exception_Class,
     pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
-    pub private: [_Unwind_Word, ..unwinder_private_data_size],
+    pub private: [_Unwind_Word; unwinder_private_data_size],
 }
 
 pub enum _Unwind_Context {}
diff --git a/src/libstd/rt/macros.rs b/src/libstd/rt/macros.rs
index 095a27203f9..0f35500a04a 100644
--- a/src/libstd/rt/macros.rs
+++ b/src/libstd/rt/macros.rs
@@ -15,22 +15,12 @@
 
 #![macro_escape]
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 macro_rules! rterrln {
     ($fmt:expr $($arg:tt)*) => ( {
         ::rt::util::dumb_print(format_args!(concat!($fmt, "\n") $($arg)*))
     } )
 }
 
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-macro_rules! rterrln {
-    ($fmt:expr $($arg:tt)*) => ( {
-        format_args!(::rt::util::dumb_print, concat!($fmt, "\n") $($arg)*)
-    } )
-}
-
 // Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build.
 macro_rules! rtdebug {
     ($($arg:tt)*) => ( {
@@ -50,14 +40,6 @@ macro_rules! rtassert {
     } )
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 macro_rules! rtabort {
     ($($arg:tt)*) => (::rt::util::abort(format_args!($($arg)*)))
 }
-
-// NOTE(stage0): Remove macro after a snapshot
-#[cfg(stage0)]
-macro_rules! rtabort {
-    ($($arg:tt)*) => (format_args!(::rt::util::abort, $($arg)*))
-}
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index eb446edbbd8..68aaa1b3ae5 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -49,7 +49,7 @@ pub mod args;
 mod at_exit_imp;
 mod libunwind;
 
-/// The default error code of the rust runtime if the main task panics instead
+/// The default error code of the rust runtime if the main thread panics instead
 /// of exiting cleanly.
 pub const DEFAULT_ERROR_CODE: int = 101;
 
@@ -138,9 +138,9 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
 ///
 /// The procedure passed to this function will be executed as part of the
 /// runtime cleanup phase. For normal rust programs, this means that it will run
-/// after all other tasks have exited.
+/// after all other threads have exited.
 ///
-/// The procedure is *not* executed with a local `Task` available to it, so
+/// The procedure is *not* executed with a local `Thread` available to it, so
 /// primitives like logging, I/O, channels, spawning, etc, are *not* available.
 /// This is meant for "bare bones" usage to clean up runtime details, this is
 /// not meant as a general-purpose "let's clean everything up" function.
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index a8d5216e202..48cdfc20a35 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -36,7 +36,7 @@ use sys_common::stack;
 use rt::unwind;
 use rt::unwind::Unwinder;
 
-/// State associated with Rust tasks.
+/// State associated with Rust threads
 ///
 /// This structure is currently undergoing major changes, and is
 /// likely to be move/be merged with a `Thread` structure.
@@ -50,14 +50,14 @@ pub struct Task {
     awoken: bool,            // used to prevent spurious wakeups
 
     // This field holds the known bounds of the stack in (lo, hi) form. Not all
-    // native tasks necessarily know their precise bounds, hence this is
+    // native threads necessarily know their precise bounds, hence this is
     // optional.
     stack_bounds: (uint, uint),
 
     stack_guard: uint
 }
 
-// Once a task has entered the `Armed` state it must be destroyed via `drop`,
+// Once a thread has entered the `Armed` state it must be destroyed via `drop`,
 // and no other method. This state is used to track this transition.
 #[deriving(PartialEq)]
 enum TaskState {
@@ -67,31 +67,31 @@ enum TaskState {
 }
 
 pub struct TaskOpts {
-    /// Invoke this procedure with the result of the task when it finishes.
+    /// Invoke this procedure with the result of the thread when it finishes.
     pub on_exit: Option<Thunk<Result>>,
-    /// A name for the task-to-be, for identification in panic messages
+    /// A name for the thread-to-be, for identification in panic messages
     pub name: Option<SendStr>,
-    /// The size of the stack for the spawned task
+    /// The size of the stack for the spawned thread
     pub stack_size: Option<uint>,
 }
 
-/// Indicates the manner in which a task exited.
+/// Indicates the manner in which a thread exited.
 ///
-/// A task that completes without panicking is considered to exit successfully.
+/// A thread that completes without panicking is considered to exit successfully.
 ///
 /// If you wish for this result's delivery to block until all
-/// children tasks complete, recommend using a result future.
+/// children threads complete, recommend using a result future.
 pub type Result = ::core::result::Result<(), Box<Any + Send>>;
 
-/// A handle to a blocked task. Usually this means having the Box<Task>
-/// pointer by ownership, but if the task is killable, a killer can steal it
+/// A handle to a blocked thread. Usually this means having the Box<Task>
+/// pointer by ownership, but if the thread is killable, a killer can steal it
 /// at any time.
 pub enum BlockedTask {
     Owned(Box<Task>),
     Shared(Arc<AtomicUint>),
 }
 
-/// Per-task state related to task death, killing, panic, etc.
+/// Per-thread state related to thread death, killing, panic, etc.
 pub struct Death {
     pub on_exit: Option<Thunk<Result>>,
 }
@@ -101,7 +101,7 @@ pub struct BlockedTasks {
 }
 
 impl Task {
-    /// Creates a new uninitialized task.
+    /// Creates a new uninitialized thread.
     pub fn new(stack_bounds: Option<(uint, uint)>, stack_guard: Option<uint>) -> Task {
         Task {
             unwinder: Unwinder::new(),
@@ -153,17 +153,17 @@ impl Task {
         })
     }
 
-    /// Consumes ownership of a task, runs some code, and returns the task back.
+    /// Consumes ownership of a thread, runs some code, and returns the thread back.
     ///
     /// This function can be used as an emulated "try/catch" to interoperate
     /// with the rust runtime at the outermost boundary. It is not possible to
     /// use this function in a nested fashion (a try/catch inside of another
     /// try/catch). Invoking this function is quite cheap.
     ///
-    /// If the closure `f` succeeds, then the returned task can be used again
+    /// If the closure `f` succeeds, then the returned thread can be used again
     /// for another invocation of `run`. If the closure `f` panics then `self`
     /// will be internally destroyed along with all of the other associated
-    /// resources of this task. The `on_exit` callback is invoked with the
+    /// resources of this thread. The `on_exit` callback is invoked with the
     /// cause of panic (not returned here). This can be discovered by querying
     /// `is_destroyed()`.
     ///
@@ -172,30 +172,30 @@ impl Task {
     /// guaranteed to return if it panicks. Care should be taken to ensure that
     /// stack references made by `f` are handled appropriately.
     ///
-    /// It is invalid to call this function with a task that has been previously
+    /// It is invalid to call this function with a thread that has been previously
     /// destroyed via a failed call to `run`.
-    pub fn run(mut self: Box<Task>, f: ||) -> Box<Task> {
-        assert!(!self.is_destroyed(), "cannot re-use a destroyed task");
+    pub fn run<F>(mut self: Box<Task>, f: F) -> Box<Task> where F: FnOnce() {
+        assert!(!self.is_destroyed(), "cannot re-use a destroyed thread");
 
         // First, make sure that no one else is in TLS. This does not allow
         // recursive invocations of run(). If there's no one else, then
         // relinquish ownership of ourselves back into TLS.
         if Local::exists(None::<Task>) {
-            panic!("cannot run a task recursively inside another");
+            panic!("cannot run a thread recursively inside another");
         }
         self.state = Armed;
         Local::put(self);
 
         // There are two primary reasons that general try/catch is unsafe. The
         // first is that we do not support nested try/catch. The above check for
-        // an existing task in TLS is sufficient for this invariant to be
+        // an existing thread in TLS is sufficient for this invariant to be
         // upheld. The second is that unwinding while unwinding is not defined.
-        // We take care of that by having an 'unwinding' flag in the task
+        // We take care of that by having an 'unwinding' flag in the thread
         // itself. For these reasons, this unsafety should be ok.
         let result = unsafe { unwind::try(f) };
 
-        // After running the closure given return the task back out if it ran
-        // successfully, or clean up the task if it panicked.
+        // After running the closure given return the thread back out if it ran
+        // successfully, or clean up the thread if it panicked.
         let task: Box<Task> = Local::take();
         match result {
             Ok(()) => task,
@@ -203,13 +203,13 @@ impl Task {
         }
     }
 
-    /// Destroy all associated resources of this task.
+    /// Destroy all associated resources of this thread.
     ///
-    /// This function will perform any necessary clean up to prepare the task
+    /// This function will perform any necessary clean up to prepare the thread
     /// for destruction. It is required that this is called before a `Task`
     /// falls out of scope.
     ///
-    /// The returned task cannot be used for running any more code, but it may
+    /// The returned thread cannot be used for running any more code, but it may
     /// be used to extract the runtime as necessary.
     pub fn destroy(self: Box<Task>) -> Box<Task> {
         if self.is_destroyed() {
@@ -219,14 +219,14 @@ impl Task {
         }
     }
 
-    /// Cleans up a task, processing the result of the task as appropriate.
+    /// Cleans up a thread, processing the result of the thread as appropriate.
     ///
-    /// This function consumes ownership of the task, deallocating it once it's
+    /// This function consumes ownership of the thread, deallocating it once it's
     /// done being processed. It is assumed that TLD and the local heap have
     /// already been destroyed and/or annihilated.
     fn cleanup(mut self: Box<Task>, result: Result) -> Box<Task> {
         // After taking care of the data above, we need to transmit the result
-        // of this task.
+        // of this thread.
         let what_to_do = self.death.on_exit.take();
         Local::put(self);
 
@@ -235,15 +235,15 @@ impl Task {
         //        if this panics, this will also likely abort the runtime.
         //
         //        This closure is currently limited to a channel send via the
-        //        standard library's task interface, but this needs
+        //        standard library's thread interface, but this needs
         //        reconsideration to whether it's a reasonable thing to let a
-        //        task to do or not.
+        //        thread to do or not.
         match what_to_do {
             Some(f) => { f.invoke(result) }
             None => { drop(result) }
         }
 
-        // Now that we're done, we remove the task from TLS and flag it for
+        // Now that we're done, we remove the thread from TLS and flag it for
         // destruction.
         let mut task: Box<Task> = Local::take();
         task.state = Destroyed;
@@ -253,7 +253,7 @@ impl Task {
     /// Queries whether this can be destroyed or not.
     pub fn is_destroyed(&self) -> bool { self.state == Destroyed }
 
-    /// Deschedules the current task, invoking `f` `amt` times. It is not
+    /// Deschedules the current thread, invoking `f` `amt` times. It is not
     /// recommended to use this function directly, but rather communication
     /// primitives in `std::comm` should be used.
     //
@@ -262,31 +262,31 @@ impl Task {
     // shared state. Additionally, all of the violations are protected with a
     // mutex, so in theory there are no races.
     //
-    // The first thing we need to do is to get a pointer to the task's internal
-    // mutex. This address will not be changing (because the task is allocated
-    // on the heap). We must have this handle separately because the task will
+    // The first thing we need to do is to get a pointer to the thread's internal
+    // mutex. This address will not be changing (because the thread is allocated
+    // on the heap). We must have this handle separately because the thread will
     // have its ownership transferred to the given closure. We're guaranteed,
     // however, that this memory will remain valid because *this* is the current
-    // task's execution thread.
+    // thread's execution thread.
     //
-    // The next weird part is where ownership of the task actually goes. We
+    // The next weird part is where ownership of the thread actually goes. We
     // relinquish it to the `f` blocking function, but upon returning this
-    // function needs to replace the task back in TLS. There is no communication
-    // from the wakeup thread back to this thread about the task pointer, and
-    // there's really no need to. In order to get around this, we cast the task
+    // function needs to replace the thread back in TLS. There is no communication
+    // from the wakeup thread back to this thread about the thread pointer, and
+    // there's really no need to. In order to get around this, we cast the thread
     // to a `uint` which is then used at the end of this function to cast back
     // to a `Box<Task>` object. Naturally, this looks like it violates
     // ownership semantics in that there may be two `Box<Task>` objects.
     //
     // The fun part is that the wakeup half of this implementation knows to
-    // "forget" the task on the other end. This means that the awakening half of
+    // "forget" the thread on the other end. This means that the awakening half of
     // things silently relinquishes ownership back to this thread, but not in a
-    // way that the compiler can understand. The task's memory is always valid
-    // for both tasks because these operations are all done inside of a mutex.
+    // way that the compiler can understand. The thread's memory is always valid
+    // for both threads because these operations are all done inside of a mutex.
     //
     // You'll also find that if blocking fails (the `f` function hands the
     // BlockedTask back to us), we will `mem::forget` the handles. The
-    // reasoning for this is the same logic as above in that the task silently
+    // reasoning for this is the same logic as above in that the thread silently
     // transfers ownership via the `uint`, not through normal compiler
     // semantics.
     //
@@ -319,11 +319,11 @@ impl Task {
                 let guard = (*me).lock.lock();
                 (*me).awoken = false;
 
-                // Apply the given closure to all of the "selectable tasks",
+                // Apply the given closure to all of the "selectable threads",
                 // bailing on the first one that produces an error. Note that
                 // care must be taken such that when an error is occurred, we
-                // may not own the task, so we may still have to wait for the
-                // task to become available. In other words, if task.wake()
+                // may not own the thread, so we may still have to wait for the
+                // thread to become available. In other words, if thread.wake()
                 // returns `None`, then someone else has ownership and we must
                 // wait for their signal.
                 match iter.map(f).filter_map(|a| a.err()).next() {
@@ -342,15 +342,15 @@ impl Task {
                     guard.wait();
                 }
             }
-            // put the task back in TLS, and everything is as it once was.
+            // put the thread back in TLS, and everything is as it once was.
             Local::put(mem::transmute(me));
         }
     }
 
-    /// Wakes up a previously blocked task. This function can only be
-    /// called on tasks that were previously blocked in `deschedule`.
+    /// Wakes up a previously blocked thread. This function can only be
+    /// called on threads that were previously blocked in `deschedule`.
     //
-    // See the comments on `deschedule` for why the task is forgotten here, and
+    // See the comments on `deschedule` for why the thread is forgotten here, and
     // why it's valid to do so.
     pub fn reawaken(mut self: Box<Task>) {
         unsafe {
@@ -362,21 +362,21 @@ impl Task {
         }
     }
 
-    /// Yields control of this task to another task. This function will
+    /// Yields control of this thread to another thread. This function will
     /// eventually return, but possibly not immediately. This is used as an
-    /// opportunity to allow other tasks a chance to run.
+    /// opportunity to allow other threads a chance to run.
     pub fn yield_now() {
         Thread::yield_now();
     }
 
-    /// Returns the stack bounds for this task in (lo, hi) format. The stack
-    /// bounds may not be known for all tasks, so the return value may be
+    /// Returns the stack bounds for this thread in (lo, hi) format. The stack
+    /// bounds may not be known for all threads, so the return value may be
     /// `None`.
     pub fn stack_bounds(&self) -> (uint, uint) {
         self.stack_bounds
     }
 
-    /// Returns the stack guard for this task, if known.
+    /// Returns the stack guard for this thread, if known.
     pub fn stack_guard(&self) -> Option<uint> {
         if self.stack_guard != 0 {
             Some(self.stack_guard)
@@ -385,9 +385,9 @@ impl Task {
         }
     }
 
-    /// Consume this task, flagging it as a candidate for destruction.
+    /// Consume this thread, flagging it as a candidate for destruction.
     ///
-    /// This function is required to be invoked to destroy a task. A task
+    /// This function is required to be invoked to destroy a thread. A thread
     /// destroyed through a normal drop will abort.
     pub fn drop(mut self) {
         self.state = Destroyed;
@@ -396,7 +396,7 @@ impl Task {
 
 impl Drop for Task {
     fn drop(&mut self) {
-        rtdebug!("called drop for a task: {}", self as *mut Task as uint);
+        rtdebug!("called drop for a thread: {}", self as *mut Task as uint);
         rtassert!(self.state != Armed);
     }
 }
@@ -414,7 +414,7 @@ impl Iterator<BlockedTask> for BlockedTasks {
 }
 
 impl BlockedTask {
-    /// Returns Some if the task was successfully woken; None if already killed.
+    /// Returns Some if the thread was successfully woken; None if already killed.
     pub fn wake(self) -> Option<Box<Task>> {
         match self {
             Owned(task) => Some(task),
@@ -427,7 +427,7 @@ impl BlockedTask {
         }
     }
 
-    /// Reawakens this task if ownership is acquired. If finer-grained control
+    /// Reawakens this thread if ownership is acquired. If finer-grained control
     /// is desired, use `wake` instead.
     pub fn reawaken(self) {
         self.wake().map(|t| t.reawaken());
@@ -438,12 +438,12 @@ impl BlockedTask {
     #[cfg(not(test))] pub fn trash(self) { }
     #[cfg(test)]      pub fn trash(self) { assert!(self.wake().is_none()); }
 
-    /// Create a blocked task, unless the task was already killed.
+    /// Create a blocked thread, unless the thread was already killed.
     pub fn block(task: Box<Task>) -> BlockedTask {
         Owned(task)
     }
 
-    /// Converts one blocked task handle to a list of many handles to the same.
+    /// Converts one blocked thread handle to a list of many handles to the same.
     pub fn make_selectable(self, num_handles: uint) -> Take<BlockedTasks> {
         let arc = match self {
             Owned(task) => {
@@ -543,7 +543,7 @@ mod test {
         drop(Task::new(None, None));
     }
 
-    // Task blocking tests
+    // Thread blocking tests
 
     #[test]
     fn block_and_wake() {
diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs
index 8c35eb58284..dcd967a774c 100644
--- a/src/libstd/rt/unwind.rs
+++ b/src/libstd/rt/unwind.rs
@@ -79,11 +79,11 @@ struct Exception {
 
 pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint);
 
-// Variables used for invoking callbacks when a task starts to unwind.
+// Variables used for invoking callbacks when a thread starts to unwind.
 //
 // For more information, see below.
 const MAX_CALLBACKS: uint = 16;
-static CALLBACKS: [atomic::AtomicUint, ..MAX_CALLBACKS] =
+static CALLBACKS: [atomic::AtomicUint; MAX_CALLBACKS] =
         [atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
          atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
          atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT,
@@ -106,14 +106,14 @@ thread_local! { static PANICKING: Cell<bool> = Cell::new(false) }
 ///
 /// * This is not safe to call in a nested fashion. The unwinding
 ///   interface for Rust is designed to have at most one try/catch block per
-///   task, not multiple. No runtime checking is currently performed to uphold
+///   thread, not multiple. No runtime checking is currently performed to uphold
 ///   this invariant, so this function is not safe. A nested try/catch block
 ///   may result in corruption of the outer try/catch block's state, especially
-///   if this is used within a task itself.
+///   if this is used within a thread itself.
 ///
-/// * It is not sound to trigger unwinding while already unwinding. Rust tasks
+/// * It is not sound to trigger unwinding while already unwinding. Rust threads
 ///   have runtime checks in place to ensure this invariant, but it is not
-///   guaranteed that a rust task is in place when invoking this function.
+///   guaranteed that a rust thread is in place when invoking this function.
 ///   Unwinding twice can lead to resource leaks where some destructors are not
 ///   run.
 pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
@@ -168,7 +168,7 @@ fn rust_panic(cause: Box<Any + Send>) -> ! {
             uwe: uw::_Unwind_Exception {
                 exception_class: rust_exception_class(),
                 exception_cleanup: exception_cleanup,
-                private: [0, ..uw::unwinder_private_data_size],
+                private: [0; uw::unwinder_private_data_size],
             },
             cause: Some(cause),
         };
@@ -203,7 +203,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
 // _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase.
 //
 // This is pretty close to Rust's exception handling approach, except that Rust
-// does have a single "catch-all" handler at the bottom of each task's stack.
+// does have a single "catch-all" handler at the bottom of each thread's stack.
 // So we have two versions of the personality routine:
 // - rust_eh_personality, used by all cleanup landing pads, which never catches,
 //   so the behavior of __gcc_personality_v0 is perfectly adequate there, and
@@ -477,8 +477,6 @@ pub mod eabi {
     }
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 #[cfg(not(test))]
 /// Entry point of panic from the libcore crate.
 #[lang = "panic_fmt"]
@@ -487,18 +485,6 @@ pub extern fn rust_begin_unwind(msg: fmt::Arguments,
     begin_unwind_fmt(msg, &(file, line))
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-#[cfg(not(test))]
-/// Entry point of panic from the libcore crate.
-#[lang = "panic_fmt"]
-pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
-                                file: &'static str, line: uint) -> ! {
-    begin_unwind_fmt(msg, &(file, line))
-}
-
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 /// The entry point for unwinding with a formatted message.
 ///
 /// This is designed to reduce the amount of code required at the call
@@ -530,39 +516,6 @@ pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -
     begin_unwind_inner(msg, file_line)
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-/// The entry point for unwinding with a formatted message.
-///
-/// This is designed to reduce the amount of code required at the call
-/// site as much as possible (so that `panic!()` has as low an impact
-/// on (e.g.) the inlining of other functions as possible), by moving
-/// the actual formatting into this shared place.
-#[inline(never)] #[cold]
-pub fn begin_unwind_fmt(msg: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
-    use fmt::FormatWriter;
-
-    // We do two allocations here, unfortunately. But (a) they're
-    // required with the current scheme, and (b) we don't handle
-    // panic + OOM properly anyway (see comment in begin_unwind
-    // below).
-
-    struct VecWriter<'a> { v: &'a mut Vec<u8> }
-
-    impl<'a> fmt::FormatWriter for VecWriter<'a> {
-        fn write(&mut self, buf: &[u8]) -> fmt::Result {
-            self.v.push_all(buf);
-            Ok(())
-        }
-    }
-
-    let mut v = Vec::new();
-    let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg);
-
-    let msg = box String::from_utf8_lossy(v.as_slice()).into_owned();
-    begin_unwind_inner(msg, file_line)
-}
-
 /// This is the entry point of unwinding for panic!() and assert!().
 #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
 pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> ! {
@@ -570,7 +523,7 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) ->
     // Currently this means that panic!() on OOM will invoke this code path,
     // but then again we're not really ready for panic on OOM anyway. If
     // we do start doing this, then we should propagate this allocation to
-    // be performed in the parent of this task instead of the task that's
+    // be performed in the parent of this thread instead of the thread that's
     // panicking.
 
     // see below for why we do the `Any` coercion here.
@@ -593,7 +546,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
     static INIT: Once = ONCE_INIT;
     INIT.doit(|| unsafe { register(failure::on_fail); });
 
-    // First, invoke call the user-defined callbacks triggered on task panic.
+    // First, invoke call the user-defined callbacks triggered on thread panic.
     //
     // By the time that we see a callback has been registered (by reading
     // MAX_CALLBACKS), the actual callback itself may have not been stored yet,
@@ -621,7 +574,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
         // If a thread panics while it's already unwinding then we
         // have limited options. Currently our preference is to
         // just abort. In the future we may consider resuming
-        // unwinding or otherwise exiting the task cleanly.
+        // unwinding or otherwise exiting the thread cleanly.
         rterrln!("thread panicked while panicking. aborting.");
         unsafe { intrinsics::abort() }
     }
@@ -629,10 +582,10 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
     rust_panic(msg);
 }
 
-/// Register a callback to be invoked when a task unwinds.
+/// Register a callback to be invoked when a thread unwinds.
 ///
 /// This is an unsafe and experimental API which allows for an arbitrary
-/// callback to be invoked when a task panics. This callback is invoked on both
+/// callback to be invoked when a thread panics. This callback is invoked on both
 /// the initial unwinding and a double unwinding if one occurs. Additionally,
 /// the local `Task` will be in place for the duration of the callback, and
 /// the callback must ensure that it remains in place once the callback returns.
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index d6c0e4a5aea..2a8deccb5dc 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -111,25 +111,11 @@ impl fmt::FormatWriter for Stdio {
     }
 }
 
-// NOTE(stage0): Remove cfg after a snapshot
-#[cfg(not(stage0))]
 pub fn dumb_print(args: fmt::Arguments) {
     let _ = Stderr.write_fmt(args);
 }
 
-// NOTE(stage0): Remove function after a snapshot
-#[cfg(stage0)]
-pub fn dumb_print(args: &fmt::Arguments) {
-    let mut w = Stderr;
-    let _ = write!(&mut w, "{}", args);
-}
-
-// NOTE(stage0): Remove wrappers after a snapshot
-#[cfg(not(stage0))] pub fn abort(args: fmt::Arguments) -> ! { abort_(&args) }
-#[cfg(stage0)] pub fn abort(args: &fmt::Arguments) -> ! { abort_(args) }
-
-// NOTE(stage0): Change to `pub fn abort(args: fmt::Arguments) -> !` after a snapshot
-fn abort_(args: &fmt::Arguments) -> ! {
+pub fn abort(args: fmt::Arguments) -> ! {
     use fmt::FormatWriter;
 
     struct BufWriter<'a> {
@@ -138,7 +124,7 @@ fn abort_(args: &fmt::Arguments) -> ! {
     }
     impl<'a> FormatWriter for BufWriter<'a> {
         fn write(&mut self, bytes: &[u8]) -> fmt::Result {
-            let left = self.buf[mut self.pos..];
+            let left = self.buf.slice_from_mut(self.pos);
             let to_write = bytes[..cmp::min(bytes.len(), left.len())];
             slice::bytes::copy_memory(left, to_write);
             self.pos += to_write.len();
@@ -147,7 +133,7 @@ fn abort_(args: &fmt::Arguments) -> ! {
     }
 
     // Convert the arguments into a stack-allocated string
-    let mut msg = [0u8, ..512];
+    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[mut ..w.pos]).unwrap_or("aborted");
diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs
index 5d45836af80..a88932f21cb 100644
--- a/src/libstd/sync/atomic.rs
+++ b/src/libstd/sync/atomic.rs
@@ -101,9 +101,9 @@ use core::mem;
 use core::prelude::{Send, Drop, None, Option, Some};
 
 pub use core::atomic::{AtomicBool, AtomicInt, AtomicUint, AtomicPtr};
-pub use core::atomic::{Ordering, Relaxed, Release, Acquire, AcqRel, SeqCst};
 pub use core::atomic::{INIT_ATOMIC_BOOL, INIT_ATOMIC_INT, INIT_ATOMIC_UINT};
 pub use core::atomic::fence;
+pub use core::atomic::Ordering::{mod, Relaxed, Release, Acquire, AcqRel, SeqCst};
 
 /// An atomic, nullable unique pointer
 ///
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index 55d50af3b83..50e4f848d82 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -69,7 +69,7 @@ impl Barrier {
     /// Barriers are re-usable after all threads have rendezvoused once, and can
     /// be used continuously.
     pub fn wait(&self) {
-        let mut lock = self.lock.lock();
+        let mut lock = self.lock.lock().unwrap();
         let local_gen = lock.generation_id;
         lock.count += 1;
         if lock.count < self.num_threads {
@@ -77,7 +77,7 @@ impl Barrier {
             // http://en.wikipedia.org/wiki/Spurious_wakeup
             while local_gen == lock.generation_id &&
                   lock.count < self.num_threads {
-                self.cvar.wait(&lock);
+                lock = self.cvar.wait(lock).unwrap();
             }
         } else {
             lock.count = 0;
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 28960c1574e..d71cdeb25fd 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -11,10 +11,11 @@
 use prelude::v1::*;
 
 use sync::atomic::{mod, AtomicUint};
-use sync::{mutex, StaticMutexGuard};
+use sync::poison::{mod, LockResult};
 use sys_common::condvar as sys;
 use sys_common::mutex as sys_mutex;
 use time::Duration;
+use sync::{mutex, MutexGuard};
 
 /// A Condition Variable
 ///
@@ -44,18 +45,19 @@ use time::Duration;
 /// // Inside of our lock, spawn a new thread, and then wait for it to start
 /// Thread::spawn(move|| {
 ///     let &(ref lock, ref cvar) = &*pair2;
-///     let mut started = lock.lock();
+///     let mut started = lock.lock().unwrap();
 ///     *started = true;
 ///     cvar.notify_one();
 /// }).detach();
 ///
 /// // wait for the thread to start up
 /// let &(ref lock, ref cvar) = &*pair;
-/// let started = lock.lock();
+/// let mut started = lock.lock().unwrap();
 /// while !*started {
-///     cvar.wait(&started);
+///     started = cvar.wait(started).unwrap();
 /// }
 /// ```
+#[stable]
 pub struct Condvar { inner: Box<StaticCondvar> }
 
 unsafe impl Send for Condvar {}
@@ -73,6 +75,7 @@ unsafe impl Sync for Condvar {}
 ///
 /// static CVAR: StaticCondvar = CONDVAR_INIT;
 /// ```
+#[unstable = "may be merged with Condvar in the future"]
 pub struct StaticCondvar {
     inner: sys::Condvar,
     mutex: AtomicUint,
@@ -82,24 +85,16 @@ unsafe impl Send for StaticCondvar {}
 unsafe impl Sync for StaticCondvar {}
 
 /// Constant initializer for a statically allocated condition variable.
+#[unstable = "may be merged with Condvar in the future"]
 pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
     inner: sys::CONDVAR_INIT,
     mutex: atomic::INIT_ATOMIC_UINT,
 };
 
-/// A trait for vaules which can be passed to the waiting methods of condition
-/// variables. This is implemented by the mutex guards in this module.
-///
-/// Note that this trait should likely not be implemented manually unless you
-/// really know what you're doing.
-pub trait AsMutexGuard {
-    #[allow(missing_docs)]
-    unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard;
-}
-
 impl Condvar {
     /// Creates a new condition variable which is ready to be waited on and
     /// notified.
+    #[stable]
     pub fn new() -> Condvar {
         Condvar {
             inner: box StaticCondvar {
@@ -113,8 +108,8 @@ impl Condvar {
     /// notification.
     ///
     /// This function will atomically unlock the mutex specified (represented by
-    /// `guard`) and block the current thread. This means that any calls to
-    /// `notify_*()` which happen logically after the mutex is unlocked are
+    /// `mutex_guard`) and block the current thread. This means that any calls
+    /// to `notify_*()` which happen logically after the mutex is unlocked are
     /// candidates to wake this thread up. When this function call returns, the
     /// lock specified will have been re-acquired.
     ///
@@ -123,16 +118,24 @@ impl Condvar {
     /// the predicate must always be checked each time this function returns to
     /// protect against spurious wakeups.
     ///
+    /// # Failure
+    ///
+    /// This function will return an error if the mutex being waited on is
+    /// poisoned when this thread re-acquires the lock. For more information,
+    /// see information about poisoning on the Mutex type.
+    ///
     /// # Panics
     ///
     /// This function will `panic!()` if it is used with more than one mutex
     /// over time. Each condition variable is dynamically bound to exactly one
     /// mutex to ensure defined behavior across platforms. If this functionality
     /// is not desired, then unsafe primitives in `sys` are provided.
-    pub fn wait<T: AsMutexGuard>(&self, mutex_guard: &T) {
+    #[stable]
+    pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
+                       -> LockResult<MutexGuard<'a, T>> {
         unsafe {
             let me: &'static Condvar = &*(self as *const _);
-            me.inner.wait(mutex_guard)
+            me.inner.wait(guard)
         }
     }
 
@@ -156,11 +159,11 @@ impl Condvar {
     // provide. There are also additional concerns about the unix-specific
     // implementation which may need to be addressed.
     #[allow(dead_code)]
-    fn wait_timeout<T: AsMutexGuard>(&self, mutex_guard: &T,
-                                     dur: Duration) -> bool {
+    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 _);
-            me.inner.wait_timeout(mutex_guard, dur)
+            me.inner.wait_timeout(guard, dur)
         }
     }
 
@@ -171,6 +174,7 @@ impl Condvar {
     /// `notify_one` are not buffered in any way.
     ///
     /// To wake up all threads, see `notify_one()`.
+    #[stable]
     pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } }
 
     /// Wake up all blocked threads on this condvar.
@@ -180,6 +184,7 @@ impl Condvar {
     /// way.
     ///
     /// To wake up only one thread, see `notify_one()`.
+    #[stable]
     pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } }
 }
 
@@ -194,13 +199,19 @@ impl StaticCondvar {
     /// notification.
     ///
     /// See `Condvar::wait`.
-    pub fn wait<T: AsMutexGuard>(&'static self, mutex_guard: &T) {
-        unsafe {
-            let lock = mutex_guard.as_mutex_guard();
-            let sys = mutex::guard_lock(lock);
-            self.verify(sys);
-            self.inner.wait(sys);
-            (*mutex::guard_poison(lock)).check("mutex");
+    #[unstable = "may be merged with Condvar in the future"]
+    pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>)
+                       -> LockResult<MutexGuard<'a, T>> {
+        let poisoned = unsafe {
+            let lock = mutex::guard_lock(&guard);
+            self.verify(lock);
+            self.inner.wait(lock);
+            mutex::guard_poison(&guard).get()
+        };
+        if poisoned {
+            Err(poison::new_poison_error(guard))
+        } else {
+            Ok(guard)
         }
     }
 
@@ -209,26 +220,31 @@ impl StaticCondvar {
     ///
     /// See `Condvar::wait_timeout`.
     #[allow(dead_code)] // may want to stabilize this later, see wait_timeout above
-    fn wait_timeout<T: AsMutexGuard>(&'static self, mutex_guard: &T,
-                                     dur: Duration) -> bool {
-        unsafe {
-            let lock = mutex_guard.as_mutex_guard();
-            let sys = mutex::guard_lock(lock);
-            self.verify(sys);
-            let ret = self.inner.wait_timeout(sys, dur);
-            (*mutex::guard_poison(lock)).check("mutex");
-            return ret;
+    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);
+            let success = self.inner.wait_timeout(lock, dur);
+            (mutex::guard_poison(&guard).get(), success)
+        };
+        if poisoned {
+            Err(poison::new_poison_error((guard, success)))
+        } else {
+            Ok((guard, success))
         }
     }
 
     /// Wake up one blocked thread on this condvar.
     ///
     /// See `Condvar::notify_one`.
+    #[unstable = "may be merged with Condvar in the future"]
     pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } }
 
     /// Wake up all blocked threads on this condvar.
     ///
     /// See `Condvar::notify_all`.
+    #[unstable = "may be merged with Condvar in the future"]
     pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } }
 
     /// Deallocate all resources associated with this static condvar.
@@ -237,6 +253,7 @@ impl StaticCondvar {
     /// active users of the condvar, and this also doesn't prevent any future
     /// users of the condvar. This method is required to be called to not leak
     /// memory on all platforms.
+    #[unstable = "may be merged with Condvar in the future"]
     pub unsafe fn destroy(&'static self) {
         self.inner.destroy()
     }
@@ -290,12 +307,12 @@ mod tests {
         static C: StaticCondvar = CONDVAR_INIT;
         static M: StaticMutex = MUTEX_INIT;
 
-        let g = M.lock();
+        let mut g = M.lock().unwrap();
         let _t = Thread::spawn(move|| {
-            let _g = M.lock();
+            let _g = M.lock().unwrap();
             C.notify_one();
         });
-        C.wait(&g);
+        let g = C.wait(g).unwrap();
         drop(g);
         unsafe { C.destroy(); M.destroy(); }
     }
@@ -311,13 +328,13 @@ mod tests {
             let tx = tx.clone();
             Thread::spawn(move|| {
                 let &(ref lock, ref cond) = &*data;
-                let mut cnt = lock.lock();
+                let mut cnt = lock.lock().unwrap();
                 *cnt += 1;
                 if *cnt == N {
                     tx.send(()).unwrap();
                 }
                 while *cnt != 0 {
-                    cond.wait(&cnt);
+                    cnt = cond.wait(cnt).unwrap();
                 }
                 tx.send(()).unwrap();
             }).detach();
@@ -326,7 +343,7 @@ mod tests {
 
         let &(ref lock, ref cond) = &*data;
         rx.recv().unwrap();
-        let mut cnt = lock.lock();
+        let mut cnt = lock.lock().unwrap();
         *cnt = 0;
         cond.notify_all();
         drop(cnt);
@@ -341,13 +358,15 @@ mod tests {
         static C: StaticCondvar = CONDVAR_INIT;
         static M: StaticMutex = MUTEX_INIT;
 
-        let g = M.lock();
-        assert!(!C.wait_timeout(&g, Duration::nanoseconds(1000)));
-        let _t = Thread::spawn(move|| {
-            let _g = M.lock();
+        let g = M.lock().unwrap();
+        let (g, success) = C.wait_timeout(g, Duration::nanoseconds(1000)).unwrap();
+        assert!(!success);
+        let _t = Thread::spawn(move || {
+            let _g = M.lock().unwrap();
             C.notify_one();
         });
-        assert!(C.wait_timeout(&g, Duration::days(1)));
+        let (g, success) = C.wait_timeout(g, Duration::days(1)).unwrap();
+        assert!(success);
         drop(g);
         unsafe { C.destroy(); M.destroy(); }
     }
@@ -359,15 +378,14 @@ mod tests {
         static M2: StaticMutex = MUTEX_INIT;
         static C: StaticCondvar = CONDVAR_INIT;
 
-        let g = M1.lock();
+        let mut g = M1.lock().unwrap();
         let _t = Thread::spawn(move|| {
-            let _g = M1.lock();
+            let _g = M1.lock().unwrap();
             C.notify_one();
         });
-        C.wait(&g);
+        g = C.wait(g).unwrap();
         drop(g);
 
-        C.wait(&M2.lock());
-
+        C.wait(M2.lock().unwrap()).unwrap();
     }
 }
diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs
index 2b7311e4e98..1f8e5d7ee37 100644
--- a/src/libstd/sync/mod.rs
+++ b/src/libstd/sync/mod.rs
@@ -19,14 +19,15 @@
 
 pub use alloc::arc::{Arc, Weak};
 
-pub use self::mutex::{Mutex, MutexGuard, StaticMutex, StaticMutexGuard, MUTEX_INIT};
+pub use self::mutex::{Mutex, MutexGuard, StaticMutex};
+pub use self::mutex::MUTEX_INIT;
 pub use self::rwlock::{RWLock, StaticRWLock, RWLOCK_INIT};
 pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard};
-pub use self::rwlock::{StaticRWLockReadGuard, StaticRWLockWriteGuard};
-pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT, AsMutexGuard};
+pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT};
 pub use self::once::{Once, ONCE_INIT};
 pub use self::semaphore::{Semaphore, SemaphoreGuard};
 pub use self::barrier::Barrier;
+pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
 
 pub use self::future::Future;
 pub use self::task_pool::TaskPool;
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index e2294906229..413675f26d5 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -182,7 +182,7 @@
 // senders. Under the hood, however, there are actually three flavors of
 // channels in play.
 //
-// * Oneshots - these channels are highly optimized for the one-send use case.
+// * Flavor::Oneshots - these channels are highly optimized for the one-send use case.
 //              They contain as few atomics as possible and involve one and
 //              exactly one allocation.
 // * Streams - these channels are optimized for the non-shared use case. They
diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs
index e1606cb4317..e15c38cf9a1 100644
--- a/src/libstd/sync/mpsc/shared.rs
+++ b/src/libstd/sync/mpsc/shared.rs
@@ -86,7 +86,7 @@ impl<T: Send> Packet<T> {
     // and that could cause problems on platforms where it is
     // represented by opaque data structure
     pub fn postinit_lock(&self) -> MutexGuard<()> {
-        self.select_lock.lock()
+        self.select_lock.lock().unwrap()
     }
 
     // This function is used at the creation of a shared packet to inherit a
@@ -435,7 +435,7 @@ impl<T: Send> Packet<T> {
         // about looking at and dealing with to_wake. Once we have acquired the
         // lock, we are guaranteed that inherit_blocker is done.
         {
-            let _guard = self.select_lock.lock();
+            let _guard = self.select_lock.lock().unwrap();
         }
 
         // Like the stream implementation, we want to make sure that the count
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 28005831d4f..98f1c4c46f9 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -121,9 +121,9 @@ fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
         NoneBlocked => {}
         _ => unreachable!(),
     }
-    drop(guard);        // unlock
-    wait_token.wait();  // block
-    lock.lock()         // relock
+    drop(guard);         // unlock
+    wait_token.wait();   // block
+    lock.lock().unwrap() // relock
 }
 
 /// Wakes up a thread, dropping the lock at the correct time
@@ -148,7 +148,7 @@ impl<T: Send> Packet<T> {
                     tail: 0 as *mut Node,
                 },
                 buf: Buffer {
-                    buf: Vec::from_fn(cap + if cap == 0 {1} else {0}, |_| None),
+                    buf: range(0, cap + if cap == 0 {1} else {0}).map(|_| None).collect(),
                     start: 0,
                     size: 0,
                 },
@@ -161,7 +161,7 @@ impl<T: Send> Packet<T> {
     fn acquire_send_slot(&self) -> MutexGuard<State<T>> {
         let mut node = Node { token: None, next: 0 as *mut Node };
         loop {
-            let mut guard = self.lock.lock();
+            let mut guard = self.lock.lock().unwrap();
             // are we ready to go?
             if guard.disconnected || guard.buf.size() < guard.buf.cap() {
                 return guard;
@@ -202,7 +202,7 @@ impl<T: Send> Packet<T> {
     }
 
     pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
         if guard.disconnected {
             Err(super::TrySendError::Disconnected(t))
         } else if guard.buf.size() == guard.buf.cap() {
@@ -239,7 +239,7 @@ impl<T: Send> Packet<T> {
     // When reading this, remember that there can only ever be one receiver at
     // time.
     pub fn recv(&self) -> Result<T, ()> {
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
 
         // Wait for the buffer to have something in it. No need for a while loop
         // because we're the only receiver.
@@ -258,7 +258,7 @@ impl<T: Send> Packet<T> {
     }
 
     pub fn try_recv(&self) -> Result<T, Failure> {
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
 
         // Easy cases first
         if guard.disconnected { return Err(Disconnected) }
@@ -315,7 +315,7 @@ impl<T: Send> Packet<T> {
         }
 
         // Not much to do other than wake up a receiver if one's there
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
         if guard.disconnected { return }
         guard.disconnected = true;
         match mem::replace(&mut guard.blocker, NoneBlocked) {
@@ -326,7 +326,7 @@ impl<T: Send> Packet<T> {
     }
 
     pub fn drop_port(&self) {
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
 
         if guard.disconnected { return }
         guard.disconnected = true;
@@ -372,14 +372,14 @@ impl<T: Send> Packet<T> {
     // If Ok, the value is whether this port has data, if Err, then the upgraded
     // port needs to be checked instead of this one.
     pub fn can_recv(&self) -> bool {
-        let guard = self.lock.lock();
+        let guard = self.lock.lock().unwrap();
         guard.disconnected || guard.buf.size() > 0
     }
 
     // Attempts to start selection on this port. This can either succeed or fail
     // because there is data waiting.
     pub fn start_selection(&self, token: SignalToken) -> StartResult {
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
         if guard.disconnected || guard.buf.size() > 0 {
             Abort
         } else {
@@ -397,7 +397,7 @@ impl<T: Send> Packet<T> {
     //
     // The return value indicates whether there's data on this port.
     pub fn abort_selection(&self) -> bool {
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
         match mem::replace(&mut guard.blocker, NoneBlocked) {
             NoneBlocked => true,
             BlockedSender(token) => {
@@ -413,7 +413,7 @@ impl<T: Send> Packet<T> {
 impl<T: Send> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.channels.load(atomic::SeqCst), 0);
-        let mut guard = self.lock.lock();
+        let mut guard = self.lock.lock().unwrap();
         assert!(guard.queue.dequeue().is_none());
         assert!(guard.canceled.is_none());
     }
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 1562031499f..3f155b02065 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -13,7 +13,7 @@ use prelude::v1::*;
 use cell::UnsafeCell;
 use kinds::marker;
 use ops::{Deref, DerefMut};
-use sync::{poison, AsMutexGuard};
+use sync::poison::{mod, TryLockError, TryLockResult, LockResult};
 use sys_common::mutex as sys;
 
 /// A mutual exclusion primitive useful for protecting shared data
@@ -27,12 +27,23 @@ use sys_common::mutex as sys;
 ///
 /// # Poisoning
 ///
-/// In order to prevent access to otherwise invalid data, each mutex will
-/// propagate any panics which occur while the lock is held. Once a thread has
-/// panicked while holding the lock, then all other threads will immediately
-/// panic as well once they hold the lock.
+/// The mutexes in this module implement a strategy called "poisoning" where a
+/// mutex is considered poisoned whenever a thread panics while holding the
+/// lock. Once a mutex is poisoned, all other tasks are unable to access the
+/// data by default as it is likely tainted (some invariant is not being
+/// upheld).
 ///
-/// # Example
+/// For a mutex, this means that the `lock` and `try_lock` methods return a
+/// `Result` which indicates whether a mutex has been poisoned or not. Most
+/// usage of a mutex will simply `unwrap()` these results, propagating panics
+/// among threads to ensure that a possibly invalid invariant is not witnessed.
+///
+/// A poisoned mutex, however, does not prevent all access to the underlying
+/// data. The `PoisonError` type has an `into_guard` method which will return
+/// the guard that would have otherwise been returned on a successful lock. This
+/// allows access to the data, despite the lock being poisoned.
+///
+/// # Examples
 ///
 /// ```rust
 /// use std::sync::{Arc, Mutex};
@@ -51,11 +62,14 @@ use sys_common::mutex as sys;
 /// let (tx, rx) = channel();
 /// for _ in range(0u, 10) {
 ///     let (data, tx) = (data.clone(), tx.clone());
-///     Thread::spawn(move|| {
+///     Thread::spawn(move || {
 ///         // The shared static can only be accessed once the lock is held.
 ///         // Our non-atomic increment is safe because we're the only thread
 ///         // which can access the shared state when the lock is held.
-///         let mut data = data.lock();
+///         //
+///         // We unwrap() the return value to assert that we are not expecting
+///         // tasks to ever fail while holding the lock.
+///         let mut data = data.lock().unwrap();
 ///         *data += 1;
 ///         if *data == N {
 ///             tx.send(()).unwrap();
@@ -66,6 +80,36 @@ use sys_common::mutex as sys;
 ///
 /// rx.recv().unwrap();
 /// ```
+///
+/// To recover from a poisoned mutex:
+///
+/// ```rust
+/// use std::sync::{Arc, Mutex};
+/// use std::thread::Thread;
+///
+/// let lock = Arc::new(Mutex::new(0u));
+/// let lock2 = lock.clone();
+///
+/// let _ = Thread::spawn(move || -> () {
+///     // This thread will acquire the mutex first, unwrapping the result of
+///     // `lock` because the lock has not been poisoned.
+///     let _lock = lock2.lock().unwrap();
+///
+///     // This panic while holding the lock (`_guard` is in scope) will poison
+///     // the mutex.
+///     panic!();
+/// }).join();
+///
+/// // The lock is poisoned by this point, but the returned result can be
+/// // pattern matched on to return the underlying guard on both branches.
+/// let mut guard = match lock.lock() {
+///     Ok(guard) => guard,
+///     Err(poisoned) => poisoned.into_guard(),
+/// };
+///
+/// *guard += 1;
+/// ```
+#[stable]
 pub struct Mutex<T> {
     // Note that this static mutex is in a *box*, not inlined into the struct
     // itself. Once a native mutex has been used once, its address can never
@@ -96,14 +140,15 @@ unsafe impl<T:Send> Sync for Mutex<T> { }
 /// static LOCK: StaticMutex = MUTEX_INIT;
 ///
 /// {
-///     let _g = LOCK.lock();
+///     let _g = LOCK.lock().unwrap();
 ///     // do some productive work
 /// }
 /// // lock is unlocked here.
 /// ```
+#[unstable = "may be merged with Mutex in the future"]
 pub struct StaticMutex {
     lock: sys::Mutex,
-    poison: UnsafeCell<poison::Flag>,
+    poison: poison::Flag,
 }
 
 unsafe impl Sync for StaticMutex {}
@@ -114,31 +159,27 @@ unsafe impl Sync for StaticMutex {}
 /// The data protected by the mutex can be access through this guard via its
 /// Deref and DerefMut implementations
 #[must_use]
+#[stable]
 pub struct MutexGuard<'a, T: 'a> {
     // funny underscores due to how Deref/DerefMut currently work (they
     // disregard field privacy).
-    __lock: &'a Mutex<T>,
-    __guard: StaticMutexGuard,
-}
-
-/// An RAII implementation of a "scoped lock" of a static mutex. When this
-/// structure is dropped (falls out of scope), the lock will be unlocked.
-#[must_use]
-pub struct StaticMutexGuard {
-    lock: &'static sys::Mutex,
-    marker: marker::NoSend,
-    poison: poison::Guard<'static>,
+    __lock: &'a StaticMutex,
+    __data: &'a UnsafeCell<T>,
+    __poison: poison::Guard,
+    __marker: marker::NoSend,
 }
 
 /// Static initialization of a mutex. This constant can be used to initialize
 /// other mutex constants.
+#[unstable = "may be merged with Mutex in the future"]
 pub const MUTEX_INIT: StaticMutex = StaticMutex {
     lock: sys::MUTEX_INIT,
-    poison: UnsafeCell { value: poison::Flag { failed: false } },
+    poison: poison::FLAG_INIT,
 };
 
 impl<T: Send> Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
+    #[stable]
     pub fn new(t: T) -> Mutex<T> {
         Mutex {
             inner: box MUTEX_INIT,
@@ -153,15 +194,14 @@ impl<T: Send> Mutex<T> {
     /// held. An RAII guard is returned to allow scoped unlock of the lock. When
     /// the guard goes out of scope, the mutex will be unlocked.
     ///
-    /// # Panics
+    /// # Failure
     ///
     /// If another user of this mutex panicked while holding the mutex, then
-    /// this call will immediately panic once the mutex is acquired.
-    pub fn lock(&self) -> MutexGuard<T> {
-        unsafe {
-            let lock: &'static StaticMutex = &*(&*self.inner as *const _);
-            MutexGuard::new(self, lock.lock())
-        }
+    /// this call will return an error once the mutex is acquired.
+    #[stable]
+    pub fn lock(&self) -> LockResult<MutexGuard<T>> {
+        unsafe { self.inner.lock.lock() }
+        MutexGuard::new(&*self.inner, &self.data)
     }
 
     /// Attempts to acquire this lock.
@@ -172,17 +212,17 @@ impl<T: Send> Mutex<T> {
     ///
     /// This function does not block.
     ///
-    /// # Panics
+    /// # Failure
     ///
     /// If another user of this mutex panicked while holding the mutex, then
-    /// this call will immediately panic if the mutex would otherwise be
+    /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    pub fn try_lock(&self) -> Option<MutexGuard<T>> {
-        unsafe {
-            let lock: &'static StaticMutex = &*(&*self.inner as *const _);
-            lock.try_lock().map(|guard| {
-                MutexGuard::new(self, guard)
-            })
+    #[stable]
+    pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
+        if unsafe { self.inner.lock.try_lock() } {
+            Ok(try!(MutexGuard::new(&*self.inner, &self.data)))
+        } else {
+            Err(TryLockError::WouldBlock)
         }
     }
 }
@@ -197,19 +237,27 @@ impl<T: Send> Drop for Mutex<T> {
     }
 }
 
+struct Dummy(UnsafeCell<()>);
+unsafe impl Sync for Dummy {}
+static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
+
 impl StaticMutex {
     /// Acquires this lock, see `Mutex::lock`
-    pub fn lock(&'static self) -> StaticMutexGuard {
+    #[inline]
+    #[unstable = "may be merged with Mutex in the future"]
+    pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
         unsafe { self.lock.lock() }
-        StaticMutexGuard::new(self)
+        MutexGuard::new(self, &DUMMY.0)
     }
 
     /// Attempts to grab this lock, see `Mutex::try_lock`
-    pub fn try_lock(&'static self) -> Option<StaticMutexGuard> {
+    #[inline]
+    #[unstable = "may be merged with Mutex in the future"]
+    pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
         if unsafe { self.lock.try_lock() } {
-            Some(StaticMutexGuard::new(self))
+            Ok(try!(MutexGuard::new(self, &DUMMY.0)))
         } else {
-            None
+            Err(TryLockError::WouldBlock)
         }
     }
 
@@ -223,61 +271,54 @@ impl StaticMutex {
     /// *all* platforms. It may be the case that some platforms do not leak
     /// memory if this method is not called, but this is not guaranteed to be
     /// true on all platforms.
+    #[unstable = "may be merged with Mutex in the future"]
     pub unsafe fn destroy(&'static self) {
         self.lock.destroy()
     }
 }
 
 impl<'mutex, T> MutexGuard<'mutex, T> {
-    fn new(lock: &Mutex<T>, guard: StaticMutexGuard) -> MutexGuard<T> {
-        MutexGuard { __lock: lock, __guard: guard }
+    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,
+                __marker: marker::NoSend,
+            }
+        })
     }
 }
 
-impl<'mutex, T> AsMutexGuard for MutexGuard<'mutex, T> {
-    unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard { &self.__guard }
-}
-
 impl<'mutex, T> Deref<T> for MutexGuard<'mutex, T> {
-    fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.__lock.data.get() } }
+    fn deref<'a>(&'a self) -> &'a T {
+        unsafe { &*self.__data.get() }
+    }
 }
 impl<'mutex, T> DerefMut<T> for MutexGuard<'mutex, T> {
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
-        unsafe { &mut *self.__lock.data.get() }
+        unsafe { &mut *self.__data.get() }
     }
 }
 
-impl StaticMutexGuard {
-    fn new(lock: &'static StaticMutex) -> StaticMutexGuard {
+#[unsafe_destructor]
+impl<'a, T> Drop for MutexGuard<'a, T> {
+    #[inline]
+    fn drop(&mut self) {
         unsafe {
-            let guard = StaticMutexGuard {
-                lock: &lock.lock,
-                marker: marker::NoSend,
-                poison: (*lock.poison.get()).borrow(),
-            };
-            guard.poison.check("mutex");
-            return guard;
+            self.__lock.poison.done(&self.__poison);
+            self.__lock.lock.unlock();
         }
     }
 }
 
-pub fn guard_lock(guard: &StaticMutexGuard) -> &sys::Mutex { guard.lock }
-pub fn guard_poison(guard: &StaticMutexGuard) -> &poison::Guard {
-    &guard.poison
+pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
+    &guard.__lock.lock
 }
 
-impl AsMutexGuard for StaticMutexGuard {
-    unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard { self }
-}
-
-#[unsafe_destructor]
-impl Drop for StaticMutexGuard {
-    fn drop(&mut self) {
-        unsafe {
-            self.poison.done();
-            self.lock.unlock();
-        }
-    }
+pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
+    &guard.__lock.poison
 }
 
 #[cfg(test)]
@@ -296,16 +337,16 @@ mod test {
     #[test]
     fn smoke() {
         let m = Mutex::new(());
-        drop(m.lock());
-        drop(m.lock());
+        drop(m.lock().unwrap());
+        drop(m.lock().unwrap());
     }
 
     #[test]
     fn smoke_static() {
         static M: StaticMutex = MUTEX_INIT;
         unsafe {
-            drop(M.lock());
-            drop(M.lock());
+            drop(M.lock().unwrap());
+            drop(M.lock().unwrap());
             M.destroy();
         }
     }
@@ -320,7 +361,7 @@ mod test {
         fn inc() {
             for _ in range(0, J) {
                 unsafe {
-                    let _g = M.lock();
+                    let _g = M.lock().unwrap();
                     CNT += 1;
                 }
             }
@@ -347,7 +388,7 @@ mod test {
     #[test]
     fn try_lock() {
         let m = Mutex::new(());
-        assert!(m.try_lock().is_some());
+        *m.try_lock().unwrap() = ();
     }
 
     #[test]
@@ -359,22 +400,21 @@ mod test {
             // wait until parent gets in
             rx.recv().unwrap();
             let &(ref lock, ref cvar) = &*packet2.0;
-            let mut lock = lock.lock();
+            let mut lock = lock.lock().unwrap();
             *lock = true;
             cvar.notify_one();
         });
 
         let &(ref lock, ref cvar) = &*packet.0;
-        let lock = lock.lock();
+        let mut lock = lock.lock().unwrap();
         tx.send(()).unwrap();
         assert!(!*lock);
         while !*lock {
-            cvar.wait(&lock);
+            lock = cvar.wait(lock).unwrap();
         }
     }
 
     #[test]
-    #[should_fail]
     fn test_arc_condvar_poison() {
         let packet = Packet(Arc::new((Mutex::new(1i), Condvar::new())));
         let packet2 = Packet(packet.0.clone());
@@ -383,31 +423,35 @@ mod test {
         let _t = Thread::spawn(move || -> () {
             rx.recv().unwrap();
             let &(ref lock, ref cvar) = &*packet2.0;
-            let _g = lock.lock();
+            let _g = lock.lock().unwrap();
             cvar.notify_one();
             // Parent should fail when it wakes up.
             panic!();
         });
 
         let &(ref lock, ref cvar) = &*packet.0;
-        let lock = lock.lock();
+        let mut lock = lock.lock().unwrap();
         tx.send(()).unwrap();
         while *lock == 1 {
-            cvar.wait(&lock);
+            match cvar.wait(lock) {
+                Ok(l) => {
+                    lock = l;
+                    assert_eq!(*lock, 1);
+                }
+                Err(..) => break,
+            }
         }
     }
 
     #[test]
-    #[should_fail]
     fn test_mutex_arc_poison() {
         let arc = Arc::new(Mutex::new(1i));
         let arc2 = arc.clone();
-        let _ = Thread::spawn(move|| {
-            let lock = arc2.lock();
+        Thread::spawn(move|| {
+            let lock = arc2.lock().unwrap();
             assert_eq!(*lock, 2);
         }).join();
-        let lock = arc.lock();
-        assert_eq!(*lock, 1);
+        assert!(arc.lock().is_err());
     }
 
     #[test]
@@ -418,8 +462,8 @@ mod test {
         let arc2 = Arc::new(Mutex::new(arc));
         let (tx, rx) = channel();
         let _t = Thread::spawn(move|| {
-            let lock = arc2.lock();
-            let lock2 = lock.lock();
+            let lock = arc2.lock().unwrap();
+            let lock2 = lock.lock().unwrap();
             assert_eq!(*lock2, 1);
             tx.send(()).unwrap();
         });
@@ -436,13 +480,13 @@ mod test {
             }
             impl Drop for Unwinder {
                 fn drop(&mut self) {
-                    *self.i.lock() += 1;
+                    *self.i.lock().unwrap() += 1;
                 }
             }
             let _u = Unwinder { i: arc2 };
             panic!();
         }).join();
-        let lock = arc.lock();
+        let lock = arc.lock().unwrap();
         assert_eq!(*lock, 2);
     }
 }
diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs
index ad08e9873fa..6e4df118209 100644
--- a/src/libstd/sync/poison.rs
+++ b/src/libstd/sync/poison.rs
@@ -8,31 +8,127 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
+use cell::UnsafeCell;
+use error::FromError;
+use fmt;
 use thread::Thread;
 
-pub struct Flag { pub failed: bool }
+pub struct Flag { failed: UnsafeCell<bool> }
+pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } };
 
 impl Flag {
-    pub fn borrow(&mut self) -> Guard {
-        Guard { flag: &mut self.failed, panicking: Thread::panicking() }
+    #[inline]
+    pub fn borrow(&self) -> LockResult<Guard> {
+        let ret = Guard { panicking: Thread::panicking() };
+        if unsafe { *self.failed.get() } {
+            Err(new_poison_error(ret))
+        } else {
+            Ok(ret)
+        }
+    }
+
+    #[inline]
+    pub fn done(&self, guard: &Guard) {
+        if !guard.panicking && Thread::panicking() {
+            unsafe { *self.failed.get() = true; }
+        }
+    }
+
+    #[inline]
+    pub fn get(&self) -> bool {
+        unsafe { *self.failed.get() }
     }
 }
 
-pub struct Guard<'a> {
-    flag: &'a mut bool,
+#[allow(missing_copy_implementations)]
+pub struct Guard {
     panicking: bool,
 }
 
-impl<'a> Guard<'a> {
-    pub fn check(&self, name: &str) {
-        if *self.flag {
-            panic!("poisoned {} - another task failed inside", name);
-        }
+/// A type of error which can be returned whenever a lock is acquired.
+///
+/// Both Mutexes and RWLocks are poisoned whenever a task fails while the lock
+/// is held. The precise semantics for when a lock is poisoned is documented on
+/// each lock, but once a lock is poisoned then all future acquisitions will
+/// return this error.
+#[stable]
+pub struct PoisonError<T> {
+    guard: T,
+}
+
+/// An enumeration of possible errors which can occur while calling the
+/// `try_lock` method.
+#[stable]
+pub enum TryLockError<T> {
+    /// The lock could not be acquired because another task failed while holding
+    /// the lock.
+    #[stable]
+    Poisoned(PoisonError<T>),
+    /// The lock could not be acquired at this time because the operation would
+    /// otherwise block.
+    #[stable]
+    WouldBlock,
+}
+
+/// A type alias for the result of a lock method which can be poisoned.
+///
+/// The `Ok` variant of this result indicates that the primitive was not
+/// poisoned, and the `Guard` is contained within. The `Err` variant indicates
+/// that the primitive was poisoned. Note that the `Err` variant *also* carries
+/// the associated guard, and it can be acquired through the `into_inner`
+/// method.
+#[stable]
+pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>;
+
+/// A type alias for the result of a nonblocking locking method.
+///
+/// For more information, see `LockResult`. A `TryLockResult` doesn't
+/// necessarily hold the associated guard in the `Err` type as the lock may not
+/// have been acquired for other reasons.
+#[stable]
+pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>;
+
+impl<T> fmt::Show for PoisonError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "poisoned lock: another task failed inside".fmt(f)
+    }
+}
+
+impl<T> PoisonError<T> {
+    /// Consumes this error indicating that a lock is poisoned, returning the
+    /// underlying guard to allow access regardless.
+    #[stable]
+    pub fn into_guard(self) -> T { self.guard }
+}
+
+impl<T> FromError<PoisonError<T>> for TryLockError<T> {
+    fn from_error(err: PoisonError<T>) -> TryLockError<T> {
+        TryLockError::Poisoned(err)
     }
+}
 
-    pub fn done(&mut self) {
-        if !self.panicking && Thread::panicking() {
-            *self.flag = true;
+impl<T> fmt::Show for TryLockError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TryLockError::Poisoned(ref p) => p.fmt(f),
+            TryLockError::WouldBlock => {
+                "try_lock failed because the operation would block".fmt(f)
+            }
         }
     }
 }
+
+pub fn new_poison_error<T>(guard: T) -> PoisonError<T> {
+    PoisonError { guard: guard }
+}
+
+pub fn map_result<T, U, F>(result: LockResult<T>, f: F)
+                           -> LockResult<U>
+                           where F: FnOnce(T) -> U {
+    match result {
+        Ok(t) => Ok(f(t)),
+        Err(PoisonError { guard }) => Err(new_poison_error(f(guard)))
+    }
+}
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index 3c4283c72e2..b23fff31c0a 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -13,7 +13,7 @@ use prelude::v1::*;
 use cell::UnsafeCell;
 use kinds::marker;
 use ops::{Deref, DerefMut};
-use sync::poison;
+use sync::poison::{mod, LockResult, TryLockError, TryLockResult};
 use sys_common::rwlock as sys;
 
 /// A reader-writer lock
@@ -29,12 +29,14 @@ use sys_common::rwlock as sys;
 /// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
 /// to allow access to the contained of the lock.
 ///
+/// # Poisoning
+///
 /// RWLocks, like Mutexes, will become poisoned on panics. Note, however, that
 /// an RWLock may only be poisoned if a panic occurs while it is locked
 /// exclusively (write mode). If a panic occurs in any reader, then the lock
 /// will not be poisoned.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::sync::RWLock;
@@ -43,19 +45,20 @@ use sys_common::rwlock as sys;
 ///
 /// // many reader locks can be held at once
 /// {
-///     let r1 = lock.read();
-///     let r2 = lock.read();
+///     let r1 = lock.read().unwrap();
+///     let r2 = lock.read().unwrap();
 ///     assert_eq!(*r1, 5);
 ///     assert_eq!(*r2, 5);
 /// } // read locks are dropped at this point
 ///
 /// // only one write lock may be held, however
 /// {
-///     let mut w = lock.write();
+///     let mut w = lock.write().unwrap();
 ///     *w += 1;
 ///     assert_eq!(*w, 6);
 /// } // write lock is dropped here
 /// ```
+#[stable]
 pub struct RWLock<T> {
     inner: Box<StaticRWLock>,
     data: UnsafeCell<T>,
@@ -78,64 +81,55 @@ unsafe impl<T> Sync for RWLock<T> {}
 /// static LOCK: StaticRWLock = RWLOCK_INIT;
 ///
 /// {
-///     let _g = LOCK.read();
+///     let _g = LOCK.read().unwrap();
 ///     // ... shared read access
 /// }
 /// {
-///     let _g = LOCK.write();
+///     let _g = LOCK.write().unwrap();
 ///     // ... exclusive write access
 /// }
 /// unsafe { LOCK.destroy() } // free all resources
 /// ```
+#[unstable = "may be merged with RWLock in the future"]
 pub struct StaticRWLock {
-    inner: sys::RWLock,
-    poison: UnsafeCell<poison::Flag>,
+    lock: sys::RWLock,
+    poison: poison::Flag,
 }
 
 unsafe impl Send for StaticRWLock {}
 unsafe impl Sync for StaticRWLock {}
 
 /// Constant initialization for a statically-initialized rwlock.
+#[unstable = "may be merged with RWLock in the future"]
 pub const RWLOCK_INIT: StaticRWLock = StaticRWLock {
-    inner: sys::RWLOCK_INIT,
-    poison: UnsafeCell { value: poison::Flag { failed: false } },
+    lock: sys::RWLOCK_INIT,
+    poison: poison::FLAG_INIT,
 };
 
 /// RAII structure used to release the shared read access of a lock when
 /// dropped.
 #[must_use]
+#[stable]
 pub struct RWLockReadGuard<'a, T: 'a> {
-    __lock: &'a RWLock<T>,
-    __guard: StaticRWLockReadGuard,
+    __lock: &'a StaticRWLock,
+    __data: &'a UnsafeCell<T>,
+    __marker: marker::NoSend,
 }
 
 /// RAII structure used to release the exclusive write access of a lock when
 /// dropped.
 #[must_use]
+#[stable]
 pub struct RWLockWriteGuard<'a, T: 'a> {
-    __lock: &'a RWLock<T>,
-    __guard: StaticRWLockWriteGuard,
-}
-
-/// RAII structure used to release the shared read access of a lock when
-/// dropped.
-#[must_use]
-pub struct StaticRWLockReadGuard {
-    lock: &'static sys::RWLock,
-    marker: marker::NoSend,
-}
-
-/// RAII structure used to release the exclusive write access of a lock when
-/// dropped.
-#[must_use]
-pub struct StaticRWLockWriteGuard {
-    lock: &'static sys::RWLock,
-    marker: marker::NoSend,
-    poison: poison::Guard<'static>,
+    __lock: &'a StaticRWLock,
+    __data: &'a UnsafeCell<T>,
+    __poison: poison::Guard,
+    __marker: marker::NoSend,
 }
 
 impl<T: Send + Sync> RWLock<T> {
     /// Creates a new instance of an RWLock which is unlocked and read to go.
+    #[stable]
     pub fn new(t: T) -> RWLock<T> {
         RWLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) }
     }
@@ -152,17 +146,16 @@ impl<T: Send + Sync> RWLock<T> {
     /// Returns an RAII guard which will release this thread's shared access
     /// once it is dropped.
     ///
-    /// # Panics
+    /// # Failure
     ///
-    /// This function will panic if the RWLock is poisoned. An RWLock is
-    /// poisoned whenever a writer panics while holding an exclusive lock. The
-    /// panic will occur immediately after the lock has been acquired.
+    /// This function will return an error if the RWLock is poisoned. An RWLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock.
+    /// The failure will occur immediately after the lock has been acquired.
     #[inline]
-    pub fn read(&self) -> RWLockReadGuard<T> {
-        unsafe {
-            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
-            RWLockReadGuard::new(self, lock.read())
-        }
+    #[stable]
+    pub fn read(&self) -> LockResult<RWLockReadGuard<T>> {
+        unsafe { self.inner.lock.read() }
+        RWLockReadGuard::new(&*self.inner, &self.data)
     }
 
     /// Attempt to acquire this lock with shared read access.
@@ -174,18 +167,19 @@ impl<T: Send + Sync> RWLock<T> {
     /// guarantees with respect to the ordering of whether contentious readers
     /// or writers will acquire the lock first.
     ///
-    /// # Panics
+    /// # Failure
     ///
-    /// This function will panic if the RWLock is poisoned. An RWLock is
-    /// poisoned whenever a writer panics while holding an exclusive lock. A
-    /// panic will only occur if the lock is acquired.
+    /// This function will return an error if the RWLock is poisoned. An RWLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
     #[inline]
-    pub fn try_read(&self) -> Option<RWLockReadGuard<T>> {
-        unsafe {
-            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
-            lock.try_read().map(|guard| {
-                RWLockReadGuard::new(self, guard)
-            })
+    #[stable]
+    pub fn try_read(&self) -> TryLockResult<RWLockReadGuard<T>> {
+        if unsafe { self.inner.lock.try_read() } {
+            Ok(try!(RWLockReadGuard::new(&*self.inner, &self.data)))
+        } else {
+            Err(TryLockError::WouldBlock)
         }
     }
 
@@ -198,17 +192,16 @@ impl<T: Send + Sync> RWLock<T> {
     /// Returns an RAII guard which will drop the write access of this rwlock
     /// when dropped.
     ///
-    /// # Panics
+    /// # Failure
     ///
-    /// This function will panic if the RWLock is poisoned. An RWLock is
-    /// poisoned whenever a writer panics while holding an exclusive lock. The
-    /// panic will occur when the lock is acquired.
+    /// This function will return an error if the RWLock is poisoned. An RWLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock.
+    /// An error will be returned when the lock is acquired.
     #[inline]
-    pub fn write(&self) -> RWLockWriteGuard<T> {
-        unsafe {
-            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
-            RWLockWriteGuard::new(self, lock.write())
-        }
+    #[stable]
+    pub fn write(&self) -> LockResult<RWLockWriteGuard<T>> {
+        unsafe { self.inner.lock.write() }
+        RWLockWriteGuard::new(&*self.inner, &self.data)
     }
 
     /// Attempt to lock this rwlock with exclusive write access.
@@ -217,18 +210,19 @@ impl<T: Send + Sync> RWLock<T> {
     /// to `write` would otherwise block. If successful, an RAII guard is
     /// returned.
     ///
-    /// # Panics
+    /// # Failure
     ///
-    /// This function will panic if the RWLock is poisoned. An RWLock is
-    /// poisoned whenever a writer panics while holding an exclusive lock. A
-    /// panic will only occur if the lock is acquired.
+    /// This function will return an error if the RWLock is poisoned. An RWLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
     #[inline]
-    pub fn try_write(&self) -> Option<RWLockWriteGuard<T>> {
-        unsafe {
-            let lock: &'static StaticRWLock = &*(&*self.inner as *const _);
-            lock.try_write().map(|guard| {
-                RWLockWriteGuard::new(self, guard)
-            })
+    #[stable]
+    pub fn try_write(&self) -> TryLockResult<RWLockWriteGuard<T>> {
+        if unsafe { self.inner.lock.try_read() } {
+            Ok(try!(RWLockWriteGuard::new(&*self.inner, &self.data)))
+        } else {
+            Err(TryLockError::WouldBlock)
         }
     }
 }
@@ -236,30 +230,37 @@ impl<T: Send + Sync> RWLock<T> {
 #[unsafe_destructor]
 impl<T> Drop for RWLock<T> {
     fn drop(&mut self) {
-        unsafe { self.inner.inner.destroy() }
+        unsafe { self.inner.lock.destroy() }
     }
 }
 
+struct Dummy(UnsafeCell<()>);
+unsafe impl Sync for Dummy {}
+static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
+
 impl StaticRWLock {
     /// Locks this rwlock with shared read access, blocking the current thread
     /// until it can be acquired.
     ///
     /// See `RWLock::read`.
     #[inline]
-    pub fn read(&'static self) -> StaticRWLockReadGuard {
-        unsafe { self.inner.read() }
-        StaticRWLockReadGuard::new(self)
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn read(&'static self) -> LockResult<RWLockReadGuard<'static, ()>> {
+        unsafe { self.lock.read() }
+        RWLockReadGuard::new(self, &DUMMY.0)
     }
 
     /// Attempt to acquire this lock with shared read access.
     ///
     /// See `RWLock::try_read`.
     #[inline]
-    pub fn try_read(&'static self) -> Option<StaticRWLockReadGuard> {
-        if unsafe { self.inner.try_read() } {
-            Some(StaticRWLockReadGuard::new(self))
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn try_read(&'static self)
+                    -> TryLockResult<RWLockReadGuard<'static, ()>> {
+        if unsafe { self.lock.try_read() } {
+            Ok(try!(RWLockReadGuard::new(self, &DUMMY.0)))
         } else {
-            None
+            Err(TryLockError::WouldBlock)
         }
     }
 
@@ -268,20 +269,23 @@ impl StaticRWLock {
     ///
     /// See `RWLock::write`.
     #[inline]
-    pub fn write(&'static self) -> StaticRWLockWriteGuard {
-        unsafe { self.inner.write() }
-        StaticRWLockWriteGuard::new(self)
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn write(&'static self) -> LockResult<RWLockWriteGuard<'static, ()>> {
+        unsafe { self.lock.write() }
+        RWLockWriteGuard::new(self, &DUMMY.0)
     }
 
     /// Attempt to lock this rwlock with exclusive write access.
     ///
     /// See `RWLock::try_write`.
     #[inline]
-    pub fn try_write(&'static self) -> Option<StaticRWLockWriteGuard> {
-        if unsafe { self.inner.try_write() } {
-            Some(StaticRWLockWriteGuard::new(self))
+    #[unstable = "may be merged with RWLock in the future"]
+    pub fn try_write(&'static self)
+                     -> TryLockResult<RWLockWriteGuard<'static, ()>> {
+        if unsafe { self.lock.try_write() } {
+            Ok(try!(RWLockWriteGuard::new(self, &DUMMY.0)))
         } else {
-            None
+            Err(TryLockError::WouldBlock)
         }
     }
 
@@ -291,70 +295,62 @@ impl StaticRWLock {
     /// active users of the lock, and this also doesn't prevent any future users
     /// of this lock. This method is required to be called to not leak memory on
     /// all platforms.
+    #[unstable = "may be merged with RWLock in the future"]
     pub unsafe fn destroy(&'static self) {
-        self.inner.destroy()
+        self.lock.destroy()
     }
 }
 
 impl<'rwlock, T> RWLockReadGuard<'rwlock, T> {
-    fn new(lock: &RWLock<T>, guard: StaticRWLockReadGuard)
-           -> RWLockReadGuard<T> {
-        RWLockReadGuard { __lock: lock, __guard: guard }
+    fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell<T>)
+           -> LockResult<RWLockReadGuard<'rwlock, T>> {
+        poison::map_result(lock.poison.borrow(), |_| {
+            RWLockReadGuard {
+                __lock: lock,
+                __data: data,
+                __marker: marker::NoSend,
+            }
+        })
     }
 }
 impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> {
-    fn new(lock: &RWLock<T>, guard: StaticRWLockWriteGuard)
-           -> RWLockWriteGuard<T> {
-        RWLockWriteGuard { __lock: lock, __guard: guard }
+    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,
+                __marker: marker::NoSend,
+            }
+        })
     }
 }
 
 impl<'rwlock, T> Deref<T> for RWLockReadGuard<'rwlock, T> {
-    fn deref(&self) -> &T { unsafe { &*self.__lock.data.get() } }
+    fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
 impl<'rwlock, T> Deref<T> for RWLockWriteGuard<'rwlock, T> {
-    fn deref(&self) -> &T { unsafe { &*self.__lock.data.get() } }
+    fn deref(&self) -> &T { unsafe { &*self.__data.get() } }
 }
 impl<'rwlock, T> DerefMut<T> for RWLockWriteGuard<'rwlock, T> {
-    fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__lock.data.get() } }
-}
-
-impl StaticRWLockReadGuard {
-    fn new(lock: &'static StaticRWLock) -> StaticRWLockReadGuard {
-        let guard = StaticRWLockReadGuard {
-            lock: &lock.inner,
-            marker: marker::NoSend,
-        };
-        unsafe { (*lock.poison.get()).borrow().check("rwlock"); }
-        return guard;
-    }
-}
-impl StaticRWLockWriteGuard {
-    fn new(lock: &'static StaticRWLock) -> StaticRWLockWriteGuard {
-        unsafe {
-            let guard = StaticRWLockWriteGuard {
-                lock: &lock.inner,
-                marker: marker::NoSend,
-                poison: (*lock.poison.get()).borrow(),
-            };
-            guard.poison.check("rwlock");
-            return guard;
-        }
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.__data.get() }
     }
 }
 
 #[unsafe_destructor]
-impl Drop for StaticRWLockReadGuard {
+impl<'a, T> Drop for RWLockReadGuard<'a, T> {
     fn drop(&mut self) {
-        unsafe { self.lock.read_unlock(); }
+        unsafe { self.__lock.lock.read_unlock(); }
     }
 }
 
 #[unsafe_destructor]
-impl Drop for StaticRWLockWriteGuard {
+impl<'a, T> Drop for RWLockWriteGuard<'a, T> {
     fn drop(&mut self) {
-        self.poison.done();
-        unsafe { self.lock.write_unlock(); }
+        self.__lock.poison.done(&self.__poison);
+        unsafe { self.__lock.lock.write_unlock(); }
     }
 }
 
@@ -370,19 +366,19 @@ mod tests {
     #[test]
     fn smoke() {
         let l = RWLock::new(());
-        drop(l.read());
-        drop(l.write());
-        drop((l.read(), l.read()));
-        drop(l.write());
+        drop(l.read().unwrap());
+        drop(l.write().unwrap());
+        drop((l.read().unwrap(), l.read().unwrap()));
+        drop(l.write().unwrap());
     }
 
     #[test]
     fn static_smoke() {
         static R: StaticRWLock = RWLOCK_INIT;
-        drop(R.read());
-        drop(R.write());
-        drop((R.read(), R.read()));
-        drop(R.write());
+        drop(R.read().unwrap());
+        drop(R.write().unwrap());
+        drop((R.read().unwrap(), R.read().unwrap()));
+        drop(R.write().unwrap());
         unsafe { R.destroy(); }
     }
 
@@ -396,12 +392,12 @@ mod tests {
         for _ in range(0, N) {
             let tx = tx.clone();
             Thread::spawn(move|| {
-                let mut rng = rand::task_rng();
+                let mut rng = rand::thread_rng();
                 for _ in range(0, M) {
                     if rng.gen_weighted_bool(N) {
-                        drop(R.write());
+                        drop(R.write().unwrap());
                     } else {
-                        drop(R.read());
+                        drop(R.read().unwrap());
                     }
                 }
                 drop(tx);
@@ -413,51 +409,47 @@ mod tests {
     }
 
     #[test]
-    #[should_fail]
     fn test_rw_arc_poison_wr() {
         let arc = Arc::new(RWLock::new(1i));
         let arc2 = arc.clone();
-        let _ = Thread::spawn(move|| {
-            let lock = arc2.write();
-            assert_eq!(*lock, 2);
+        let _: Result<uint, _> = Thread::spawn(move|| {
+            let _lock = arc2.write().unwrap();
+            panic!();
         }).join();
-        let lock = arc.read();
-        assert_eq!(*lock, 1);
+        assert!(arc.read().is_err());
     }
 
     #[test]
-    #[should_fail]
     fn test_rw_arc_poison_ww() {
         let arc = Arc::new(RWLock::new(1i));
         let arc2 = arc.clone();
-        let _ = Thread::spawn(move|| {
-            let lock = arc2.write();
-            assert_eq!(*lock, 2);
+        let _: Result<uint, _> = Thread::spawn(move|| {
+            let _lock = arc2.write().unwrap();
+            panic!();
         }).join();
-        let lock = arc.write();
-        assert_eq!(*lock, 1);
+        assert!(arc.write().is_err());
     }
 
     #[test]
     fn test_rw_arc_no_poison_rr() {
         let arc = Arc::new(RWLock::new(1i));
         let arc2 = arc.clone();
-        let _ = Thread::spawn(move|| {
-            let lock = arc2.read();
-            assert_eq!(*lock, 2);
+        let _: Result<uint, _> = Thread::spawn(move|| {
+            let _lock = arc2.read().unwrap();
+            panic!();
         }).join();
-        let lock = arc.read();
+        let lock = arc.read().unwrap();
         assert_eq!(*lock, 1);
     }
     #[test]
     fn test_rw_arc_no_poison_rw() {
         let arc = Arc::new(RWLock::new(1i));
         let arc2 = arc.clone();
-        let _ = Thread::spawn(move|| {
-            let lock = arc2.read();
-            assert_eq!(*lock, 2);
+        let _: Result<uint, _> = Thread::spawn(move|| {
+            let _lock = arc2.read().unwrap();
+            panic!()
         }).join();
-        let lock = arc.write();
+        let lock = arc.write().unwrap();
         assert_eq!(*lock, 1);
     }
 
@@ -468,7 +460,7 @@ mod tests {
         let (tx, rx) = channel();
 
         Thread::spawn(move|| {
-            let mut lock = arc2.write();
+            let mut lock = arc2.write().unwrap();
             for _ in range(0u, 10) {
                 let tmp = *lock;
                 *lock = -1;
@@ -483,7 +475,7 @@ mod tests {
         for _ in range(0u, 5) {
             let arc3 = arc.clone();
             children.push(Thread::spawn(move|| {
-                let lock = arc3.read();
+                let lock = arc3.read().unwrap();
                 assert!(*lock >= 0);
             }));
         }
@@ -495,7 +487,7 @@ mod tests {
 
         // Wait for writer to finish
         rx.recv().unwrap();
-        let lock = arc.read();
+        let lock = arc.read().unwrap();
         assert_eq!(*lock, 10);
     }
 
@@ -509,14 +501,14 @@ mod tests {
             }
             impl Drop for Unwinder {
                 fn drop(&mut self) {
-                    let mut lock = self.i.write();
+                    let mut lock = self.i.write().unwrap();
                     *lock += 1;
                 }
             }
             let _u = Unwinder { i: arc2 };
             panic!();
         }).join();
-        let lock = arc.read();
+        let lock = arc.read().unwrap();
         assert_eq!(*lock, 2);
     }
 }
diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs
index 784b173b99e..b03c0e08035 100644
--- a/src/libstd/sync/semaphore.rs
+++ b/src/libstd/sync/semaphore.rs
@@ -68,9 +68,9 @@ impl Semaphore {
     /// This method will block until the internal count of the semaphore is at
     /// least 1.
     pub fn acquire(&self) {
-        let mut count = self.lock.lock();
+        let mut count = self.lock.lock().unwrap();
         while *count <= 0 {
-            self.cvar.wait(&count);
+            count = self.cvar.wait(count).unwrap();
         }
         *count -= 1;
     }
@@ -80,7 +80,7 @@ impl Semaphore {
     /// This will increment the number of resources in this semaphore by 1 and
     /// will notify any pending waiters in `acquire` or `access` if necessary.
     pub fn release(&self) {
-        *self.lock.lock() += 1;
+        *self.lock.lock().unwrap() += 1;
         self.cvar.notify_one();
     }
 
diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs
index b0325998358..c34fa66d12a 100644
--- a/src/libstd/sync/task_pool.rs
+++ b/src/libstd/sync/task_pool.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Abstraction of a task pool for basic parallelism.
+//! Abstraction of a thread pool for basic parallelism.
 
 use core::prelude::*;
 
@@ -45,9 +45,9 @@ impl<'a> Drop for Sentinel<'a> {
     }
 }
 
-/// A task pool used to execute functions in parallel.
+/// A thread pool used to execute functions in parallel.
 ///
-/// Spawns `n` worker tasks and replenishes the pool if any worker tasks
+/// Spawns `n` worker threads and replenishes the pool if any worker threads
 /// panic.
 ///
 /// # Example
@@ -70,34 +70,34 @@ impl<'a> Drop for Sentinel<'a> {
 /// assert_eq!(rx.iter().take(8u).sum(), 8u);
 /// ```
 pub struct TaskPool {
-    // How the taskpool communicates with subtasks.
+    // How the threadpool communicates with subthreads.
     //
-    // This is the only such Sender, so when it is dropped all subtasks will
+    // This is the only such Sender, so when it is dropped all subthreads will
     // quit.
     jobs: Sender<Thunk>
 }
 
 impl TaskPool {
-    /// Spawns a new task pool with `tasks` tasks.
+    /// Spawns a new thread pool with `threads` threads.
     ///
     /// # Panics
     ///
-    /// This function will panic if `tasks` is 0.
-    pub fn new(tasks: uint) -> TaskPool {
-        assert!(tasks >= 1);
+    /// This function will panic if `threads` is 0.
+    pub fn new(threads: uint) -> TaskPool {
+        assert!(threads >= 1);
 
         let (tx, rx) = channel::<Thunk>();
         let rx = Arc::new(Mutex::new(rx));
 
-        // Taskpool tasks.
-        for _ in range(0, tasks) {
+        // Threadpool threads
+        for _ in range(0, threads) {
             spawn_in_pool(rx.clone());
         }
 
         TaskPool { jobs: tx }
     }
 
-    /// Executes the function `job` on a task in the pool.
+    /// Executes the function `job` on a thread in the pool.
     pub fn execute<F>(&self, job: F)
         where F : FnOnce(), F : Send
     {
@@ -107,14 +107,14 @@ impl TaskPool {
 
 fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
     Thread::spawn(move |:| {
-        // Will spawn a new task on panic unless it is cancelled.
+        // Will spawn a new thread on panic unless it is cancelled.
         let sentinel = Sentinel::new(&jobs);
 
         loop {
             let message = {
                 // Only lock jobs for the time it takes
                 // to get a job, not run it.
-                let lock = jobs.lock();
+                let lock = jobs.lock().unwrap();
                 lock.recv()
             };
 
@@ -167,12 +167,12 @@ mod test {
 
         let pool = TaskPool::new(TEST_TASKS);
 
-        // Panic all the existing tasks.
+        // Panic all the existing threads.
         for _ in range(0, TEST_TASKS) {
             pool.execute(move|| -> () { panic!() });
         }
 
-        // Ensure new tasks were spawned to compensate.
+        // Ensure new threads were spawned to compensate.
         let (tx, rx) = channel();
         for _ in range(0, TEST_TASKS) {
             let tx = tx.clone();
@@ -191,7 +191,7 @@ mod test {
         let pool = TaskPool::new(TEST_TASKS);
         let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));
 
-        // Panic all the existing tasks in a bit.
+        // Panic all the existing threads in a bit.
         for _ in range(0, TEST_TASKS) {
             let waiter = waiter.clone();
             pool.execute(move|| {
diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs
index c1aace764fc..d4039fd96ff 100644
--- a/src/libstd/sys/common/backtrace.rs
+++ b/src/libstd/sys/common/backtrace.rs
@@ -115,10 +115,10 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
 
                         // in theory we can demangle any Unicode code point, but
                         // for simplicity we just catch the common ones.
-                        "$x20" => " ",
-                        "$x27" => "'",
-                        "$x5b" => "[",
-                        "$x5d" => "]"
+                        "$u{20}" => " ",
+                        "$u{27}" => "'",
+                        "$u{5b}" => "[",
+                        "$u{5d}" => "]"
                     )
                 } else {
                     let idx = match rest.find('$') {
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs
index b9dc5f0e398..1ce42aaa175 100644
--- a/src/libstd/sys/common/helper_thread.rs
+++ b/src/libstd/sys/common/helper_thread.rs
@@ -23,6 +23,7 @@
 use prelude::v1::*;
 
 use cell::UnsafeCell;
+use comm::{channel, Sender, Receiver};
 use mem;
 use rt;
 use sync::{StaticMutex, StaticCondvar};
@@ -84,7 +85,7 @@ impl<M: Send> Helper<M> {
         F: FnOnce() -> T,
     {
         unsafe {
-            let _guard = self.lock.lock();
+            let _guard = self.lock.lock().unwrap();
             if !*self.initialized.get() {
                 let (tx, rx) = channel();
                 *self.chan.get() = mem::transmute(box tx);
@@ -96,7 +97,7 @@ impl<M: Send> Helper<M> {
                 let t = f();
                 Thread::spawn(move |:| {
                     helper(receive.0, rx, t);
-                    let _g = self.lock.lock();
+                    let _g = self.lock.lock().unwrap();
                     *self.shutdown.get() = true;
                     self.cond.notify_one()
                 }).detach();
@@ -112,7 +113,7 @@ impl<M: Send> Helper<M> {
     /// This is only valid if the worker thread has previously booted
     pub fn send(&'static self, msg: M) {
         unsafe {
-            let _guard = self.lock.lock();
+            let _guard = self.lock.lock().unwrap();
 
             // Must send and *then* signal to ensure that the child receives the
             // message. Otherwise it could wake up and go to sleep before we
@@ -128,7 +129,7 @@ impl<M: Send> Helper<M> {
             // Shut down, but make sure this is done inside our lock to ensure
             // that we'll always receive the exit signal when the thread
             // returns.
-            let guard = self.lock.lock();
+            let mut guard = self.lock.lock().unwrap();
 
             // Close the channel by destroying it
             let chan: Box<Sender<M>> = mem::transmute(*self.chan.get());
@@ -138,7 +139,7 @@ impl<M: Send> Helper<M> {
 
             // Wait for the child to exit
             while !*self.shutdown.get() {
-                self.cond.wait(&guard);
+                guard = self.cond.wait(guard).unwrap();
             }
             drop(guard);
 
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index 9ab5077ae79..cb0c5581abd 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -17,6 +17,7 @@ use io::net::addrinfo;
 use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
 use io::{IoResult, IoError};
 use libc::{mod, c_char, c_int};
+use c_str::CString;
 use mem;
 use num::Int;
 use ptr::{mod, null, null_mut};
@@ -269,7 +270,7 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
     // Collect all the results we found
     let mut addrs = Vec::new();
     let mut rp = res;
-    while rp.is_not_null() {
+    while !rp.is_null() {
         unsafe {
             let addr = try!(sockaddr_to_addr(mem::transmute((*rp).ai_addr),
                                              (*rp).ai_addrlen as uint));
@@ -291,6 +292,43 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// get_address_name
+////////////////////////////////////////////////////////////////////////////////
+
+extern "system" {
+    fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t,
+        host: *mut c_char, hostlen: libc::size_t,
+        serv: *mut c_char, servlen: libc::size_t,
+        flags: c_int) -> c_int;
+}
+
+const NI_MAXHOST: uint = 1025;
+
+pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> {
+    let addr = SocketAddr{ip: addr, port: 0};
+
+    let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
+    let len = addr_to_sockaddr(addr, &mut storage);
+
+    let mut hostbuf = [0 as c_char; NI_MAXHOST];
+
+    let res = unsafe {
+        getnameinfo(&storage as *const _ as *const libc::sockaddr, len,
+            hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t,
+            ptr::null_mut(), 0,
+            0)
+    };
+
+    if res != 0 {
+        return Err(last_gai_error(res));
+    }
+
+    unsafe {
+        Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string())
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // Timeout helpers
 //
 // The read/write functions below are the helpers for reading/writing a socket
@@ -669,7 +707,7 @@ impl TcpStream {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: self.inner.lock.lock(),
+            guard: self.inner.lock.lock().unwrap(),
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
@@ -808,7 +846,7 @@ impl UdpSocket {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: self.inner.lock.lock(),
+            guard: self.inner.lock.lock().unwrap(),
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
index dc21feb17a8..8c76eb1504d 100644
--- a/src/libstd/sys/common/thread_info.rs
+++ b/src/libstd/sys/common/thread_info.rs
@@ -26,13 +26,13 @@ struct ThreadInfo {
 thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) }
 
 impl ThreadInfo {
-    fn with<R>(f: |&mut ThreadInfo| -> R) -> R {
+    fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R {
         if THREAD_INFO.destroyed() {
             panic!("Use of std::thread::Thread::current() is not possible after \
                     the thread's local data has been destroyed");
         }
 
-        THREAD_INFO.with(|c| {
+        THREAD_INFO.with(move |c| {
             if c.borrow().is_none() {
                 *c.borrow_mut() = Some(ThreadInfo {
                     stack_bounds: (0, 0),
diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs
index 983d0e5fa14..9e26475f814 100644
--- a/src/libstd/sys/unix/backtrace.rs
+++ b/src/libstd/sys/unix/backtrace.rs
@@ -123,7 +123,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> {
     try!(writeln!(w, "stack backtrace:"));
     // 100 lines should be enough
     const SIZE: uint = 100;
-    let mut buf: [*mut libc::c_void, ..SIZE] = unsafe {mem::zeroed()};
+    let mut buf: [*mut libc::c_void; SIZE] = unsafe {mem::zeroed()};
     let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as uint};
 
     // skipping the first one as it is write itself
@@ -244,7 +244,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
     use iter::{Iterator, IteratorExt};
     use os;
     use path::GenericPath;
-    use ptr::RawPtr;
+    use ptr::PtrExt;
     use ptr;
     use slice::SliceExt;
 
@@ -320,7 +320,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
     //        tested if this is required or not.
     unsafe fn init_state() -> *mut backtrace_state {
         static mut STATE: *mut backtrace_state = 0 as *mut backtrace_state;
-        static mut LAST_FILENAME: [libc::c_char, ..256] = [0, ..256];
+        static mut LAST_FILENAME: [libc::c_char; 256] = [0; 256];
         if !STATE.is_null() { return STATE }
         let selfname = if cfg!(target_os = "freebsd") ||
                           cfg!(target_os = "dragonfly") {
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index a4ebcbd25d0..1bb8ed78177 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -94,7 +94,7 @@ mod select {
 
     #[repr(C)]
     pub struct fd_set {
-        fds_bits: [i32, ..(FD_SETSIZE / 32)]
+        fds_bits: [i32; (FD_SETSIZE / 32)]
     }
 
     pub fn fd_set(set: &mut fd_set, fd: i32) {
@@ -115,7 +115,7 @@ mod select {
     #[repr(C)]
     pub struct fd_set {
         // FIXME: shouldn't this be a c_ulong?
-        fds_bits: [libc::uintptr_t, ..(FD_SETSIZE / uint::BITS)]
+        fds_bits: [libc::uintptr_t; (FD_SETSIZE / uint::BITS)]
     }
 
     pub fn fd_set(set: &mut fd_set, fd: i32) {
@@ -168,13 +168,13 @@ mod signal {
     #[repr(C)]
     #[cfg(target_word_size = "32")]
     pub struct sigset_t {
-        __val: [libc::c_ulong, ..32],
+        __val: [libc::c_ulong; 32],
     }
 
     #[repr(C)]
     #[cfg(target_word_size = "64")]
     pub struct sigset_t {
-        __val: [libc::c_ulong, ..16],
+        __val: [libc::c_ulong; 16],
     }
 }
 
@@ -211,15 +211,15 @@ mod signal {
         pub sa_handler: extern fn(libc::c_int),
         pub sa_mask: sigset_t,
         sa_restorer: *mut libc::c_void,
-        sa_resv: [libc::c_int, ..1],
+        sa_resv: [libc::c_int; 1],
     }
 
-    impl ::kinds::Send for sigaction { }
-    impl ::kinds::Sync for sigaction { }
+    unsafe impl ::kinds::Send for sigaction { }
+    unsafe impl ::kinds::Sync for sigaction { }
 
     #[repr(C)]
     pub struct sigset_t {
-        __val: [libc::c_ulong, ..32],
+        __val: [libc::c_ulong; 32],
     }
 }
 
@@ -244,7 +244,7 @@ mod signal {
     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
     #[repr(C)]
     pub struct sigset_t {
-        bits: [u32, ..4],
+        bits: [u32; 4],
     }
 
     // This structure has more fields, but we're not all that interested in
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index d537579d453..e3e0b279c12 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -371,7 +371,7 @@ mod tests {
         let mut writer = FileDesc::new(writer, true);
 
         writer.write(b"test").ok().unwrap();
-        let mut buf = [0u8, ..4];
+        let mut buf = [0u8; 4];
         match reader.read(&mut buf) {
             Ok(4) => {
                 assert_eq!(buf[0], 't' as u8);
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 15dad810756..4199cbc1bb9 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -56,6 +56,7 @@ pub mod udp;
 
 pub mod addrinfo {
     pub use sys_common::net::get_host_addresses;
+    pub use sys_common::net::get_address_name;
 }
 
 // FIXME: move these to c module
@@ -109,6 +110,8 @@ pub fn decode_error(errno: i32) -> IoError {
              "file descriptor is not a TTY"),
         libc::ETIMEDOUT => (io::TimedOut, "operation timed out"),
         libc::ECANCELED => (io::TimedOut, "operation aborted"),
+        libc::consts::os::posix88::EEXIST =>
+            (io::PathAlreadyExists, "path already exists"),
 
         // These two constants can have the same value on some systems,
         // but different values on others, so we can't use a match
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index a221a6bc15b..6d145e47516 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -101,7 +101,7 @@ pub fn error_string(errno: i32) -> String {
         }
     }
 
-    let mut buf = [0 as c_char, ..TMPBUF_SZ];
+    let mut buf = [0 as c_char; TMPBUF_SZ];
 
     let p = buf.as_mut_ptr();
     unsafe {
@@ -114,7 +114,7 @@ pub fn error_string(errno: i32) -> String {
 }
 
 pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
-    let mut fds = [0, ..2];
+    let mut fds = [0; 2];
     if libc::pipe(fds.as_mut_ptr()) == 0 {
         Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true)))
     } else {
@@ -125,7 +125,7 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
 pub fn getcwd() -> IoResult<Path> {
     use c_str::CString;
 
-    let mut buf = [0 as c_char, ..BUF_BYTES];
+    let mut buf = [0 as c_char; BUF_BYTES];
     unsafe {
         if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
             Err(IoError::last_error())
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 6954866257e..e46814ef4a2 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -145,7 +145,7 @@ impl UnixStream {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: unsafe { self.inner.lock.lock() },
+            guard: unsafe { self.inner.lock.lock().unwrap() },
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index a11fe3487a8..af09bf4fbd0 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -121,7 +121,7 @@ impl Process {
 
                     let p = Process{ pid: pid };
                     drop(output);
-                    let mut bytes = [0, ..8];
+                    let mut bytes = [0; 8];
                     return match input.read(&mut bytes) {
                         Ok(8) => {
                             assert!(combine(CLOEXEC_MSG_FOOTER) == combine(bytes.slice(4, 8)),
@@ -196,7 +196,7 @@ impl Process {
                 // up /dev/null into that file descriptor. Otherwise, the first file
                 // descriptor opened up in the child would be numbered as one of the
                 // stdio file descriptors, which is likely to wreak havoc.
-                let setup = |src: Option<P>, dst: c_int| {
+                let setup = |&: src: Option<P>, dst: c_int| {
                     let src = match src {
                         None => {
                             let flags = if dst == libc::STDIN_FILENO {
@@ -349,7 +349,7 @@ impl Process {
         // handler we're going to start receiving signals.
         fn register_sigchld() -> (libc::c_int, c::sigaction) {
             unsafe {
-                let mut pipes = [0, ..2];
+                let mut pipes = [0; 2];
                 assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0);
                 set_nonblocking(pipes[0], true).ok().unwrap();
                 set_nonblocking(pipes[1], true).ok().unwrap();
@@ -483,7 +483,7 @@ impl Process {
         fn drain(fd: libc::c_int) -> bool {
             let mut ret = false;
             loop {
-                let mut buf = [0u8, ..1];
+                let mut buf = [0u8; 1];
                 match unsafe {
                     libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void,
                                buf.len() as libc::size_t)
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index bcbbb8766b7..95ab9b459d6 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -184,12 +184,12 @@ mod imp {
         #[cfg(target_word_size = "32")]
         #[repr(C)]
         pub struct sigset_t {
-            __val: [libc::c_ulong, ..32],
+            __val: [libc::c_ulong; 32],
         }
         #[cfg(target_word_size = "64")]
         #[repr(C)]
         pub struct sigset_t {
-            __val: [libc::c_ulong, ..16],
+            __val: [libc::c_ulong; 16],
         }
 
         #[repr(C)]
diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs
index 007826b4b9d..77c5582d8a4 100644
--- a/src/libstd/sys/unix/sync.rs
+++ b/src/libstd/sys/unix/sync.rs
@@ -86,30 +86,30 @@ mod os {
     #[repr(C)]
     pub struct pthread_mutex_t {
         __sig: libc::c_long,
-        __opaque: [u8, ..__PTHREAD_MUTEX_SIZE__],
+        __opaque: [u8; __PTHREAD_MUTEX_SIZE__],
     }
     #[repr(C)]
     pub struct pthread_cond_t {
         __sig: libc::c_long,
-        __opaque: [u8, ..__PTHREAD_COND_SIZE__],
+        __opaque: [u8; __PTHREAD_COND_SIZE__],
     }
     #[repr(C)]
     pub struct pthread_rwlock_t {
         __sig: libc::c_long,
-        __opaque: [u8, ..__PTHREAD_RWLOCK_SIZE__],
+        __opaque: [u8; __PTHREAD_RWLOCK_SIZE__],
     }
 
     pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
         __sig: _PTHREAD_MUTEX_SIG_INIT,
-        __opaque: [0, ..__PTHREAD_MUTEX_SIZE__],
+        __opaque: [0; __PTHREAD_MUTEX_SIZE__],
     };
     pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
         __sig: _PTHREAD_COND_SIG_INIT,
-        __opaque: [0, ..__PTHREAD_COND_SIZE__],
+        __opaque: [0; __PTHREAD_COND_SIZE__],
     };
     pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
         __sig: _PTHREAD_RWLOCK_SIG_INIT,
-        __opaque: [0, ..__PTHREAD_RWLOCK_SIZE__],
+        __opaque: [0; __PTHREAD_RWLOCK_SIZE__],
     };
 }
 
@@ -145,30 +145,30 @@ mod os {
     #[repr(C)]
     pub struct pthread_mutex_t {
         __align: libc::c_longlong,
-        size: [u8, ..__SIZEOF_PTHREAD_MUTEX_T],
+        size: [u8; __SIZEOF_PTHREAD_MUTEX_T],
     }
     #[repr(C)]
     pub struct pthread_cond_t {
         __align: libc::c_longlong,
-        size: [u8, ..__SIZEOF_PTHREAD_COND_T],
+        size: [u8; __SIZEOF_PTHREAD_COND_T],
     }
     #[repr(C)]
     pub struct pthread_rwlock_t {
         __align: libc::c_longlong,
-        size: [u8, ..__SIZEOF_PTHREAD_RWLOCK_T],
+        size: [u8; __SIZEOF_PTHREAD_RWLOCK_T],
     }
 
     pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
         __align: 0,
-        size: [0, ..__SIZEOF_PTHREAD_MUTEX_T],
+        size: [0; __SIZEOF_PTHREAD_MUTEX_T],
     };
     pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
         __align: 0,
-        size: [0, ..__SIZEOF_PTHREAD_COND_T],
+        size: [0; __SIZEOF_PTHREAD_COND_T],
     };
     pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
         __align: 0,
-        size: [0, ..__SIZEOF_PTHREAD_RWLOCK_T],
+        size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
     };
 }
 #[cfg(target_os = "android")]
@@ -187,7 +187,7 @@ mod os {
         writerThreadId: libc::c_int,
         pendingReaders: libc::c_int,
         pendingWriters: libc::c_int,
-        reserved: [*mut libc::c_void, ..4],
+        reserved: [*mut libc::c_void; 4],
     }
 
     pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
@@ -203,6 +203,6 @@ mod os {
         writerThreadId: 0,
         pendingReaders: 0,
         pendingWriters: 0,
-        reserved: [0 as *mut _, ..4],
+        reserved: [0 as *mut _; 4],
     };
 }
diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs
index 4afe13d8735..afa77140d13 100644
--- a/src/libstd/sys/unix/timer.rs
+++ b/src/libstd/sys/unix/timer.rs
@@ -120,9 +120,9 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
     // signals the first requests in the queue, possible re-enqueueing it.
     fn signal(active: &mut Vec<Box<Inner>>,
               dead: &mut Vec<(uint, Box<Inner>)>) {
-        let mut timer = match active.remove(0) {
-            Some(timer) => timer, None => return
-        };
+        if active.is_empty() { return }
+
+        let mut timer = active.remove(0);
         let mut cb = timer.cb.take().unwrap();
         cb.call();
         if timer.repeat {
@@ -178,7 +178,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
                         Ok(RemoveTimer(id, ack)) => {
                             match dead.iter().position(|&(i, _)| id == i) {
                                 Some(i) => {
-                                    let (_, i) = dead.remove(i).unwrap();
+                                    let (_, i) = dead.remove(i);
                                     ack.send(i).unwrap();
                                     continue
                                 }
@@ -186,7 +186,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
                             }
                             let i = active.iter().position(|i| i.id == id);
                             let i = i.expect("no timer found");
-                            let t = active.remove(i).unwrap();
+                            let t = active.remove(i);
                             ack.send(t).unwrap();
                         }
                         Err(..) => break
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
index 42c8f7705e1..319a458087b 100644
--- a/src/libstd/sys/windows/backtrace.rs
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -68,7 +68,7 @@ const IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
 struct SYMBOL_INFO {
     SizeOfStruct: libc::c_ulong,
     TypeIndex: libc::c_ulong,
-    Reserved: [u64, ..2],
+    Reserved: [u64; 2],
     Index: libc::c_ulong,
     Size: libc::c_ulong,
     ModBase: u64,
@@ -83,7 +83,7 @@ struct SYMBOL_INFO {
     // note that windows has this as 1, but it basically just means that
     // the name is inline at the end of the struct. For us, we just bump
     // the struct size up to MAX_SYM_NAME.
-    Name: [libc::c_char, ..MAX_SYM_NAME],
+    Name: [libc::c_char; MAX_SYM_NAME],
 }
 
 
@@ -108,10 +108,10 @@ struct STACKFRAME64 {
     AddrStack: ADDRESS64,
     AddrBStore: ADDRESS64,
     FuncTableEntry: *mut libc::c_void,
-    Params: [u64, ..4],
+    Params: [u64; 4],
     Far: libc::BOOL,
     Virtual: libc::BOOL,
-    Reserved: [u64, ..3],
+    Reserved: [u64; 3],
     KdHelp: KDHELP64,
 }
 
@@ -127,7 +127,7 @@ struct KDHELP64 {
     KiUserExceptionDispatcher: u64,
     StackBase: u64,
     StackLimit: u64,
-    Reserved: [u64, ..5],
+    Reserved: [u64; 5],
 }
 
 #[cfg(target_arch = "x86")]
@@ -162,7 +162,7 @@ mod arch {
         EFlags: libc::DWORD,
         Esp: libc::DWORD,
         SegSs: libc::DWORD,
-        ExtendedRegisters: [u8, ..MAXIMUM_SUPPORTED_EXTENSION],
+        ExtendedRegisters: [u8; MAXIMUM_SUPPORTED_EXTENSION],
     }
 
     #[repr(C)]
@@ -174,7 +174,7 @@ mod arch {
         ErrorSelector: libc::DWORD,
         DataOffset: libc::DWORD,
         DataSelector: libc::DWORD,
-        RegisterArea: [u8, ..80],
+        RegisterArea: [u8; 80],
         Cr0NpxState: libc::DWORD,
     }
 
@@ -198,7 +198,7 @@ mod arch {
 
     #[repr(C)]
     pub struct CONTEXT {
-        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte
         P1Home: DWORDLONG,
         P2Home: DWORDLONG,
         P3Home: DWORDLONG,
@@ -245,7 +245,7 @@ mod arch {
 
         FltSave: FLOATING_SAVE_AREA,
 
-        VectorRegister: [M128A, .. 26],
+        VectorRegister: [M128A; 26],
         VectorControl: DWORDLONG,
 
         DebugControl: DWORDLONG,
@@ -257,15 +257,15 @@ mod arch {
 
     #[repr(C)]
     pub struct M128A {
-        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte
         Low:  c_ulonglong,
         High: c_longlong
     }
 
     #[repr(C)]
     pub struct FLOATING_SAVE_AREA {
-        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
-        _Dummy: [u8, ..512] // FIXME: Fill this out
+        _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte
+        _Dummy: [u8; 512] // FIXME: Fill this out
     }
 
     pub fn init_frame(frame: &mut super::STACKFRAME64,
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index d1177776dd8..1ee57434fb9 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -43,8 +43,8 @@ pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED;
 pub struct WSADATA {
     pub wVersion: libc::WORD,
     pub wHighVersion: libc::WORD,
-    pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1],
-    pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1],
+    pub szDescription: [u8; WSADESCRIPTION_LEN + 1],
+    pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
     pub iMaxSockets: u16,
     pub iMaxUdpDg: u16,
     pub lpVendorInfo: *mut u8,
@@ -57,8 +57,8 @@ pub struct WSADATA {
     pub iMaxSockets: u16,
     pub iMaxUdpDg: u16,
     pub lpVendorInfo: *mut u8,
-    pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1],
-    pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1],
+    pub szDescription: [u8; WSADESCRIPTION_LEN + 1],
+    pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
 }
 
 pub type LPWSADATA = *mut WSADATA;
@@ -66,7 +66,7 @@ pub type LPWSADATA = *mut WSADATA;
 #[repr(C)]
 pub struct WSANETWORKEVENTS {
     pub lNetworkEvents: libc::c_long,
-    pub iErrorCode: [libc::c_int, ..FD_MAX_EVENTS],
+    pub iErrorCode: [libc::c_int; FD_MAX_EVENTS],
 }
 
 pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS;
@@ -76,7 +76,7 @@ pub type WSAEVENT = libc::HANDLE;
 #[repr(C)]
 pub struct fd_set {
     fd_count: libc::c_uint,
-    fd_array: [libc::SOCKET, ..FD_SETSIZE],
+    fd_array: [libc::SOCKET; FD_SETSIZE],
 }
 
 pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) {
@@ -131,9 +131,9 @@ extern "system" {
 
 pub mod compat {
     use intrinsics::{atomic_store_relaxed, transmute};
-    use iter::IteratorExt;
     use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
     use prelude::v1::*;
+    use c_str::ToCStr;
 
     extern "system" {
         fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 632261f0ad9..523d60c71aa 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -265,8 +265,8 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
                 {
                     let filename = os::truncate_utf16_at_nul(&wfd.cFileName);
                     match String::from_utf16(filename) {
-                        Some(filename) => paths.push(Path::new(filename)),
-                        None => {
+                        Ok(filename) => paths.push(Path::new(filename)),
+                        Err(..) => {
                             assert!(libc::FindClose(find_handle) != 0);
                             return Err(IoError {
                                 kind: io::InvalidInput,
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 94f5822ccea..c354e7b3ece 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -24,6 +24,7 @@ use num;
 use mem;
 use io::{mod, IoResult, IoError};
 use sync::{Once, ONCE_INIT};
+use comm::Sender;
 
 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
     static $name: Helper<$m> = Helper {
@@ -58,6 +59,7 @@ pub mod udp;
 
 pub mod addrinfo {
     pub use sys_common::net::get_host_addresses;
+    pub use sys_common::net::get_address_name;
 }
 
 // FIXME: move these to c module
@@ -122,6 +124,8 @@ pub fn decode_error(errno: i32) -> IoError {
              "invalid handle provided to function"),
         libc::ERROR_NOTHING_TO_TERMINATE =>
             (io::InvalidInput, "no process to kill"),
+        libc::ERROR_ALREADY_EXISTS =>
+            (io::PathAlreadyExists, "path already exists"),
 
         // libuv maps this error code to EISDIR. we do too. if it is found
         // to be incorrect, we can add in some more machinery to only
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index 159512525d8..dfdee0e0385 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -17,14 +17,14 @@ use prelude::v1::*;
 
 use fmt;
 use io::{IoResult, IoError};
-use libc::{c_int, c_char, c_void};
+use iter::repeat;
+use libc::{c_int, c_void};
 use libc;
 use os;
 use path::BytesContainer;
 use ptr;
-use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
-use sys::fs::FileDesc;
 use slice;
+use sys::fs::FileDesc;
 
 use os::TMPBUF_SZ;
 use libc::types::os::arch::extra::DWORD;
@@ -80,7 +80,7 @@ pub fn error_string(errnum: i32) -> String {
     // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
     let langId = 0x0800 as DWORD;
 
-    let mut buf = [0 as WCHAR, ..TMPBUF_SZ];
+    let mut buf = [0 as WCHAR; TMPBUF_SZ];
 
     unsafe {
         let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
@@ -99,8 +99,9 @@ pub fn error_string(errnum: i32) -> String {
 
         let msg = String::from_utf16(truncate_utf16_at_nul(&buf));
         match msg {
-            Some(msg) => format!("OS Error {}: {}", errnum, msg),
-            None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum),
+            Ok(msg) => format!("OS Error {}: {}", errnum, msg),
+            Err(..) => format!("OS Error {} (FormatMessageW() returned \
+                                invalid UTF-16)", errnum),
         }
     }
 }
@@ -111,7 +112,7 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
     // fully understand. Here we explicitly make the pipe non-inheritable,
     // which means to pass it to a subprocess they need to be duplicated
     // first, as in std::run.
-    let mut fds = [0, ..2];
+    let mut fds = [0; 2];
     match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint,
                      (libc::O_BINARY | libc::O_NOINHERIT) as c_int) {
         0 => {
@@ -123,13 +124,15 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
     }
 }
 
-pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD) -> Option<String> {
+pub fn fill_utf16_buf_and_decode<F>(mut f: F) -> Option<String> where
+    F: FnMut(*mut u16, DWORD) -> DWORD,
+{
     unsafe {
         let mut n = TMPBUF_SZ as DWORD;
         let mut res = None;
         let mut done = false;
         while !done {
-            let mut buf = Vec::from_elem(n as uint, 0u16);
+            let mut buf: Vec<u16> = repeat(0u16).take(n as uint).collect();
             let k = f(buf.as_mut_ptr(), n);
             if k == (0 as DWORD) {
                 done = true;
@@ -147,7 +150,7 @@ pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD) -> Option<String
                 // We want to explicitly catch the case when the
                 // closure returned invalid UTF-16, rather than
                 // set `res` to None and continue.
-                let s = String::from_utf16(sub)
+                let s = String::from_utf16(sub).ok()
                     .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16");
                 res = Some(s)
             }
@@ -161,7 +164,7 @@ pub fn getcwd() -> IoResult<Path> {
     use libc::GetCurrentDirectoryW;
     use io::OtherIoError;
 
-    let mut buf = [0 as u16, ..BUF_BYTES];
+    let mut buf = [0 as u16; BUF_BYTES];
     unsafe {
         if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
             return Err(IoError::last_error());
@@ -169,8 +172,8 @@ pub fn getcwd() -> IoResult<Path> {
     }
 
     match String::from_utf16(truncate_utf16_at_nul(&buf)) {
-        Some(ref cwd) => Ok(Path::new(cwd)),
-        None => Err(IoError {
+        Ok(ref cwd) => Ok(Path::new(cwd)),
+        Err(..) => Err(IoError {
             kind: OtherIoError,
             desc: "GetCurrentDirectoryW returned invalid UTF-16",
             detail: None,
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index f99995eb028..cb99a886ce4 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -12,7 +12,7 @@ use prelude::v1::*;
 
 use libc::{pid_t, c_void, c_int};
 use libc;
-use c_str::CString;
+use c_str::{CString, ToCStr};
 use io;
 use mem;
 use os;
@@ -163,7 +163,7 @@ impl Process {
             // Similarly to unix, we don't actually leave holes for the stdio file
             // descriptors, but rather open up /dev/null equivalents. These
             // equivalents are drawn from libuv's windows process spawning.
-            let set_fd = |fd: &Option<P>, slot: &mut HANDLE,
+            let set_fd = |&: fd: &Option<P>, slot: &mut HANDLE,
                           is_stdin: bool| {
                 match *fd {
                     None => {
@@ -467,6 +467,7 @@ fn free_handle(handle: *mut ()) {
 
 #[cfg(test)]
 mod tests {
+    use c_str::ToCStr;
 
     #[test]
     fn test_make_command_line() {
diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs
index bdf2e0bccb1..e8b447022cb 100644
--- a/src/libstd/sys/windows/stack_overflow.rs
+++ b/src/libstd/sys/windows/stack_overflow.rs
@@ -90,7 +90,7 @@ pub struct EXCEPTION_RECORD {
     pub ExceptionRecord: *mut EXCEPTION_RECORD,
     pub ExceptionAddress: LPVOID,
     pub NumberParameters: DWORD,
-    pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS]
+    pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS]
 }
 
 pub struct EXCEPTION_POINTERS {
diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs
index 3df0debff51..485dc251050 100644
--- a/src/libstd/sys/windows/timer.rs
+++ b/src/libstd/sys/windows/timer.rs
@@ -21,16 +21,17 @@
 //! the other two implementations of timers with nothing *that* new showing up.
 
 use self::Req::*;
+use prelude::v1::*;
 
 use libc;
 use ptr;
 use comm;
 
+use comm::{channel, Sender, Receiver};
+use io::IoResult;
 use sys::c;
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
-use prelude::v1::*;
-use io::IoResult;
 
 helper_init! { static HELPER: Helper<Req> }
 
diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs
index dfa3440067a..7591025d76d 100644
--- a/src/libstd/sys/windows/tty.rs
+++ b/src/libstd/sys/windows/tty.rs
@@ -27,17 +27,18 @@
 
 use prelude::v1::*;
 
-use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
-use super::c::{ERROR_ILLEGAL_CHARACTER};
-use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
-use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
-use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
+use io::{mod, IoError, IoResult, MemReader};
+use iter::repeat;
+use libc::types::os::arch::extra::LPCVOID;
 use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID};
 use libc::{get_osfhandle, CloseHandle};
-use libc::types::os::arch::extra::LPCVOID;
-use io::{mod, IoError, IoResult, MemReader};
 use ptr;
 use str::from_utf8;
+use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
+use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
+use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
+use super::c::{ERROR_ILLEGAL_CHARACTER};
+use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
 
 fn invalid_encoding() -> IoError {
     IoError {
@@ -90,7 +91,7 @@ impl TTY {
     pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         // Read more if the buffer is empty
         if self.utf8.eof() {
-            let mut utf16 = Vec::from_elem(0x1000, 0u16);
+            let mut utf16: Vec<u16> = repeat(0u16).take(0x1000).collect();
             let mut num: DWORD = 0;
             match unsafe { ReadConsoleW(self.handle,
                                          utf16.as_mut_ptr() as LPVOID,
@@ -102,8 +103,8 @@ impl TTY {
             };
             utf16.truncate(num as uint);
             let utf8 = match String::from_utf16(utf16.as_slice()) {
-                Some(utf8) => utf8.into_bytes(),
-                None => return Err(invalid_encoding()),
+                Ok(utf8) => utf8.into_bytes(),
+                Err(..) => return Err(invalid_encoding()),
             };
             self.utf8 = MemReader::new(utf8);
         }
diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs
index 5c9e6153afb..9a6fcab6a88 100644
--- a/src/libstd/thread.rs
+++ b/src/libstd/thread.rs
@@ -313,7 +313,7 @@ impl Thread {
 
     /// Spawn a new joinable thread, returning a `JoinGuard` for it.
     ///
-    /// The join guard can be used to explicitly join the child thead (via
+    /// The join guard can be used to explicitly join the child thread (via
     /// `join`), returning `Result<T>`, or it will implicitly join the child
     /// upon being dropped. To detach the child, allowing it to outlive the
     /// current thread, use `detach`.  See the module documentation for additional details.
@@ -334,6 +334,7 @@ impl Thread {
     }
 
     /// Determines whether the current thread is panicking.
+    #[inline]
     pub fn panicking() -> bool {
         unwind::panicking()
     }
@@ -349,9 +350,9 @@ impl Thread {
     // or futuxes, and in either case may allow spurious wakeups.
     pub fn park() {
         let thread = Thread::current();
-        let mut guard = thread.inner.lock.lock();
+        let mut guard = thread.inner.lock.lock().unwrap();
         while !*guard {
-            thread.inner.cvar.wait(&guard);
+            guard = thread.inner.cvar.wait(guard).unwrap();
         }
         *guard = false;
     }
@@ -360,7 +361,7 @@ impl Thread {
     ///
     /// See the module doc for more detail.
     pub fn unpark(&self) {
-        let mut guard = self.inner.lock.lock();
+        let mut guard = self.inner.lock.lock().unwrap();
         if !*guard {
             *guard = true;
             self.inner.cvar.notify_one();
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs
index 6cd26a366ae..4950337b9af 100644
--- a/src/libstd/thread_local/mod.rs
+++ b/src/libstd/thread_local/mod.rs
@@ -189,22 +189,7 @@ macro_rules! __thread_local_inner {
             }
         };
 
-        #[cfg(all(stage0, not(any(target_os = "macos", target_os = "linux"))))]
-        const INIT: ::std::thread_local::KeyInner<$t> = {
-            unsafe extern fn __destroy(ptr: *mut u8) {
-                ::std::thread_local::destroy_value::<$t>(ptr);
-            }
-
-            ::std::thread_local::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: $init },
-                os: ::std::thread_local::OsStaticKey {
-                    inner: ::std::thread_local::OS_INIT_INNER,
-                    dtor: ::std::option::Option::Some(__destroy),
-                },
-            }
-        };
-
-        #[cfg(all(not(stage0), not(any(target_os = "macos", target_os = "linux"))))]
+        #[cfg(all(not(any(target_os = "macos", target_os = "linux"))))]
         const INIT: ::std::thread_local::KeyInner<$t> = {
             unsafe extern fn __destroy(ptr: *mut u8) {
                 ::std::thread_local::destroy_value::<$t>(ptr);
@@ -240,13 +225,18 @@ impl<T: 'static> Key<T> {
         unsafe {
             let slot = slot.get().expect("cannot access a TLS value during or \
                                           after it is destroyed");
-            if (*slot.get()).is_none() {
-                *slot.get() = Some((self.init)());
-            }
-            f((*slot.get()).as_ref().unwrap())
+            f(match *slot.get() {
+                Some(ref inner) => inner,
+                None => self.init(slot),
+            })
         }
     }
 
+    unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
+        *slot.get() = Some((self.init)());
+        (*slot.get()).as_ref().unwrap()
+    }
+
     /// Test this TLS key to determine whether its value has been destroyed for
     /// the current thread or not.
     ///
@@ -341,16 +331,10 @@ mod imp {
         // *should* be the case that this loop always terminates because we
         // provide the guarantee that a TLS key cannot be set after it is
         // flagged for destruction.
-        #[cfg(not(stage0))]
         static DTORS: os::StaticKey = os::StaticKey {
             inner: os::INIT_INNER,
             dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)),
         };
-        #[cfg(stage0)]
-        static DTORS: os::StaticKey = os::StaticKey {
-            inner: os::INIT_INNER,
-            dtor: Some(run_dtors),
-        };
         type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
         if DTORS.get().is_null() {
             let v: Box<List> = box Vec::new();
diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs
index a06048aa706..a2e2bd43849 100644
--- a/src/libstd/thread_local/scoped.rs
+++ b/src/libstd/thread_local/scoped.rs
@@ -62,10 +62,10 @@ pub struct Key<T> { #[doc(hidden)] pub inner: KeyInner<T> }
 #[macro_export]
 macro_rules! scoped_thread_local {
     (static $name:ident: $t:ty) => (
-        __scoped_thread_local_inner!(static $name: $t)
+        __scoped_thread_local_inner!(static $name: $t);
     );
     (pub static $name:ident: $t:ty) => (
-        __scoped_thread_local_inner!(pub static $name: $t)
+        __scoped_thread_local_inner!(pub static $name: $t);
     );
 }
 
@@ -240,6 +240,8 @@ mod tests {
     use cell::Cell;
     use prelude::v1::*;
 
+    scoped_thread_local!(static FOO: uint);
+
     #[test]
     fn smoke() {
         scoped_thread_local!(static BAR: uint);
@@ -264,4 +266,16 @@ mod tests {
             });
         });
     }
+
+    #[test]
+    fn scope_item_allowed() {
+        assert!(!FOO.is_set());
+        FOO.set(&1, || {
+            assert!(FOO.is_set());
+            FOO.with(|slot| {
+                assert_eq!(*slot, 1);
+            });
+        });
+        assert!(!FOO.is_set());
+    }
 }
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index f7351c9580f..51564b53976 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -262,20 +262,6 @@ impl Duration {
     }
 }
 
-// NOTE(stage0): Remove impl after a snapshot
-#[cfg(stage0)]
-impl Neg<Duration> for Duration {
-    #[inline]
-    fn neg(&self) -> Duration {
-        if self.nanos == 0 {
-            Duration { secs: -self.secs, nanos: 0 }
-        } else {
-            Duration { secs: -self.secs - 1, nanos: NANOS_PER_SEC - self.nanos }
-        }
-    }
-}
-
-#[cfg(not(stage0))]  // NOTE(stage0): Remove cfg after a snapshot
 impl Neg<Duration> for Duration {
     #[inline]
     fn neg(self) -> Duration {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index d4932fbb5f1..12432c8c78f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -371,10 +371,18 @@ pub const DUMMY_NODE_ID: NodeId = -1;
 /// detects Copy, Send and Sync.
 #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub enum TyParamBound {
-    TraitTyParamBound(PolyTraitRef),
+    TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
     RegionTyParamBound(Lifetime)
 }
 
+/// A modifier on a bound, currently this is only used for `?Sized`, where the
+/// modifier is `Maybe`. Negative bounds should also be handled here.
+#[deriving(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
+pub enum TraitBoundModifier {
+    None,
+    Maybe,
+}
+
 pub type TyParamBounds = OwnedSlice<TyParamBound>;
 
 #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
@@ -382,7 +390,6 @@ pub struct TyParam {
     pub ident: Ident,
     pub id: NodeId,
     pub bounds: TyParamBounds,
-    pub unbound: Option<TraitRef>,
     pub default: Option<P<Ty>>,
     pub span: Span
 }
@@ -723,8 +730,7 @@ pub enum Expr_ {
     ExprField(P<Expr>, SpannedIdent),
     ExprTupField(P<Expr>, Spanned<uint>),
     ExprIndex(P<Expr>, P<Expr>),
-    ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability),
-    ExprRange(P<Expr>, Option<P<Expr>>),
+    ExprRange(Option<P<Expr>>, Option<P<Expr>>),
 
     /// Variable reference, possibly containing `::` and/or
     /// type parameters, e.g. foo::bar::<baz>
@@ -758,7 +764,7 @@ pub enum Expr_ {
 pub struct QPath {
     pub self_type: P<Ty>,
     pub trait_ref: P<TraitRef>,
-    pub item_name: Ident,
+    pub item_name: Ident, // FIXME(#20301) -- should use Name
 }
 
 #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@@ -1489,7 +1495,7 @@ pub struct PolyTraitRef {
     pub bound_lifetimes: Vec<LifetimeDef>,
 
     /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
-    pub trait_ref: TraitRef
+    pub trait_ref: TraitRef,
 }
 
 #[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@@ -1578,8 +1584,6 @@ pub enum Item_ {
     /// Represents a Trait Declaration
     ItemTrait(Unsafety,
               Generics,
-              Option<TraitRef>, // (optional) default bound not required for Self.
-                                // Currently, only Sized makes sense here.
               TyParamBounds,
               Vec<TraitItem>),
     ItemImpl(Unsafety,
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 9b42a8f7540..b5395d09ca7 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -26,7 +26,7 @@ use arena::TypedArena;
 use std::cell::RefCell;
 use std::fmt;
 use std::io::IoResult;
-use std::iter;
+use std::iter::{mod, repeat};
 use std::mem;
 use std::slice;
 
@@ -726,7 +726,7 @@ impl<'ast> NodeCollector<'ast> {
         debug!("ast_map: {} => {}", id, entry);
         let len = self.map.len();
         if id as uint >= len {
-            self.map.grow(id as uint - len + 1, NotPresent);
+            self.map.extend(repeat(NotPresent).take(id as uint - len + 1));
         }
         self.map[id as uint] = entry;
     }
@@ -780,9 +780,9 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                     None => {}
                 }
             }
-            ItemTrait(_, _, _, ref bounds, ref trait_items) => {
+            ItemTrait(_, _, ref bounds, ref trait_items) => {
                 for b in bounds.iter() {
-                    if let TraitTyParamBound(ref t) = *b {
+                    if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
                         self.insert(t.trait_ref.ref_id, NodeItem(i));
                     }
                 }
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 9196055267f..a8393ed9d39 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -618,34 +618,38 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
     id_visitor.operation.result
 }
 
-// FIXME(#19596) unbox `it`
-pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool {
-    if !it(pat) {
-        return false;
-    }
-
-    match pat.node {
-        PatIdent(_, _, Some(ref p)) => walk_pat(&**p, it),
-        PatStruct(_, ref fields, _) => {
-            fields.iter().all(|field| walk_pat(&*field.node.pat, |p| it(p)))
-        }
-        PatEnum(_, Some(ref s)) | PatTup(ref s) => {
-            s.iter().all(|p| walk_pat(&**p, |p| it(p)))
+pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
+    // FIXME(#19596) this is a workaround, but there should be a better way
+    fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool where G: FnMut(&Pat) -> bool {
+        if !(*it)(pat) {
+            return false;
         }
-        PatBox(ref s) | PatRegion(ref s) => {
-            walk_pat(&**s, it)
-        }
-        PatVec(ref before, ref slice, ref after) => {
-            before.iter().all(|p| walk_pat(&**p, |p| it(p))) &&
-            slice.iter().all(|p| walk_pat(&**p, |p| it(p))) &&
-            after.iter().all(|p| walk_pat(&**p, |p| it(p)))
-        }
-        PatMac(_) => panic!("attempted to analyze unexpanded pattern"),
-        PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
-        PatEnum(_, _) => {
-            true
+
+        match pat.node {
+            PatIdent(_, _, Some(ref p)) => walk_pat_(&**p, it),
+            PatStruct(_, ref fields, _) => {
+                fields.iter().all(|field| walk_pat_(&*field.node.pat, it))
+            }
+            PatEnum(_, Some(ref s)) | PatTup(ref s) => {
+                s.iter().all(|p| walk_pat_(&**p, it))
+            }
+            PatBox(ref s) | PatRegion(ref s) => {
+                walk_pat_(&**s, it)
+            }
+            PatVec(ref before, ref slice, ref after) => {
+                before.iter().all(|p| walk_pat_(&**p, it)) &&
+                slice.iter().all(|p| walk_pat_(&**p, it)) &&
+                after.iter().all(|p| walk_pat_(&**p, it))
+            }
+            PatMac(_) => panic!("attempted to analyze unexpanded pattern"),
+            PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
+            PatEnum(_, _) => {
+                true
+            }
         }
     }
+
+    walk_pat_(pat, &mut it)
 }
 
 pub trait EachViewItem {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 042a1bd0781..5eac6546c6b 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -568,6 +568,38 @@ impl CodeMap {
             ExpnId(i) => f(Some(&(*self.expansions.borrow())[i as uint]))
         }
     }
+
+    /// Check if a span is "internal" to a macro. This means that it is entirely generated by a
+    /// macro expansion and contains no code that was passed in as an argument.
+    pub fn span_is_internal(&self, span: Span) -> bool {
+        // first, check if the given expression was generated by a macro or not
+        // we need to go back the expn_info tree to check only the arguments
+        // of the initial macro call, not the nested ones.
+        let mut is_internal = false;
+        let mut expnid = span.expn_id;
+        while self.with_expn_info(expnid, |expninfo| {
+            match expninfo {
+                Some(ref info) => {
+                    // save the parent expn_id for next loop iteration
+                    expnid = info.call_site.expn_id;
+                    if info.callee.span.is_none() {
+                        // it's a compiler built-in, we *really* don't want to mess with it
+                        // so we skip it, unless it was called by a regular macro, in which case
+                        // we will handle the caller macro next turn
+                        is_internal = true;
+                        true // continue looping
+                    } else {
+                        // was this expression from the current macro arguments ?
+                        is_internal = !( span.lo > info.call_site.lo &&
+                                         span.hi < info.call_site.hi );
+                        true // continue looping
+                    }
+                },
+                _ => false // stop looping
+            }
+        }) { /* empty while loop body */ }
+        return is_internal;
+    }
 }
 
 #[cfg(test)]
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index d2185a00876..94a3784291d 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -139,11 +139,11 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
                                        .collect();
             ast::ItemImpl(u, a, b, c, impl_items)
         }
-        ast::ItemTrait(u, a, b, c, methods) => {
+        ast::ItemTrait(u, a, b, methods) => {
             let methods = methods.into_iter()
                                  .filter(|m| trait_method_in_cfg(cx, m))
                                  .collect();
-            ast::ItemTrait(u, a, b, c, methods)
+            ast::ItemTrait(u, a, b, methods)
         }
         ast::ItemStruct(def, generics) => {
             ast::ItemStruct(fold_struct(cx, def), generics)
diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs
index 90fc28014e6..720a907fe77 100644
--- a/src/libsyntax/diagnostics/plugin.rs
+++ b/src/libsyntax/diagnostics/plugin.rs
@@ -119,6 +119,6 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
         });
 
     MacItems::new(vec![quote_item!(ecx,
-        pub static $name: [(&'static str, &'static str), ..$count] = $expr;
+        pub static $name: [(&'static str, &'static str); $count] = $expr;
     ).unwrap()].into_iter())
 }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 8e69076a2c5..5134897893f 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -47,18 +47,18 @@ pub trait ItemDecorator {
               sp: Span,
               meta_item: &ast::MetaItem,
               item: &ast::Item,
-              push: |P<ast::Item>|);
+              push: Box<FnMut(P<ast::Item>)>);
 }
 
 impl<F> ItemDecorator for F
-    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P<ast::Item>|)
+    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, Box<FnMut(P<ast::Item>)>)
 {
     fn expand(&self,
               ecx: &mut ExtCtxt,
               sp: Span,
               meta_item: &ast::MetaItem,
               item: &ast::Item,
-              push: |P<ast::Item>|) {
+              push: Box<FnMut(P<ast::Item>)>) {
         (*self)(ecx, sp, meta_item, item, push)
     }
 }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 77165168746..239af188909 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -68,7 +68,6 @@ pub trait AstBuilder {
                span: Span,
                id: ast::Ident,
                bounds: OwnedSlice<ast::TyParamBound>,
-               unbound: Option<ast::TraitRef>,
                default: Option<P<ast::Ty>>) -> ast::TyParam;
 
     fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
@@ -414,13 +413,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                span: Span,
                id: ast::Ident,
                bounds: OwnedSlice<ast::TyParamBound>,
-               unbound: Option<ast::TraitRef>,
                default: Option<P<ast::Ty>>) -> ast::TyParam {
         ast::TyParam {
             ident: id,
             id: ast::DUMMY_NODE_ID,
             bounds: bounds,
-            unbound: unbound,
             default: default,
             span: span
         }
@@ -455,7 +452,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn typarambound(&self, path: ast::Path) -> ast::TyParamBound {
-        ast::TraitTyParamBound(self.poly_trait_ref(path))
+        ast::TraitTyParamBound(self.poly_trait_ref(path), ast::TraitBoundModifier::None)
     }
 
     fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime {
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index 57dfbc0c6e8..3c8d74c14ee 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -58,10 +58,10 @@ fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__D", None, vec!(Path::new_(
+            bounds: vec!(("__D", vec!(Path::new_(
                             vec!(krate, "Decoder"), None,
                             vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", None, vec!()))
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs
index b3621490ce3..49bcb26a4c2 100644
--- a/src/libsyntax/ext/deriving/default.rs
+++ b/src/libsyntax/ext/deriving/default.rs
@@ -55,7 +55,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
         cx.ident_of("Default"),
         cx.ident_of("default")
     );
-    let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
+    let default_call = |&: span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
 
     return match *substr.fields {
         StaticStruct(_, ref summary) => {
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 8bd3df6232c..5829f34bccc 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -134,10 +134,10 @@ fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds {
             lifetimes: Vec::new(),
-            bounds: vec!(("__S", None, vec!(Path::new_(
+            bounds: vec!(("__S", vec!(Path::new_(
                             vec!(krate, "Encoder"), None,
                             vec!(box Literal(Path::new_local("__E"))), true))),
-                         ("__E", None, vec!()))
+                         ("__E", vec!()))
         },
         methods: vec!(
             MethodDef {
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index cf0201294ae..9149c20ce1b 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -417,7 +417,6 @@ impl<'a> TraitDef<'a> {
             cx.typaram(self.span,
                        ty_param.ident,
                        OwnedSlice::from_vec(bounds),
-                       ty_param.unbound.clone(),
                        None)
         }));
 
@@ -936,7 +935,7 @@ impl<'a> MethodDef<'a> {
         // where each tuple has length = self_args.len()
         let mut match_arms: Vec<ast::Arm> = variants.iter().enumerate()
             .map(|(index, variant)| {
-                let mk_self_pat = |cx: &mut ExtCtxt, self_arg_name: &str| {
+                let mk_self_pat = |&: cx: &mut ExtCtxt, self_arg_name: &str| {
                     let (p, idents) = trait_.create_enum_variant_pattern(cx, type_ident,
                                                                          &**variant,
                                                                          self_arg_name,
diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs
index 56d11c2377f..95bdd8b9ffd 100644
--- a/src/libsyntax/ext/deriving/generic/ty.rs
+++ b/src/libsyntax/ext/deriving/generic/ty.rs
@@ -189,15 +189,19 @@ impl<'a> Ty<'a> {
 }
 
 
-fn mk_ty_param(cx: &ExtCtxt, span: Span, name: &str,
-               bounds: &[Path], unbound: Option<ast::TraitRef>,
-               self_ident: Ident, self_generics: &Generics) -> ast::TyParam {
+fn mk_ty_param(cx: &ExtCtxt,
+               span: Span,
+               name: &str,
+               bounds: &[Path],
+               self_ident: Ident,
+               self_generics: &Generics)
+               -> ast::TyParam {
     let bounds =
         bounds.iter().map(|b| {
             let path = b.to_path(cx, span, self_ident, self_generics);
             cx.typarambound(path)
         }).collect();
-    cx.typaram(span, cx.ident_of(name), bounds, unbound, None)
+    cx.typaram(span, cx.ident_of(name), bounds, None)
 }
 
 fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
@@ -216,7 +220,7 @@ fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
 #[deriving(Clone)]
 pub struct LifetimeBounds<'a> {
     pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
-    pub bounds: Vec<(&'a str, Option<ast::TraitRef>, Vec<Path<'a>>)>,
+    pub bounds: Vec<(&'a str, Vec<Path<'a>>)>,
 }
 
 impl<'a> LifetimeBounds<'a> {
@@ -239,12 +243,11 @@ impl<'a> LifetimeBounds<'a> {
         }).collect();
         let ty_params = self.bounds.iter().map(|t| {
             match t {
-                &(ref name, ref unbound, ref bounds) => {
+                &(ref name, ref bounds) => {
                     mk_ty_param(cx,
                                 span,
                                 *name,
                                 bounds.as_slice(),
-                                unbound.clone(),
                                 self_ty,
                                 self_generics)
                 }
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index 4e59124a129..9ad0ad16217 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -30,7 +30,7 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
                     vec!(box Literal(Path::new_local("__S"))), true),
          LifetimeBounds {
              lifetimes: Vec::new(),
-             bounds: vec!(("__S", None,
+             bounds: vec!(("__S",
                            vec!(Path::new(vec!("std", "hash", "Writer"))))),
          },
          Path::new_local("__S"))
@@ -71,7 +71,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
         _ => cx.span_bug(trait_span, "incorrect number of arguments in `deriving(Hash)`")
     };
     let hash_ident = substr.method_ident;
-    let call_hash = |span, thing_expr| {
+    let call_hash = |&: span, thing_expr| {
         let expr = cx.expr_method_call(span, thing_expr, hash_ident, vec!(state_expr.clone()));
         cx.stmt_expr(expr)
     };
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
index edf29e670eb..75f763b5c38 100644
--- a/src/libsyntax/ext/deriving/mod.rs
+++ b/src/libsyntax/ext/deriving/mod.rs
@@ -45,7 +45,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
                             _span: Span,
                             mitem: &MetaItem,
                             item: &Item,
-                            push: |P<Item>|) {
+                            mut push: Box<FnMut(P<Item>)>) {
     match mitem.node {
         MetaNameValue(_, ref l) => {
             cx.span_err(l.span, "unexpected value in `deriving`");
@@ -64,7 +64,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
                     MetaWord(ref tname) => {
                         macro_rules! expand(($func:path) => ($func(cx, titem.span,
                                                                    &**titem, item,
-                                                                   |i| push(i))));
+                                                                   |i| push.call_mut((i,)))));
                         match tname.get() {
                             "Clone" => expand!(clone::expand_deriving_clone),
 
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index 4f6e4d1fb3c..1ddf5b2a5c3 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -36,7 +36,6 @@ pub fn expand_deriving_rand<F>(cx: &mut ExtCtxt,
                 generics: LifetimeBounds {
                     lifetimes: Vec::new(),
                     bounds: vec!(("R",
-                                  None,
                                   vec!( Path::new(vec!("std", "rand", "Rng")) )))
                 },
                 explicit_self: None,
diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs
index ea32549cad2..73331f06aa4 100644
--- a/src/libsyntax/ext/deriving/zero.rs
+++ b/src/libsyntax/ext/deriving/zero.rs
@@ -71,7 +71,7 @@ fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
         cx.ident_of("Zero"),
         cx.ident_of("zero")
     );
-    let zero_call = |span| cx.expr_call_global(span, zero_ident.clone(), Vec::new());
+    let zero_call = |&: span| cx.expr_call_global(span, zero_ident.clone(), Vec::new());
 
     return match *substr.fields {
         StaticStruct(_, ref summary) => {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index d2d624fa05e..5de7068563d 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -424,7 +424,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
                     // 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,
-                               |item| items.push(item));
+                               box |&mut : item| items.push(item));
                     decorator_items.extend(items.into_iter()
                         .flat_map(|item| expand_item(item, fld).into_iter()));
 
@@ -470,7 +470,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
 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) = it.attrs.partitioned(|attr| {
+    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
@@ -1660,7 +1660,7 @@ mod test {
             assert!((shouldmatch.len() == 0) ||
                     (varrefs.len() > *shouldmatch.iter().max().unwrap()));
             for (idx,varref) in varrefs.iter().enumerate() {
-                let print_hygiene_debug_info = || {
+                let print_hygiene_debug_info = |&:| {
                     // good lord, you can't make a path with 0 segments, can you?
                     let final_varref_ident = match varref.segments.last() {
                         Some(pathsegment) => pathsegment.identifier,
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 6474d92953f..500070a14d2 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -22,6 +22,7 @@ use parse::token;
 use ptr::P;
 
 use std::collections::HashMap;
+use std::iter::repeat;
 
 #[deriving(PartialEq)]
 enum ArgumentType {
@@ -477,7 +478,7 @@ impl<'a, 'b> Context<'a, 'b> {
     /// to
     fn into_expr(mut self) -> P<ast::Expr> {
         let mut locals = Vec::new();
-        let mut names = Vec::from_fn(self.name_positions.len(), |_| None);
+        let mut names: Vec<_> = repeat(None).take(self.name_positions.len()).collect();
         let mut pats = Vec::new();
         let mut heads = Vec::new();
 
@@ -664,7 +665,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
                                     name_ordering: Vec<String>,
                                     names: HashMap<String, P<ast::Expr>>)
                                     -> P<ast::Expr> {
-    let arg_types = Vec::from_fn(args.len(), |_| None);
+    let arg_types: Vec<_> = range(0, args.len()).map(|_| None).collect();
     let mut cx = Context {
         ecx: ecx,
         args: args,
@@ -707,13 +708,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
             None => break
         }
     }
-    match parser.errors.remove(0) {
-        Some(error) => {
-            cx.ecx.span_err(cx.fmtsp,
-                            format!("invalid format string: {}", error)[]);
-            return DummyResult::raw_expr(sp);
-        }
-        None => {}
+    if !parser.errors.is_empty() {
+        cx.ecx.span_err(cx.fmtsp, format!("invalid format string: {}",
+                                          parser.errors.remove(0))[]);
+        return DummyResult::raw_expr(sp);
     }
     if !cx.literal.is_empty() {
         let s = cx.trans_literal_string();
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 4aadc78babd..e46bd7ac4bc 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -799,11 +799,11 @@ fn expand_parse_call(cx: &ExtCtxt,
                      tts: &[ast::TokenTree]) -> P<ast::Expr> {
     let (cx_expr, tts_expr) = expand_tts(cx, sp, tts);
 
-    let cfg_call = || cx.expr_method_call(
+    let cfg_call = |&:| cx.expr_method_call(
         sp, cx.expr_ident(sp, id_ext("ext_cx")),
         id_ext("cfg"), Vec::new());
 
-    let parse_sess_call = || cx.expr_method_call(
+    let parse_sess_call = |&:| cx.expr_method_call(
         sp, cx.expr_ident(sp, id_ext("ext_cx")),
         id_ext("parse_sess"), Vec::new());
 
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 73ef18b8449..65ecf701e8d 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -166,7 +166,7 @@ pub fn count_names(ms: &[TokenTree]) -> uint {
 pub fn initial_matcher_pos(ms: Rc<Vec<TokenTree>>, sep: Option<Token>, lo: BytePos)
                            -> Box<MatcherPos> {
     let match_idx_hi = count_names(ms[]);
-    let matches = Vec::from_fn(match_idx_hi, |_i| Vec::new());
+    let matches: Vec<_> = range(0, match_idx_hi).map(|_| Vec::new()).collect();
     box MatcherPos {
         stack: vec![],
         top_elts: TtSeq(ms),
@@ -392,7 +392,8 @@ pub fn parse(sess: &ParseSess,
                             cur_eis.push(new_ei);
                         }
 
-                        let matches = Vec::from_elem(ei.matches.len(), Vec::new());
+                        let matches: Vec<_> = range(0, ei.matches.len())
+                            .map(|_| Vec::new()).collect();
                         let ei_t = ei;
                         cur_eis.push(box MatcherPos {
                             stack: vec![],
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 28f7a78ddd0..b2c2d7eb626 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -24,7 +24,7 @@ use ast::NodeId;
 use ast;
 use attr;
 use attr::AttrMetaMethods;
-use codemap::Span;
+use codemap::{CodeMap, Span};
 use diagnostic::SpanHandler;
 use visit;
 use visit::Visitor;
@@ -127,6 +127,7 @@ impl Features {
 struct Context<'a> {
     features: Vec<&'static str>,
     span_handler: &'a SpanHandler,
+    cm: &'a CodeMap,
 }
 
 impl<'a> Context<'a> {
@@ -144,7 +145,71 @@ impl<'a> Context<'a> {
     }
 }
 
-impl<'a, 'v> Visitor<'v> for Context<'a> {
+struct MacroVisitor<'a> {
+    context: &'a Context<'a>
+}
+
+impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
+    fn visit_view_item(&mut self, i: &ast::ViewItem) {
+        match i.node {
+            ast::ViewItemExternCrate(..) => {
+                for attr in i.attrs.iter() {
+                    if attr.name().get() == "phase"{
+                        self.context.gate_feature("phase", attr.span,
+                                          "compile time crate loading is \
+                                           experimental and possibly buggy");
+                    }
+                }
+            },
+            _ => { }
+        }
+        visit::walk_view_item(self, i)
+    }
+
+    fn visit_mac(&mut self, macro: &ast::Mac) {
+        let ast::MacInvocTT(ref path, _, _) = macro.node;
+        let id = path.segments.last().unwrap().identifier;
+
+        if id == token::str_to_ident("macro_rules") {
+            self.context.gate_feature("macro_rules", path.span, "macro definitions are \
+                not stable enough for use and are subject to change");
+        }
+
+        else if id == token::str_to_ident("asm") {
+            self.context.gate_feature("asm", path.span, "inline assembly is not \
+                stable enough for use and is subject to change");
+        }
+
+        else if id == token::str_to_ident("log_syntax") {
+            self.context.gate_feature("log_syntax", path.span, "`log_syntax!` is not \
+                stable enough for use and is subject to change");
+        }
+
+        else if id == token::str_to_ident("trace_macros") {
+            self.context.gate_feature("trace_macros", path.span, "`trace_macros` is not \
+                stable enough for use and is subject to change");
+        }
+
+        else if id == token::str_to_ident("concat_idents") {
+            self.context.gate_feature("concat_idents", path.span, "`concat_idents` is not \
+                stable enough for use and is subject to change");
+        }
+    }
+}
+
+struct PostExpansionVisitor<'a> {
+    context: &'a Context<'a>
+}
+
+impl<'a> PostExpansionVisitor<'a> {
+    fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
+        if !self.context.cm.span_is_internal(span) {
+            self.context.gate_feature(feature, span, explain)
+        }
+    }
+}
+
+impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
     fn visit_name(&mut self, sp: Span, name: ast::Name) {
         if !token::get_name(name).get().is_ascii() {
             self.gate_feature("non_ascii_idents", sp,
@@ -217,7 +282,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
             }
 
             ast::ItemImpl(_, _, _, _, ref items) => {
-                if attr::contains_name(i.attrs.as_slice(),
+                if attr::contains_name(i.attrs[],
                                        "unsafe_destructor") {
                     self.gate_feature("unsafe_destructor",
                                       i.span,
@@ -256,36 +321,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
         }
     }
 
-    fn visit_mac(&mut self, macro: &ast::Mac) {
-        let ast::MacInvocTT(ref path, _, _) = macro.node;
-        let id = path.segments.last().unwrap().identifier;
-
-        if id == token::str_to_ident("macro_rules") {
-            self.gate_feature("macro_rules", path.span, "macro definitions are \
-                not stable enough for use and are subject to change");
-        }
-
-        else if id == token::str_to_ident("asm") {
-            self.gate_feature("asm", path.span, "inline assembly is not \
-                stable enough for use and is subject to change");
-        }
-
-        else if id == token::str_to_ident("log_syntax") {
-            self.gate_feature("log_syntax", path.span, "`log_syntax!` is not \
-                stable enough for use and is subject to change");
-        }
-
-        else if id == token::str_to_ident("trace_macros") {
-            self.gate_feature("trace_macros", path.span, "`trace_macros` is not \
-                stable enough for use and is subject to change");
-        }
-
-        else if id == token::str_to_ident("concat_idents") {
-            self.gate_feature("concat_idents", path.span, "`concat_idents` is not \
-                stable enough for use and is subject to change");
-        }
-    }
-
     fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
         if attr::contains_name(i.attrs[], "linkage") {
             self.gate_feature("linkage", i.span,
@@ -307,10 +342,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
 
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprSlice(..) => {
+            ast::ExprRange(..) => {
                 self.gate_feature("slicing_syntax",
                                   e.span,
-                                  "slicing syntax is experimental");
+                                  "range syntax is experimental");
             }
             _ => {}
         }
@@ -371,10 +406,15 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
     }
 }
 
-pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, Vec<Span>) {
+fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate,
+                        check: F)
+                       -> (Features, Vec<Span>)
+    where F: FnOnce(&mut Context, &ast::Crate)
+{
     let mut cx = Context {
         features: Vec::new(),
         span_handler: span_handler,
+        cm: cm,
     };
 
     let mut unknown_features = Vec::new();
@@ -419,7 +459,7 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features,
         }
     }
 
-    visit::walk_crate(&mut cx, krate);
+    check(&mut cx, krate);
 
     (Features {
         default_type_params: cx.has_feature("default_type_params"),
@@ -432,3 +472,16 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features,
     },
     unknown_features)
 }
+
+pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
+-> (Features, Vec<Span>) {
+    check_crate_inner(cm, span_handler, krate,
+                      |ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate))
+}
+
+pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
+-> (Features, Vec<Span>) {
+    check_crate_inner(cm, span_handler, krate,
+                      |ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx },
+                                                     krate))
+}
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index c58901701f5..4f0169e31f2 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -736,18 +736,17 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
                                    -> TyParamBound
                                    where T: Folder {
     match tpb {
-        TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_poly_trait_ref(ty)),
+        TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
         RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
     }
 }
 
 pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
-    let TyParam {id, ident, bounds, unbound, default, span} = tp;
+    let TyParam {id, ident, bounds, default, span} = tp;
     TyParam {
         id: fld.new_id(id),
         ident: ident,
         bounds: fld.fold_bounds(bounds),
-        unbound: unbound.map(|x| fld.fold_trait_ref(x)),
         default: default.map(|x| fld.fold_ty(x)),
         span: span
     }
@@ -1043,7 +1042,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
                      folder.fold_ty(ty),
                      new_impl_items)
         }
-        ItemTrait(unsafety, generics, unbound, bounds, methods) => {
+        ItemTrait(unsafety, generics, bounds, methods) => {
             let bounds = folder.fold_bounds(bounds);
             let methods = methods.into_iter().flat_map(|method| {
                 let r = match method {
@@ -1073,7 +1072,6 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             }).collect();
             ItemTrait(unsafety,
                       folder.fold_generics(generics),
-                      unbound,
                       bounds,
                       methods)
         }
@@ -1384,14 +1382,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
             ExprIndex(el, er) => {
                 ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
             }
-            ExprSlice(e, e1, e2, m) => {
-                ExprSlice(folder.fold_expr(e),
-                          e1.map(|x| folder.fold_expr(x)),
-                          e2.map(|x| folder.fold_expr(x)),
-                          m)
-            }
             ExprRange(e1, e2) => {
-                ExprRange(folder.fold_expr(e1),
+                ExprRange(e1.map(|x| folder.fold_expr(x)),
                           e2.map(|x| folder.fold_expr(x)))
             }
             ExprPath(pth) => ExprPath(folder.fold_path(pth)),
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 8cefb111fd1..88c485a07ac 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -240,7 +240,7 @@ pub fn new_parser_from_tts<'a>(sess: &'a ParseSess,
 /// add the path to the session's codemap and return the new filemap.
 pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
     -> Rc<FileMap> {
-    let err = |msg: &str| {
+    let err = |&: msg: &str| {
         match spanopt {
             Some(sp) => sess.span_diagnostic.span_fatal(sp, msg),
             None => sess.span_diagnostic.handler().fatal(msg),
@@ -399,7 +399,7 @@ pub fn char_lit(lit: &str) -> (char, int) {
         .map(|x| (x, len as int))
     }
 
-    let unicode_escape: || -> Option<(char, int)> = ||
+    let unicode_escape = |&: | -> Option<(char, int)>
         if lit.as_bytes()[2] == b'{' {
             let idx = lit.find('}').expect(msg2);
             let subslice = lit[3..idx];
@@ -426,7 +426,7 @@ pub fn str_lit(lit: &str) -> String {
     let mut res = String::with_capacity(lit.len());
 
     // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
-    let error = |i| format!("lexer should have rejected {} at {}", lit, i);
+    let error = |&: i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
     fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharIndices<'a>>) {
@@ -561,7 +561,7 @@ pub fn float_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> a
 
 /// Parse a string representing a byte literal into its final form. Similar to `char_lit`
 pub fn byte_lit(lit: &str) -> (u8, uint) {
-    let err = |i| format!("lexer accepted invalid byte literal {} step {}", lit, i);
+    let err = |&: i| format!("lexer accepted invalid byte literal {} step {}", lit, i);
 
     if lit.len() == 1 {
         (lit.as_bytes()[0], 1)
@@ -595,7 +595,7 @@ pub fn binary_lit(lit: &str) -> Rc<Vec<u8>> {
     let mut res = Vec::with_capacity(lit.len());
 
     // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
-    let error = |i| format!("lexer should have rejected {} at {}", lit, i);
+    let error = |&: i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
     fn eat<'a, I: Iterator<(uint, u8)>>(it: &mut iter::Peekable<(uint, u8), I>) {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7b40ae85c7d..832b112921e 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -15,7 +15,7 @@ use self::ItemOrViewItem::*;
 
 use abi;
 use ast::{AssociatedType, BareFnTy, ClosureTy};
-use ast::{RegionTyParamBound, TraitTyParamBound};
+use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{ProvidedMethod, Public, Unsafety};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block};
@@ -25,7 +25,7 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit
 use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
 use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
 use ast::{ExprBreak, ExprCall, ExprCast};
-use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice};
+use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
 use ast::{ExprMethodCall, ExprParen, ExprPath};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
@@ -66,7 +66,7 @@ use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
 use ast;
 use ast_util::{mod, as_prec, ident_to_path, operator_prec};
-use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp};
+use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp, DUMMY_SP};
 use diagnostic;
 use ext::tt::macro_parser;
 use parse;
@@ -118,6 +118,13 @@ pub enum PathParsingMode {
     LifetimeAndTypesWithColons,
 }
 
+/// How to parse a bound, whether to allow bound modifiers such as `?`.
+#[deriving(Copy, PartialEq)]
+pub enum BoundParsingMode {
+    Bare,
+    Modified,
+}
+
 enum ItemOrViewItem {
     /// Indicates a failure to parse any kind of item. The attributes are
     /// returned.
@@ -286,7 +293,7 @@ pub struct Parser<'a> {
     pub cfg: CrateConfig,
     /// the previous token or None (only stashed sometimes).
     pub last_token: Option<Box<token::Token>>,
-    pub buffer: [TokenAndSpan, ..4],
+    pub buffer: [TokenAndSpan; 4],
     pub buffer_start: int,
     pub buffer_end: int,
     pub tokens_consumed: uint,
@@ -1088,12 +1095,12 @@ impl<'a> Parser<'a> {
             let poly_trait_ref = ast::PolyTraitRef { bound_lifetimes: lifetime_defs,
                                                      trait_ref: trait_ref };
             let other_bounds = if self.eat(&token::BinOp(token::Plus)) {
-                self.parse_ty_param_bounds()
+                self.parse_ty_param_bounds(BoundParsingMode::Bare)
             } else {
                 OwnedSlice::empty()
             };
             let all_bounds =
-                Some(TraitTyParamBound(poly_trait_ref)).into_iter()
+                Some(TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)).into_iter()
                 .chain(other_bounds.into_vec().into_iter())
                 .collect();
             ast::TyPolyTraitRef(all_bounds)
@@ -1166,7 +1173,7 @@ impl<'a> Parser<'a> {
         // To be helpful, parse the proc as ever
         let _ = self.parse_legacy_lifetime_defs(lifetime_defs);
         let _ = self.parse_fn_args(false, false);
-        let _ = self.parse_colon_then_ty_param_bounds();
+        let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
         let _ = self.parse_ret_ty();
 
         self.obsolete(proc_span, ObsoleteProcType);
@@ -1256,7 +1263,7 @@ impl<'a> Parser<'a> {
             inputs
         };
 
-        let bounds = self.parse_colon_then_ty_param_bounds();
+        let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
 
         let output = self.parse_ret_ty();
         let decl = P(FnDecl {
@@ -1482,7 +1489,7 @@ impl<'a> Parser<'a> {
             return lhs;
         }
 
-        let bounds = self.parse_ty_param_bounds();
+        let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare);
 
         // In type grammar, `+` is treated like a binary operator,
         // and hence both L and R side are required.
@@ -1710,12 +1717,7 @@ impl<'a> Parser<'a> {
     }
 
     pub fn maybe_parse_fixed_length_of_vec(&mut self) -> Option<P<ast::Expr>> {
-        if self.check(&token::Comma) &&
-                self.look_ahead(1, |t| *t == token::DotDot) {
-            self.bump();
-            self.bump();
-            Some(self.parse_expr_res(RESTRICTION_NO_DOTS))
-        } else if self.check(&token::Semi) {
+        if self.check(&token::Semi) {
             self.bump();
             Some(self.parse_expr())
         } else {
@@ -2136,13 +2138,20 @@ impl<'a> Parser<'a> {
                     expr: P<Expr>,
                     start: Option<P<Expr>>,
                     end: Option<P<Expr>>,
-                    mutbl: Mutability)
+                    _mutbl: Mutability)
                     -> ast::Expr_ {
-        ExprSlice(expr, start, end, mutbl)
+        // FIXME: we could give more accurate span info here.
+        let (lo, hi) = match (&start, &end) {
+            (&Some(ref s), &Some(ref e)) => (s.span.lo, e.span.hi),
+            (&Some(ref s), &None) => (s.span.lo, s.span.hi),
+            (&None, &Some(ref e)) => (e.span.lo, e.span.hi),
+            (&None, &None) => (DUMMY_SP.lo, DUMMY_SP.hi),
+        };
+        ExprIndex(expr, self.mk_expr(lo, hi, ExprRange(start, end)))
     }
 
     pub fn mk_range(&mut self,
-                    start: P<Expr>,
+                    start: Option<P<Expr>>,
                     end: Option<P<Expr>>)
                     -> ast::Expr_ {
         ExprRange(start, end)
@@ -2264,15 +2273,7 @@ impl<'a> Parser<'a> {
                 } else {
                     // Nonempty vector.
                     let first_expr = self.parse_expr();
-                    if self.check(&token::Comma) &&
-                        self.look_ahead(1, |t| *t == token::DotDot) {
-                        // Repeating vector syntax: [ 0, ..512 ]
-                        self.bump();
-                        self.bump();
-                        let count = self.parse_expr();
-                        self.expect(&token::CloseDelim(token::Bracket));
-                        ex = ExprRepeat(first_expr, count);
-                    } else if self.check(&token::Semi) {
+                    if self.check(&token::Semi) {
                         // Repeating vector syntax: [ 0; 512 ]
                         self.bump();
                         let count = self.parse_expr();
@@ -2676,7 +2677,7 @@ impl<'a> Parser<'a> {
                 };
 
                 let hi = self.span.hi;
-                let range = self.mk_range(e, opt_end);
+                let range = self.mk_range(Some(e), opt_end);
                 return self.mk_expr(lo, hi, range);
               }
               _ => return e
@@ -2889,6 +2890,13 @@ impl<'a> Parser<'a> {
             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();
+            let e = self.parse_prefix_expr();
+            hi = e.span.hi;
+            ex = self.mk_range(None, Some(e));
+          }
           token::Ident(_, _) => {
             if !self.token.is_keyword(keywords::Box) {
                 return self.parse_dot_or_call_expr();
@@ -4023,13 +4031,14 @@ impl<'a> Parser<'a> {
 
     // Parses a sequence of bounds if a `:` is found,
     // otherwise returns empty list.
-    fn parse_colon_then_ty_param_bounds(&mut self)
+    fn parse_colon_then_ty_param_bounds(&mut self,
+                                        mode: BoundParsingMode)
                                         -> OwnedSlice<TyParamBound>
     {
         if !self.eat(&token::Colon) {
             OwnedSlice::empty()
         } else {
-            self.parse_ty_param_bounds()
+            self.parse_ty_param_bounds(mode)
         }
     }
 
@@ -4037,14 +4046,20 @@ impl<'a> Parser<'a> {
     // where   boundseq  = ( polybound + boundseq ) | polybound
     // and     polybound = ( 'for' '<' 'region '>' )? bound
     // and     bound     = 'region | trait_ref
-    // NB: The None/Some distinction is important for issue #7264.
-    fn parse_ty_param_bounds(&mut self)
+    fn parse_ty_param_bounds(&mut self,
+                             mode: BoundParsingMode)
                              -> OwnedSlice<TyParamBound>
     {
         let mut result = vec!();
         loop {
+            let question_span = self.span;
+            let ate_question = self.eat(&token::Question);
             match self.token {
                 token::Lifetime(lifetime) => {
+                    if ate_question {
+                        self.span_err(question_span,
+                                      "`?` may only modify trait bounds, not lifetime bounds");
+                    }
                     result.push(RegionTyParamBound(ast::Lifetime {
                         id: ast::DUMMY_NODE_ID,
                         span: self.span,
@@ -4054,7 +4069,18 @@ impl<'a> Parser<'a> {
                 }
                 token::ModSep | token::Ident(..) => {
                     let poly_trait_ref = self.parse_poly_trait_ref();
-                    result.push(TraitTyParamBound(poly_trait_ref))
+                    let modifier = if ate_question {
+                        if mode == BoundParsingMode::Modified {
+                            TraitBoundModifier::Maybe
+                        } else {
+                            self.span_err(question_span,
+                                          "unexpected `?`");
+                            TraitBoundModifier::None
+                        }
+                    } else {
+                        TraitBoundModifier::None
+                    };
+                    result.push(TraitTyParamBound(poly_trait_ref, modifier))
                 }
                 _ => break,
             }
@@ -4083,13 +4109,14 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Matches typaram = (unbound`?`)? IDENT optbounds ( EQ ty )?
+    /// Matches typaram = (unbound `?`)? IDENT (`?` unbound)? optbounds ( EQ ty )?
     fn parse_ty_param(&mut self) -> TyParam {
         // This is a bit hacky. Currently we are only interested in a single
         // unbound, and it may only be `Sized`. To avoid backtracking and other
         // complications, we parse an ident, then check for `?`. If we find it,
         // we use the ident as the unbound, otherwise, we use it as the name of
-        // type param.
+        // type param. Even worse, for now, we need to check for `?` before or
+        // after the bound.
         let mut span = self.span;
         let mut ident = self.parse_ident();
         let mut unbound = None;
@@ -4100,7 +4127,14 @@ impl<'a> Parser<'a> {
             ident = self.parse_ident();
         }
 
-        let bounds = self.parse_colon_then_ty_param_bounds();
+        let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Modified);
+        if let Some(unbound) = unbound {
+            let mut bounds_as_vec = bounds.into_vec();
+            bounds_as_vec.push(TraitTyParamBound(PolyTraitRef { bound_lifetimes: vec![],
+                                                                trait_ref: unbound },
+                                                 TraitBoundModifier::Maybe));
+            bounds = OwnedSlice::from_vec(bounds_as_vec);
+        };
 
         let default = if self.check(&token::Eq) {
             self.bump();
@@ -4112,7 +4146,6 @@ impl<'a> Parser<'a> {
             ident: ident,
             id: ast::DUMMY_NODE_ID,
             bounds: bounds,
-            unbound: unbound,
             default: default,
             span: span,
         }
@@ -4254,7 +4287,7 @@ impl<'a> Parser<'a> {
                     let bounded_ty = self.parse_ty();
 
                     if self.eat(&token::Colon) {
-                        let bounds = self.parse_ty_param_bounds();
+                        let bounds = self.parse_ty_param_bounds(BoundParsingMode::Bare);
                         let hi = self.span.hi;
                         let span = mk_sp(lo, hi);
 
@@ -4741,15 +4774,23 @@ impl<'a> Parser<'a> {
     fn parse_item_trait(&mut self, unsafety: Unsafety) -> ItemInfo {
         let ident = self.parse_ident();
         let mut tps = self.parse_generics();
-        let sized = self.parse_for_sized();
+        let unbound = self.parse_for_sized();
 
         // Parse supertrait bounds.
-        let bounds = self.parse_colon_then_ty_param_bounds();
+        let mut bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
+
+        if let Some(unbound) = unbound {
+            let mut bounds_as_vec = bounds.into_vec();
+            bounds_as_vec.push(TraitTyParamBound(PolyTraitRef { bound_lifetimes: vec![],
+                                                                trait_ref: unbound },
+                                                 TraitBoundModifier::Maybe));
+            bounds = OwnedSlice::from_vec(bounds_as_vec);
+        };
 
         self.parse_where_clause(&mut tps);
 
         let meths = self.parse_trait_items();
-        (ident, ItemTrait(unsafety, tps, sized, bounds, meths), None)
+        (ident, ItemTrait(unsafety, tps, bounds, meths), None)
     }
 
     fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
@@ -4968,12 +5009,25 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_for_sized(&mut self) -> Option<ast::TraitRef> {
+        // FIXME, this should really use TraitBoundModifier, but it will get
+        // re-jigged shortly in any case, so leaving the hacky version for now.
         if self.eat_keyword(keywords::For) {
             let span = self.span;
+            let mut ate_question = false;
+            if self.eat(&token::Question) {
+                ate_question = true;
+            }
             let ident = self.parse_ident();
-            if !self.eat(&token::Question) {
+            if self.eat(&token::Question) {
+                if ate_question {
+                    self.span_err(span,
+                        "unexpected `?`");
+                }
+                ate_question = true;
+            }
+            if !ate_question {
                 self.span_err(span,
-                    "expected 'Sized?' after `for` in trait item");
+                    "expected `?Sized` after `for` in trait item");
                 return None;
             }
             let tref = Parser::trait_ref_from_ident(ident, span);
@@ -5918,7 +5972,7 @@ impl<'a> Parser<'a> {
     }
 
 
-    /// Matches view_path : MOD? IDENT EQ non_global_path
+    /// Matches view_path : MOD? non_global_path as IDENT
     /// | MOD? non_global_path MOD_SEP LBRACE RBRACE
     /// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
     /// | MOD? non_global_path MOD_SEP STAR
@@ -6030,7 +6084,7 @@ impl<'a> Parser<'a> {
         }
         let mut rename_to = path[path.len() - 1u];
         let path = ast::Path {
-            span: mk_sp(lo, self.span.hi),
+            span: mk_sp(lo, self.last_span.hi),
             global: false,
             segments: path.into_iter().map(|identifier| {
                 ast::PathSegment {
@@ -6042,7 +6096,8 @@ impl<'a> Parser<'a> {
         if self.eat_keyword(keywords::As) {
             rename_to = self.parse_ident()
         }
-        P(spanned(lo, self.last_span.hi,
+        P(spanned(lo,
+                  self.last_span.hi,
                   ViewPathSimple(rename_to, path, ast::DUMMY_NODE_ID)))
     }
 
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index dbc0cef8340..9c6644c5204 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -726,7 +726,7 @@ pub fn fresh_name(src: &ast::Ident) -> ast::Name {
     // following: debug version. Could work in final except that it's incompatible with
     // good error messages and uses of struct names in ambiguous could-be-binding
     // locations. Also definitely destroys the guarantee given above about ptr_eq.
-    /*let num = rand::task_rng().gen_uint_range(0,0xffff);
+    /*let num = rand::thread_rng().gen_uint_range(0,0xffff);
     gensym(format!("{}_{}",ident_to_string(src),num))*/
 }
 
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index ab0e0f9585c..a15f1ca354b 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -65,6 +65,7 @@ pub use self::Token::*;
 
 use std::io;
 use std::string;
+use std::iter::repeat;
 
 #[deriving(Clone, Copy, PartialEq)]
 pub enum Breaks {
@@ -166,9 +167,9 @@ 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> = Vec::from_elem(n, Eof);
-    let size: Vec<int> = Vec::from_elem(n, 0i);
-    let scan_stack: Vec<uint> = Vec::from_elem(n, 0u);
+    let token: Vec<Token> = repeat(Eof).take(n).collect();
+    let size: Vec<int> = repeat(0i).take(n).collect();
+    let scan_stack: Vec<uint> = repeat(0u).take(n).collect();
     Printer {
         out: out,
         buf_len: n,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 623f20bccd2..02a03285d3b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -13,7 +13,7 @@ pub use self::AnnNode::*;
 use abi;
 use ast::{mod, FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
-use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound};
+use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem};
 use ast::{UnboxedClosureKind};
 use ast_util;
@@ -958,20 +958,25 @@ impl<'a> State<'a> {
                 }
                 try!(self.bclose(item.span));
             }
-            ast::ItemTrait(unsafety, ref generics, ref unbound, ref bounds, ref methods) => {
+            ast::ItemTrait(unsafety, ref generics, ref bounds, ref methods) => {
                 try!(self.head(""));
                 try!(self.print_visibility(item.vis));
                 try!(self.print_unsafety(unsafety));
                 try!(self.word_nbsp("trait"));
                 try!(self.print_ident(item.ident));
                 try!(self.print_generics(generics));
-                if let &Some(ref tref) = unbound {
-                    try!(space(&mut self.s));
-                    try!(self.word_space("for"));
-                    try!(self.print_trait_ref(tref));
-                    try!(word(&mut self.s, "?"));
+                let bounds: Vec<_> = bounds.iter().map(|b| b.clone()).collect();
+                let mut real_bounds = Vec::with_capacity(bounds.len());
+                for b in bounds.into_iter() {
+                    if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = b {
+                        try!(space(&mut self.s));
+                        try!(self.word_space("for ?"));
+                        try!(self.print_trait_ref(&ptr.trait_ref));
+                    } else {
+                        real_bounds.push(b);
+                    }
                 }
-                try!(self.print_bounds(":", bounds[]));
+                try!(self.print_bounds(":", real_bounds[]));
                 try!(self.print_where_clause(generics));
                 try!(word(&mut self.s, " "));
                 try!(self.bopen());
@@ -1739,15 +1744,7 @@ impl<'a> State<'a> {
                 try!(self.print_expr(&**index));
                 try!(word(&mut self.s, "]"));
             }
-            ast::ExprSlice(ref e, ref start, ref end, ref mutbl) => {
-                try!(self.print_expr(&**e));
-                try!(word(&mut self.s, "["));
-                if mutbl == &ast::MutMutable {
-                    try!(word(&mut self.s, "mut"));
-                    if start.is_some() || end.is_some() {
-                        try!(space(&mut self.s));
-                    }
-                }
+            ast::ExprRange(ref start, ref end) => {
                 if let &Some(ref e) = start {
                     try!(self.print_expr(&**e));
                 }
@@ -1757,14 +1754,6 @@ impl<'a> State<'a> {
                 if let &Some(ref e) = end {
                     try!(self.print_expr(&**e));
                 }
-                try!(word(&mut self.s, "]"));
-            }
-            ast::ExprRange(ref start, ref end) => {
-                try!(self.print_expr(&**start));
-                try!(word(&mut self.s, ".."));
-                if let &Some(ref e) = end {
-                    try!(self.print_expr(&**e));
-                }
             }
             ast::ExprPath(ref path) => try!(self.print_path(path, true)),
             ast::ExprBreak(opt_ident) => {
@@ -2361,7 +2350,11 @@ impl<'a> State<'a> {
                 }
 
                 try!(match *bound {
-                    TraitTyParamBound(ref tref) => {
+                    TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
+                        self.print_poly_trait_ref(tref)
+                    }
+                    TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
+                        try!(word(&mut self.s, "?"));
                         self.print_poly_trait_ref(tref)
                     }
                     RegionTyParamBound(ref lt) => {
@@ -2428,10 +2421,6 @@ impl<'a> State<'a> {
     }
 
     pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
-        if let Some(ref tref) = param.unbound {
-            try!(self.print_trait_ref(tref));
-            try!(self.word_space("?"));
-        }
         try!(self.print_ident(param.ident));
         try!(self.print_bounds(":", param.bounds[]));
         match param.default {
diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs
index 0d89403ab6c..5a4d0cc3bd8 100644
--- a/src/libsyntax/std_inject.rs
+++ b/src/libsyntax/std_inject.rs
@@ -168,7 +168,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
             ],
         };
 
-        let (crates, uses) = view_items.partitioned(|x| {
+        let (crates, uses): (Vec<_>, _) = view_items.iter().cloned().partition(|x| {
             match x.node {
                 ast::ViewItemExternCrate(..) => true,
                 _ => false,
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index bc7dda8c44a..93fe868f52c 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -545,11 +545,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     let test_id = ecx.ident_of("test");
 
     // creates self::test::$name
-    let test_path = |name| {
+    let test_path = |&: name| {
         ecx.path(span, vec![self_id, test_id, ecx.ident_of(name)])
     };
     // creates $name: $expr
-    let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
+    let field = |&: name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
 
     debug!("encoding {}", ast_util::path_name_i(path[]));
 
@@ -563,7 +563,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
                                   vec![name_expr]);
 
     let ignore_expr = ecx.expr_bool(span, test.ignore);
-    let should_fail_path = |name| {
+    let should_fail_path = |&: name| {
         ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldFail"), ecx.ident_of(name)])
     };
     let fail_expr = match test.should_fail {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 714339d0f0a..40ca6354ca6 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -85,8 +85,8 @@ pub trait Visitor<'v> {
     fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
         walk_ty_param_bound(self, bounds)
     }
-    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef) {
-        walk_poly_trait_ref(self, t)
+    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
+        walk_poly_trait_ref(self, t, m)
     }
     fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
         walk_struct_def(self, s)
@@ -133,6 +133,9 @@ pub trait Visitor<'v> {
     fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
         walk_path_parameters(self, path_span, path_parameters)
     }
+    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
+        walk_assoc_type_binding(self, type_binding)
+    }
     fn visit_attribute(&mut self, _attr: &'v Attribute) {}
 }
 
@@ -244,7 +247,8 @@ pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
 /// Like with walk_method_helper this doesn't correspond to a method
 /// in Visitor, and so it gets a _helper suffix.
 pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
-                                         trait_ref: &'v PolyTraitRef)
+                                  trait_ref: &'v PolyTraitRef,
+                                  _modifier: &'v TraitBoundModifier)
     where V: Visitor<'v>
 {
     walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
@@ -324,7 +328,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                                      generics,
                                      item.id)
         }
-        ItemTrait(_, ref generics, _, ref bounds, ref methods) => {
+        ItemTrait(_, ref generics, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
             walk_ty_param_bounds_helper(visitor, bounds);
             for method in methods.iter() {
@@ -466,6 +470,9 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
             for lifetime in data.lifetimes.iter() {
                 visitor.visit_lifetime_ref(lifetime);
             }
+            for binding in data.bindings.iter() {
+                visitor.visit_assoc_type_binding(&**binding);
+            }
         }
         ast::ParenthesizedParameters(ref data) => {
             for typ in data.inputs.iter() {
@@ -478,6 +485,12 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
     }
 }
 
+pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
+                                                   type_binding: &'v TypeBinding) {
+    visitor.visit_ident(type_binding.span, type_binding.ident);
+    visitor.visit_ty(&*type_binding.ty);
+}
+
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
     match pattern.node {
         PatEnum(ref path, ref children) => {
@@ -558,8 +571,8 @@ pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
                                                bound: &'v TyParamBound) {
     match *bound {
-        TraitTyParamBound(ref typ) => {
-            visitor.visit_poly_trait_ref(typ);
+        TraitTyParamBound(ref typ, ref modifier) => {
+            visitor.visit_poly_trait_ref(typ, modifier);
         }
         RegionTyParamBound(ref lifetime) => {
             visitor.visit_lifetime_bound(lifetime);
@@ -866,13 +879,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(&**main_expression);
             visitor.visit_expr(&**index_expression)
         }
-        ExprSlice(ref main_expression, ref start, ref end, _) => {
-            visitor.visit_expr(&**main_expression);
-            walk_expr_opt(visitor, start);
-            walk_expr_opt(visitor, end)
-        }
         ExprRange(ref start, ref end) => {
-            visitor.visit_expr(&**start);
+            walk_expr_opt(visitor, start);
             walk_expr_opt(visitor, end)
         }
         ExprPath(ref path) => {
diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs
index a4ebcfe8a56..420b1100ec1 100644
--- a/src/libterm/lib.rs
+++ b/src/libterm/lib.rs
@@ -39,7 +39,7 @@
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
 #![crate_name = "term"]
-#![experimental]
+#![experimental = "use the crates.io `term` library instead"]
 #![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/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs
index bac2452524e..35d1e166e9c 100644
--- a/src/libterm/terminfo/parm.rs
+++ b/src/libterm/terminfo/parm.rs
@@ -16,6 +16,7 @@ use self::FormatState::*;
 use self::FormatOp::*;
 use std::ascii::OwnedAsciiExt;
 use std::mem::replace;
+use std::iter::repeat;
 
 #[deriving(Copy, PartialEq)]
 enum States {
@@ -52,9 +53,9 @@ pub enum Param {
 /// Container for static and dynamic variable arrays
 pub struct Variables {
     /// Static variables A-Z
-    sta: [Param, ..26],
+    sta: [Param; 26],
     /// Dynamic variables a-z
-    dyn: [Param, ..26]
+    dyn: [Param; 26]
 }
 
 impl Variables {
@@ -508,7 +509,7 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8> ,String> {
             if flags.precision > s.len() {
                 let mut s_ = Vec::with_capacity(flags.precision);
                 let n = flags.precision - s.len();
-                s_.grow(n, b'0');
+                s_.extend(repeat(b'0').take(n));
                 s_.extend(s.into_iter());
                 s = s_;
             }
@@ -560,10 +561,10 @@ fn format(val: Param, op: FormatOp, flags: Flags) -> Result<Vec<u8> ,String> {
     if flags.width > s.len() {
         let n = flags.width - s.len();
         if flags.left {
-            s.grow(n, b' ');
+            s.extend(repeat(b' ').take(n));
         } else {
             let mut s_ = Vec::with_capacity(flags.width);
-            s_.grow(n, b' ');
+            s_.extend(repeat(b' ').take(n));
             s_.extend(s.into_iter());
             s = s_;
         }
diff --git a/src/libterm/win.rs b/src/libterm/win.rs
index 9a67ee8836b..3130ad0af3f 100644
--- a/src/libterm/win.rs
+++ b/src/libterm/win.rs
@@ -32,11 +32,11 @@ pub struct WinConsole<T> {
 #[allow(non_snake_case)]
 #[repr(C)]
 struct CONSOLE_SCREEN_BUFFER_INFO {
-    dwSize: [libc::c_short, ..2],
-    dwCursorPosition: [libc::c_short, ..2],
+    dwSize: [libc::c_short; 2],
+    dwCursorPosition: [libc::c_short; 2],
     wAttributes: libc::WORD,
-    srWindow: [libc::c_short, ..4],
-    dwMaximumWindowSize: [libc::c_short, ..2],
+    srWindow: [libc::c_short; 4],
+    dwMaximumWindowSize: [libc::c_short; 2],
 }
 
 #[allow(non_snake_case)]
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs
index c70aa41c569..8af30cc668f 100644
--- a/src/libtest/lib.rs
+++ b/src/libtest/lib.rs
@@ -990,8 +990,8 @@ fn run_tests<F>(opts: &TestOpts,
 
     try!(callback(TeFiltered(filtered_descs)));
 
-    let (filtered_tests, filtered_benchs_and_metrics) =
-        filtered_tests.partition(|e| {
+    let (filtered_tests, filtered_benchs_and_metrics): (Vec<_>, _) =
+        filtered_tests.into_iter().partition(|e| {
             match e.testfn {
                 StaticTestFn(_) | DynTestFn(_) => true,
                 _ => false
@@ -1387,7 +1387,7 @@ impl Bencher {
         if n == 0 { n = 1; }
 
         let mut total_run = Duration::nanoseconds(0);
-        let samples : &mut [f64] = &mut [0.0_f64, ..50];
+        let samples : &mut [f64] = &mut [0.0_f64; 50];
         loop {
             let mut summ = None;
             let mut summ5 = None;
diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs
index 636e4ca83a8..a6d9a542a49 100644
--- a/src/libtime/lib.rs
+++ b/src/libtime/lib.rs
@@ -24,8 +24,6 @@
 
 #[cfg(test)] #[phase(plugin, link)] extern crate log;
 
-#[cfg(stage0)]
-extern crate serialize;
 extern crate "serialize" as rustc_serialize;
 extern crate libc;
 
@@ -597,7 +595,7 @@ impl<'a> fmt::Show for TmFmt<'a> {
         }
 
         fn parse_type(fmt: &mut fmt::Formatter, ch: char, tm: &Tm) -> fmt::Result {
-            let die = || {
+            let die = |&:| {
                 unreachable!()
             };
             match ch {
@@ -1275,6 +1273,7 @@ mod tests {
     #[cfg(windows)]
     fn set_time_zone() {
         use libc;
+        use std::c_str::ToCStr;
         // Windows crt doesn't see any environment variable set by
         // `SetEnvironmentVariable`, which `os::setenv` internally uses.
         // It is why we use `putenv` here.
diff --git a/src/libunicode/normalize.rs b/src/libunicode/normalize.rs
index d239cb82896..c6f86ccd9d4 100644
--- a/src/libunicode/normalize.rs
+++ b/src/libunicode/normalize.rs
@@ -11,35 +11,37 @@
 //! Functions for computing canonical and compatible decompositions for Unicode characters.
 
 use core::cmp::Ordering::{Equal, Less, Greater};
+use core::ops::FnMut;
 use core::option::Option;
 use core::option::Option::{Some, None};
-use core::slice;
 use core::slice::SliceExt;
+use core::result::Result::{Ok, Err};
 use tables::normalization::{canonical_table, compatibility_table, composition_table};
 
 fn bsearch_table<T>(c: char, r: &'static [(char, &'static [T])]) -> Option<&'static [T]> {
-    match r.binary_search(|&(val, _)| {
+    match r.binary_search_by(|&(val, _)| {
         if c == val { Equal }
         else if val < c { Less }
         else { Greater }
     }) {
-        slice::BinarySearchResult::Found(idx) => {
+        Ok(idx) => {
             let (_, result) = r[idx];
             Some(result)
         }
-        slice::BinarySearchResult::NotFound(_) => None
+        Err(_) => None
     }
 }
 
 /// Compute canonical Unicode decomposition for character
-pub fn decompose_canonical(c: char, i: |char|) { d(c, i, false); }
+pub fn decompose_canonical<F>(c: char, mut i: F) where F: FnMut(char) { d(c, &mut i, false); }
 
 /// Compute canonical or compatible Unicode decomposition for character
-pub fn decompose_compatible(c: char, i: |char|) { d(c, i, true); }
+pub fn decompose_compatible<F>(c: char, mut i: F) where F: FnMut(char) { d(c, &mut i, true); }
 
-fn d(c: char, i: |char|, k: bool) {
+// FIXME(#19596) This is a workaround, we should use `F` instead of `&mut F`
+fn d<F>(c: char, i: &mut F, k: bool) where F: FnMut(char) {
     // 7-bit ASCII never decomposes
-    if c <= '\x7f' { i(c); return; }
+    if c <= '\x7f' { (*i)(c); return; }
 
     // Perform decomposition for Hangul
     if (c as u32) >= S_BASE && (c as u32) < (S_BASE + S_COUNT) {
@@ -51,7 +53,7 @@ fn d(c: char, i: |char|, k: bool) {
     match bsearch_table(c, canonical_table) {
         Some(canon) => {
             for x in canon.iter() {
-                d(*x, |b| i(b), k);
+                d(*x, i, k);
             }
             return;
         }
@@ -59,13 +61,13 @@ fn d(c: char, i: |char|, k: bool) {
     }
 
     // Bottom out if we're not doing compat.
-    if !k { i(c); return; }
+    if !k { (*i)(c); return; }
 
     // Then check the compatibility decompositions
     match bsearch_table(c, compatibility_table) {
         Some(compat) => {
             for x in compat.iter() {
-                d(*x, |b| i(b), k);
+                d(*x, i, k);
             }
             return;
         }
@@ -73,7 +75,7 @@ fn d(c: char, i: |char|, k: bool) {
     }
 
     // Finally bottom out.
-    i(c);
+    (*i)(c);
 }
 
 pub fn compose(a: char, b: char) -> Option<char> {
@@ -81,16 +83,16 @@ pub fn compose(a: char, b: char) -> Option<char> {
         match bsearch_table(a, composition_table) {
             None => None,
             Some(candidates) => {
-                match candidates.binary_search(|&(val, _)| {
+                match candidates.binary_search_by(|&(val, _)| {
                     if b == val { Equal }
                     else if val < b { Less }
                     else { Greater }
                 }) {
-                    slice::BinarySearchResult::Found(idx) => {
+                    Ok(idx) => {
                         let (_, result) = candidates[idx];
                         Some(result)
                     }
-                    slice::BinarySearchResult::NotFound(_) => None
+                    Err(_) => None
                 }
             }
         }
@@ -108,23 +110,24 @@ const T_COUNT: u32 = 28;
 const N_COUNT: u32 = (V_COUNT * T_COUNT);
 const S_COUNT: u32 = (L_COUNT * N_COUNT);
 
+// FIXME(#19596) This is a workaround, we should use `F` instead of `&mut F`
 // Decompose a precomposed Hangul syllable
 #[inline(always)]
-fn decompose_hangul(s: char, f: |char|) {
+fn decompose_hangul<F>(s: char, f: &mut F) where F: FnMut(char) {
     use core::mem::transmute;
 
     let si = s as u32 - S_BASE;
 
     let li = si / N_COUNT;
     unsafe {
-        f(transmute(L_BASE + li));
+        (*f)(transmute(L_BASE + li));
 
         let vi = (si % N_COUNT) / T_COUNT;
-        f(transmute(V_BASE + vi));
+        (*f)(transmute(V_BASE + vi));
 
         let ti = si % T_COUNT;
         if ti > 0 {
-            f(transmute(T_BASE + ti));
+            (*f)(transmute(T_BASE + ti));
         }
     }
 }
diff --git a/src/libunicode/tables.rs b/src/libunicode/tables.rs
index a219aefad19..5a8f63f207e 100644
--- a/src/libunicode/tables.rs
+++ b/src/libunicode/tables.rs
@@ -19,11 +19,11 @@ pub const UNICODE_VERSION: (uint, uint, uint) = (7, 0, 0);
 fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
     use core::cmp::Ordering::{Equal, Less, Greater};
     use core::slice::SliceExt;
-    r.binary_search(|&(lo,hi)| {
+    r.binary_search_by(|&(lo,hi)| {
         if lo <= c && c <= hi { Equal }
         else if hi < c { Less }
         else { Greater }
-    }).found().is_some()
+    }).is_ok()
 }
 
 pub mod general_category {
@@ -6826,17 +6826,17 @@ pub mod normalization {
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, u8)]) -> u8 {
         use core::cmp::Ordering::{Equal, Less, Greater};
         use core::slice::SliceExt;
-        use core::slice;
-        match r.binary_search(|&(lo, hi, _)| {
+        use core::result::Result::{Ok, Err};
+        match r.binary_search_by(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            slice::BinarySearchResult::Found(idx) => {
+            Ok(idx) => {
                 let (_, _, result) = r[idx];
                 result
             }
-            slice::BinarySearchResult::NotFound(_) => 0
+            Err(_) => 0
         }
     }
 
@@ -6961,7 +6961,7 @@ pub mod conversions {
     use core::slice::SliceExt;
     use core::option::Option;
     use core::option::Option::{Some, None};
-    use core::slice;
+    use core::result::Result::{Ok, Err};
 
     pub fn to_lower(c: char) -> char {
         match bsearch_case_table(c, LuLl_table) {
@@ -6978,13 +6978,13 @@ pub mod conversions {
     }
 
     fn bsearch_case_table(c: char, table: &'static [(char, char)]) -> Option<uint> {
-        match table.binary_search(|&(key, _)| {
+        match table.binary_search_by(|&(key, _)| {
             if c == key { Equal }
             else if key < c { Less }
             else { Greater }
         }) {
-            slice::BinarySearchResult::Found(i) => Some(i),
-            slice::BinarySearchResult::NotFound(_) => None,
+            Ok(i) => Some(i),
+            Err(_) => None,
         }
     }
 
@@ -7596,20 +7596,20 @@ pub mod charwidth {
     use core::option::Option;
     use core::option::Option::{Some, None};
     use core::slice::SliceExt;
-    use core::slice;
+    use core::result::Result::{Ok, Err};
 
     fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 {
         use core::cmp::Ordering::{Equal, Less, Greater};
-        match r.binary_search(|&(lo, hi, _, _)| {
+        match r.binary_search_by(|&(lo, hi, _, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            slice::BinarySearchResult::Found(idx) => {
+            Ok(idx) => {
                 let (_, _, r_ncjk, r_cjk) = r[idx];
                 if is_cjk { r_cjk } else { r_ncjk }
             }
-            slice::BinarySearchResult::NotFound(_) => 1
+            Err(_) => 1
         }
     }
 
@@ -7804,7 +7804,7 @@ pub mod grapheme {
     use core::kinds::Copy;
     use core::slice::SliceExt;
     pub use self::GraphemeCat::*;
-    use core::slice;
+    use core::result::Result::{Ok, Err};
 
     #[allow(non_camel_case_types)]
     #[deriving(Clone)]
@@ -7825,16 +7825,16 @@ pub mod grapheme {
 
     fn bsearch_range_value_table(c: char, r: &'static [(char, char, GraphemeCat)]) -> GraphemeCat {
         use core::cmp::Ordering::{Equal, Less, Greater};
-        match r.binary_search(|&(lo, hi, _)| {
+        match r.binary_search_by(|&(lo, hi, _)| {
             if lo <= c && c <= hi { Equal }
             else if hi < c { Less }
             else { Greater }
         }) {
-            slice::BinarySearchResult::Found(idx) => {
+            Ok(idx) => {
                 let (_, _, cat) = r[idx];
                 cat
             }
-            slice::BinarySearchResult::NotFound(_) => GC_Any
+            Err(_) => GC_Any
         }
     }
 
diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs
index a3d4dd057d0..9b473ea5f54 100644
--- a/src/libunicode/u_str.rs
+++ b/src/libunicode/u_str.rs
@@ -24,16 +24,15 @@ use core::iter::{Filter, AdditiveIterator};
 use core::mem;
 use core::num::Int;
 use core::slice;
-use core::str::CharSplits;
+use core::str::Split;
 
 use u_char::UnicodeChar;
 use tables::grapheme::GraphemeCat;
 
 /// An iterator over the words of a string, separated by a sequence of whitespace
-/// FIXME: This should be opaque
 #[stable]
 pub struct Words<'a> {
-    inner: Filter<&'a str, CharSplits<'a, fn(char) -> bool>, fn(&&str) -> bool>,
+    inner: Filter<&'a str, Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
 }
 
 /// Methods for Unicode string slices
@@ -90,12 +89,12 @@ impl UnicodeStr for str {
 
     #[inline]
     fn trim_left(&self) -> &str {
-        self.trim_left_chars(|&: c: char| c.is_whitespace())
+        self.trim_left_matches(|&: c: char| c.is_whitespace())
     }
 
     #[inline]
     fn trim_right(&self) -> &str {
-        self.trim_right_chars(|&: c: char| c.is_whitespace())
+        self.trim_right_matches(|&: c: char| c.is_whitespace())
     }
 }
 
@@ -354,7 +353,7 @@ impl<'a> DoubleEndedIterator<&'a str> for Graphemes<'a> {
 }
 
 // https://tools.ietf.org/html/rfc3629
-static UTF8_CHAR_WIDTH: [u8, ..256] = [
+static UTF8_CHAR_WIDTH: [u8; 256] = [
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
@@ -520,9 +519,9 @@ impl<I> Iterator<u16> for Utf16Encoder<I> where I: Iterator<char> {
             return Some(tmp);
         }
 
-        let mut buf = [0u16, ..2];
+        let mut buf = [0u16; 2];
         self.chars.next().map(|ch| {
-            let n = ch.encode_utf16(buf[mut]).unwrap_or(0);
+            let n = ch.encode_utf16(buf.as_mut_slice()).unwrap_or(0);
             if n == 2 { self.extra = buf[1]; }
             buf[0]
         })
diff --git a/src/rust-installer b/src/rust-installer
-Subproject aed73472416064642911af790b25d57c9390b6c
+Subproject 3a37981744a5af2433fed551f742465c78c9af7
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 9fda05431db..bce73a27699 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -257,7 +257,7 @@ extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
     Builder->finalize();
 }
 
-extern "C" void LLVMDIBuilderCreateCompileUnit(
+extern "C" LLVMValueRef LLVMDIBuilderCreateCompileUnit(
     DIBuilderRef Builder,
     unsigned Lang,
     const char* File,
@@ -267,8 +267,14 @@ extern "C" void LLVMDIBuilderCreateCompileUnit(
     const char* Flags,
     unsigned RuntimeVer,
     const char* SplitName) {
-    Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized,
-        Flags, RuntimeVer, SplitName);
+    return wrap(Builder->createCompileUnit(Lang,
+                                           File,
+                                           Dir,
+                                           Producer,
+                                           isOptimized,
+                                           Flags,
+                                           RuntimeVer,
+                                           SplitName));
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderCreateFile(
diff --git a/src/snapshots.txt b/src/snapshots.txt
index c3cdf4acba1..6a9bfa07cf7 100644
--- a/src/snapshots.txt
+++ b/src/snapshots.txt
@@ -1,3 +1,12 @@
+S 2014-12-30 023dfb0
+  freebsd-x86_64 41ecd0ac557c823831c46696c7d78dc250398f25
+  linux-i386 fe6b59bf70a397e18629cb82264f7c6a70df34d4
+  linux-x86_64 8ab3a223f65fbf6b0aa80fcf0564a6d0fb9122e8
+  macos-i386 d23edb1be58b8683782a473cdc249c58a959c165
+  macos-x86_64 ab87616fa5d427978db3acd2d705042133ca3c09
+  winnt-i386 f2c26ac1ccb9d9a00886da9b504190681de89a5f
+  winnt-x86_64 fa2c7636bb15583ae387554b561ab09babee281a
+
 S 2014-12-20 8443b09
   freebsd-x86_64 004f54dce86faeebc15abf92c8742634b53987e6
   linux-i386 3daf531aed03f5769402f2fef852377e2838db98
diff --git a/src/test/auxiliary/associated-types-cc-lib.rs b/src/test/auxiliary/associated-types-cc-lib.rs
new file mode 100644
index 00000000000..17b2a0751fe
--- /dev/null
+++ b/src/test/auxiliary/associated-types-cc-lib.rs
@@ -0,0 +1,27 @@
+// 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.
+
+// Helper for test issue-18048, which tests associated types in a
+// cross-crate scenario.
+
+#![crate_type="lib"]
+#![feature(associated_types)]
+
+pub trait Bar {
+    type T;
+
+    fn get(x: Option<Self>) -> <Self as Bar>::T;
+}
+
+impl Bar for int {
+    type T = uint;
+
+    fn get(_: Option<int>) -> uint { 22 }
+}
diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs
index 16129593485..26d4ec25c64 100644
--- a/src/test/bench/core-std.rs
+++ b/src/test/bench/core-std.rs
@@ -65,7 +65,7 @@ fn shift_push() {
     let mut v2 = Vec::new();
 
     while v1.len() > 0 {
-        v2.push(v1.remove(0).unwrap());
+        v2.push(v1.remove(0));
     }
 }
 
@@ -83,7 +83,7 @@ fn read_line() {
 }
 
 fn vec_plus() {
-    let mut r = rand::task_rng();
+    let mut r = rand::thread_rng();
 
     let mut v = Vec::new();
     let mut i = 0;
@@ -101,7 +101,7 @@ fn vec_plus() {
 }
 
 fn vec_append() {
-    let mut r = rand::task_rng();
+    let mut r = rand::thread_rng();
 
     let mut v = Vec::new();
     let mut i = 0;
@@ -122,7 +122,7 @@ fn vec_append() {
 }
 
 fn vec_push_all() {
-    let mut r = rand::task_rng();
+    let mut r = rand::thread_rng();
 
     let mut v = Vec::new();
     for i in range(0u, 1500) {
diff --git a/src/test/bench/msgsend-ring-mutex-arcs.rs b/src/test/bench/msgsend-ring-mutex-arcs.rs
index c0b2edd3001..3ead5ef64fd 100644
--- a/src/test/bench/msgsend-ring-mutex-arcs.rs
+++ b/src/test/bench/msgsend-ring-mutex-arcs.rs
@@ -29,15 +29,15 @@ type pipe = Arc<(Mutex<Vec<uint>>, Condvar)>;
 
 fn send(p: &pipe, msg: uint) {
     let &(ref lock, ref cond) = &**p;
-    let mut arr = lock.lock();
+    let mut arr = lock.lock().unwrap();
     arr.push(msg);
     cond.notify_one();
 }
 fn recv(p: &pipe) -> uint {
     let &(ref lock, ref cond) = &**p;
-    let mut arr = lock.lock();
+    let mut arr = lock.lock().unwrap();
     while arr.is_empty() {
-        cond.wait(&arr);
+        arr = cond.wait(arr).unwrap();
     }
     arr.pop().unwrap()
 }
diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs
index 73e0c9e0a1f..ec1268c9080 100644
--- a/src/test/bench/shootout-fannkuch-redux.rs
+++ b/src/test/bench/shootout-fannkuch-redux.rs
@@ -53,7 +53,7 @@ fn rotate(x: &mut [i32]) {
 
 fn next_permutation(perm: &mut [i32], count: &mut [i32]) {
     for i in range(1, perm.len()) {
-        rotate(perm[mut ..i + 1]);
+        rotate(perm.slice_to_mut(i + 1));
         let count_i = &mut count[i];
         if *count_i >= i as i32 {
             *count_i = 0;
@@ -132,7 +132,7 @@ impl Perm {
 
 
 fn reverse(tperm: &mut [i32], mut k: uint) {
-    tperm[mut ..k].reverse()
+    tperm.slice_to_mut(k).reverse()
 }
 
 fn work(mut perm: Perm, n: uint, max: uint) -> (i32, i32) {
diff --git a/src/test/bench/shootout-fasta-redux.rs b/src/test/bench/shootout-fasta-redux.rs
index 05524492c28..09f7f236f19 100644
--- a/src/test/bench/shootout-fasta-redux.rs
+++ b/src/test/bench/shootout-fasta-redux.rs
@@ -129,7 +129,7 @@ impl<'a, W: Writer> RepeatFasta<'a, W> {
 
         copy_memory(buf.as_mut_slice(), alu);
         let buf_len = buf.len();
-        copy_memory(buf[mut alu_len..buf_len],
+        copy_memory(buf.slice_mut(alu_len, buf_len),
                     alu[..LINE_LEN]);
 
         let mut pos = 0;
diff --git a/src/test/bench/shootout-reverse-complement.rs b/src/test/bench/shootout-reverse-complement.rs
index e286efeb304..d9dfd65d5b3 100644
--- a/src/test/bench/shootout-reverse-complement.rs
+++ b/src/test/bench/shootout-reverse-complement.rs
@@ -182,7 +182,7 @@ fn reverse_complement(seq: &mut [u8], tables: &Tables) {
         unsafe {
             copy_memory(seq.as_mut_ptr().offset((i - off + 1) as int),
                         seq.as_ptr().offset((i - off) as int), off);
-            *seq.unsafe_mut(i - off) = b'\n';
+            *seq.get_unchecked_mut(i - off) = b'\n';
         }
         i += LINE_LEN + 1;
     }
@@ -237,27 +237,18 @@ fn parallel<'a, I, T, F>(mut iter: I, f: F)
     iter.map(|chunk| {
         // Need to convert `f` and `chunk` to something that can cross the task
         // boundary.
-<<<<<<< HEAD
         let f = Racy(&f as *const F as *const uint);
         let raw = Racy(chunk.repr());
-        spawn(move|| {
+        Thread::spawn(move|| {
             let f = f.0 as *const F;
             unsafe { (*f)(mem::transmute(raw.0)) }
-            drop(tx)
-=======
-        let f = &f as *const F as *const uint;
-        let raw = chunk.repr();
-        Thread::spawn(move|| {
-            let f = f as *const F;
-            unsafe { (*f)(mem::transmute(raw)) }
->>>>>>> std: Stabilize the prelude module
-        });
+        })
     }).collect::<Vec<_>>();
 }
 
 fn main() {
     let mut data = read_to_end(&mut stdin_raw()).unwrap();
     let tables = &Tables::new();
-    parallel(mut_dna_seqs(data[mut]), |&: seq| reverse_complement(seq, tables));
+    parallel(mut_dna_seqs(data.as_mut_slice()), |&: seq| reverse_complement(seq, tables));
     stdout_raw().write(data.as_mut_slice()).unwrap();
 }
diff --git a/src/test/bench/shootout-spectralnorm.rs b/src/test/bench/shootout-spectralnorm.rs
index b8bb39d4b05..a5af1227a16 100644
--- a/src/test/bench/shootout-spectralnorm.rs
+++ b/src/test/bench/shootout-spectralnorm.rs
@@ -132,7 +132,6 @@ fn parallel<T, F>(v: &mut [T], f: F)
         Thread::spawn(move|| {
             let f = f.0 as *const F;
             unsafe { (*f)(i * size, mem::transmute(raw.0)) }
-            drop(tx)
         })
     }).collect::<Vec<_>>();
 }
diff --git a/src/test/compile-fail/array-old-syntax-1.rs b/src/test/compile-fail/array-old-syntax-1.rs
new file mode 100644
index 00000000000..3c01a7756a6
--- /dev/null
+++ b/src/test/compile-fail/array-old-syntax-1.rs
@@ -0,0 +1,15 @@
+// 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 the old fixed length array syntax is a parsing error.
+
+fn main() {
+    let _x: [int, ..3] = [0i, 1, 2]; //~ ERROR
+}
diff --git a/src/test/compile-fail/array-old-syntax-2.rs b/src/test/compile-fail/array-old-syntax-2.rs
new file mode 100644
index 00000000000..df2cc305ca8
--- /dev/null
+++ b/src/test/compile-fail/array-old-syntax-2.rs
@@ -0,0 +1,15 @@
+// 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 the old repeating array syntax gives an error.
+
+fn main() {
+    let _ = [0i, ..3]; //~ ERROR
+}
diff --git a/src/test/compile-fail/associated-types-bound-failure.rs b/src/test/compile-fail/associated-types-bound-failure.rs
new file mode 100644
index 00000000000..7981fe31827
--- /dev/null
+++ b/src/test/compile-fail/associated-types-bound-failure.rs
@@ -0,0 +1,39 @@
+// 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 equality constraints on associated types in a where clause.
+
+#![feature(associated_types)]
+
+pub trait ToInt {
+    fn to_int(&self) -> int;
+}
+
+pub trait GetToInt
+{
+    type R;
+
+    fn get(&self) -> <Self as GetToInt>::R;
+}
+
+fn foo<G>(g: G) -> int
+    where G : GetToInt
+{
+    ToInt::to_int(&g.get()) //~ ERROR not implemented
+}
+
+fn bar<G : GetToInt>(g: G) -> int
+    where G::R : ToInt
+{
+    ToInt::to_int(&g.get()) // OK
+}
+
+pub fn main() {
+}
diff --git a/src/test/compile-fail/assoc-eq-1.rs b/src/test/compile-fail/associated-types-eq-1.rs
index e93d9db28cf..e93d9db28cf 100644
--- a/src/test/compile-fail/assoc-eq-1.rs
+++ b/src/test/compile-fail/associated-types-eq-1.rs
diff --git a/src/test/compile-fail/assoc-eq-2.rs b/src/test/compile-fail/associated-types-eq-2.rs
index 652bf4fb577..b89cdd8c0ee 100644
--- a/src/test/compile-fail/assoc-eq-2.rs
+++ b/src/test/compile-fail/associated-types-eq-2.rs
@@ -25,6 +25,7 @@ impl Foo for int {
     fn boo(&self) -> uint { 42 }
 }
 
-fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {} //~ERROR equality constraints are not allowed in this
+fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
+//~^ ERROR associated type bindings are not allowed here
 
 pub fn main() {}
diff --git a/src/test/compile-fail/assoc-eq-3.rs b/src/test/compile-fail/associated-types-eq-3.rs
index 880b2e9cc4a..e5974925d73 100644
--- a/src/test/compile-fail/assoc-eq-3.rs
+++ b/src/test/compile-fail/associated-types-eq-3.rs
@@ -43,6 +43,6 @@ pub fn baz(x: &Foo<A=Bar>) {
 
 pub fn main() {
     let a = 42i;
-    foo1(a); //~ERROR the trait `Foo` is not implemented for the type `int`
-    baz(&a); //~ERROR the trait `Foo` is not implemented for the type `int`
+    foo1(a); //~ERROR expected uint, found struct Bar
+    baz(&a); //~ERROR expected uint, found struct Bar
 }
diff --git a/src/test/compile-fail/assoc-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs
index 1a96b0ca681..1a96b0ca681 100644
--- a/src/test/compile-fail/assoc-eq-expr-path.rs
+++ b/src/test/compile-fail/associated-types-eq-expr-path.rs
diff --git a/src/test/compile-fail/associated-types-eq-hr.rs b/src/test/compile-fail/associated-types-eq-hr.rs
new file mode 100644
index 00000000000..aad55745c25
--- /dev/null
+++ b/src/test/compile-fail/associated-types-eq-hr.rs
@@ -0,0 +1,72 @@
+// 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 testing of equality constraints in a higher-ranked context.
+
+#![feature(associated_types)]
+
+pub trait TheTrait<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+struct IntStruct {
+    x: int
+}
+
+impl<'a> TheTrait<&'a int> for IntStruct {
+    type A = &'a int;
+
+    fn get(&self, t: &'a int) -> &'a int {
+        t
+    }
+}
+
+struct UintStruct {
+    x: int
+}
+
+impl<'a> TheTrait<&'a int> for UintStruct {
+    type A = &'a uint;
+
+    fn get(&self, t: &'a int) -> &'a uint {
+        panic!()
+    }
+}
+
+fn foo<T>()
+    where T : for<'x> TheTrait<&'x int, A = &'x int>
+{
+    // ok for IntStruct, but not UintStruct
+}
+
+fn bar<T>()
+    where T : for<'x> TheTrait<&'x int, A = &'x uint>
+{
+    // ok for UintStruct, but not IntStruct
+}
+
+fn baz<T>()
+    where T : for<'x,'y> TheTrait<&'x int, A = &'y int>
+{
+    // not ok for either struct, due to the use of two lifetimes
+}
+
+pub fn main() {
+    foo::<IntStruct>();
+    foo::<UintStruct>(); //~ ERROR type mismatch
+
+    bar::<IntStruct>(); //~ ERROR type mismatch
+    bar::<UintStruct>();
+
+    baz::<IntStruct>(); //~ ERROR type mismatch
+    baz::<UintStruct>(); //~ ERROR type mismatch
+}
diff --git a/src/test/compile-fail/associated-types-for-unimpl-trait.rs b/src/test/compile-fail/associated-types-for-unimpl-trait.rs
new file mode 100644
index 00000000000..2c6ee502fca
--- /dev/null
+++ b/src/test/compile-fail/associated-types-for-unimpl-trait.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_types)]
+
+trait Get {
+    type Value;
+    fn get(&self) -> <Self as Get>::Value;
+}
+
+trait Other {
+    fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+    //~^ ERROR the trait `Get` is not implemented for the type `Self`
+}
+
+fn main() {
+}
+
diff --git a/src/test/compile-fail/associated-types-in-ambiguous-context.rs b/src/test/compile-fail/associated-types-in-ambiguous-context.rs
index 24de1fa2f78..fcd3e4d1636 100644
--- a/src/test/compile-fail/associated-types-in-ambiguous-context.rs
+++ b/src/test/compile-fail/associated-types-in-ambiguous-context.rs
@@ -18,16 +18,6 @@ trait Get {
 fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
 //~^ ERROR ambiguous associated type
 
-trait Other {
-    fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-    //~^ ERROR no suitable bound on `Self`
-}
-
-impl<T:Get> Other for T {
-    fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-    //~^ ERROR currently unsupported
-}
-
 trait Grab {
     type Value;
     fn grab(&self) -> Grab::Value;
diff --git a/src/test/compile-fail/associated-types-incomplete-object.rs b/src/test/compile-fail/associated-types-incomplete-object.rs
new file mode 100644
index 00000000000..7e4e1315110
--- /dev/null
+++ b/src/test/compile-fail/associated-types-incomplete-object.rs
@@ -0,0 +1,44 @@
+// 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 the user gets an errror if they omit a binding from an
+// object type.
+
+#![feature(associated_types)]
+
+pub trait Foo {
+    type A;
+    type B;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+struct Bar;
+
+impl Foo for int {
+    type A = uint;
+    type B = char;
+    fn boo(&self) -> uint {
+        42
+    }
+}
+
+pub fn main() {
+    let a = &42i as &Foo<A=uint, B=char>;
+
+    let b = &42i as &Foo<A=uint>;
+    //~^ ERROR the value of the associated type `B` (from the trait `Foo`) must be specified
+
+    let c = &42i as &Foo<B=char>;
+    //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
+
+    let d = &42i as &Foo;
+    //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified
+    //~| ERROR the value of the associated type `B` (from the trait `Foo`) must be specified
+}
diff --git a/src/test/compile-fail/associated-types-issue-20346.rs b/src/test/compile-fail/associated-types-issue-20346.rs
new file mode 100644
index 00000000000..255b8a25a4c
--- /dev/null
+++ b/src/test/compile-fail/associated-types-issue-20346.rs
@@ -0,0 +1,46 @@
+// 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 we reliably check the value of the associated type.
+
+#![crate_type = "lib"]
+#![feature(associated_types)]
+#![no_implicit_prelude]
+
+use std::option::Option::{None, Some, mod};
+use std::vec::Vec;
+
+trait Iterator {
+    type Item;
+
+    fn next(&mut self) -> Option<Self::Item>;
+}
+
+fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
+
+struct Adapter<I> {
+    iter: I,
+    found_none: bool,
+}
+
+impl<T, I> Iterator for Adapter<I> where I: Iterator<Item=Option<T>> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        loop {}
+    }
+}
+
+fn test_adapter<T, I: Iterator<Item=Option<T>>>(it: I) {
+    is_iterator_of::<Option<T>, _>(&it);  // Sanity check
+    let adapter = Adapter { iter: it, found_none: false };
+    is_iterator_of::<T, _>(&adapter); // OK
+    is_iterator_of::<Option<T>, _>(&adapter); //~ ERROR type mismatch
+}
diff --git a/src/test/compile-fail/associated-types-in-wrong-context.rs b/src/test/compile-fail/associated-types-no-suitable-bound.rs
index 8cab2759ad5..6b856204091 100644
--- a/src/test/compile-fail/associated-types-in-wrong-context.rs
+++ b/src/test/compile-fail/associated-types-no-suitable-bound.rs
@@ -15,16 +15,13 @@ trait Get {
     fn get(&self) -> <Self as Get>::Value;
 }
 
-fn get(x: int) -> <int as Get>::Value {}
-//~^ ERROR unsupported
-
 struct Struct {
     x: int,
 }
 
 impl Struct {
     fn uhoh<T>(foo: <T as Get>::Value) {}
-    //~^ ERROR no suitable bound on `T`
+    //~^ ERROR the trait `Get` is not implemented for the type `T`
 }
 
 fn main() {
diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs
new file mode 100644
index 00000000000..5a4ebeac41e
--- /dev/null
+++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_types)]
+
+// Check that we get an error when you use `<Self as Get>::Value` in
+// the trait definition but `Self` does not, in fact, implement `Get`.
+
+trait Get {
+    type Value;
+}
+
+trait Other {
+    fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
+    //~^ ERROR the trait `Get` is not implemented for the type `Self`
+}
+
+impl<T:Get> Other for T {
+    fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
+    //~^ ERROR the trait `Get` is not implemented for the type `(T, U)`
+    //~| ERROR the trait `Get` is not implemented for the type `(T, U)`
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/assoc-path-1.rs b/src/test/compile-fail/associated-types-path-1.rs
index 41f5bc17b56..41f5bc17b56 100644
--- a/src/test/compile-fail/assoc-path-1.rs
+++ b/src/test/compile-fail/associated-types-path-1.rs
diff --git a/src/test/compile-fail/assoc-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs
index caf8ab3695d..989214d81da 100644
--- a/src/test/compile-fail/assoc-path-2.rs
+++ b/src/test/compile-fail/associated-types-path-2.rs
@@ -25,10 +25,30 @@ pub fn f2<T: Foo>(a: T) -> T::A {
     panic!();
 }
 
-pub fn main() {
-    f1(2i, 4i); //~ERROR the trait `Foo` is not implemented
-    f1(2u, 4u); //~ERROR the trait `Foo` is not implemented
-    f1(2u, 4i); //~ERROR the trait `Foo` is not implemented
+pub fn f1_int_int() {
+    f1(2i, 4i);
+    //~^ ERROR expected uint, found int
+}
+
+pub fn f1_int_uint() {
+    f1(2i, 4u);
+}
+
+pub fn f1_uint_uint() {
+    f1(2u, 4u);
+    //~^ ERROR the trait `Foo` is not implemented
+    //~| ERROR the trait `Foo` is not implemented
+}
+
+pub fn f1_uint_int() {
+    f1(2u, 4i);
+    //~^ ERROR the trait `Foo` is not implemented
+    //~| ERROR the trait `Foo` is not implemented
+}
 
-    let _: int = f2(2i); //~ERROR mismatched types: expected `int`, found `uint`
+pub fn f2_int() {
+    let _: int = f2(2i);
+    //~^ ERROR expected `int`, found `uint`
 }
+
+pub fn main() { }
diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs b/src/test/compile-fail/associated-types-project-from-hrtb-explicit.rs
new file mode 100644
index 00000000000..1f0f044a4c0
--- /dev/null
+++ b/src/test/compile-fail/associated-types-project-from-hrtb-explicit.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.
+
+// Test you can't use a higher-ranked trait bound inside of a qualified
+// path (just won't parse).
+
+#![feature(associated_types)]
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+fn foo2<I>(x: <I as for<'x> Foo<&'x int>>::A)
+    //~^ ERROR expected identifier, found keyword `for`
+    //~| ERROR expected one of `::` or `>`
+{
+}
+
+pub fn main() {}
diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.rs
new file mode 100644
index 00000000000..0e13efdebc9
--- /dev/null
+++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn-body.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.
+
+// Check projection of an associated type out of a higher-ranked
+// trait-bound in the context of a function body.
+
+#![feature(associated_types)]
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+fn foo<'a, I : for<'x> Foo<&'x int>>(
+    x: <I as Foo<&'a int>>::A)
+{
+    let y: I::A = x;
+}
+
+fn bar<'a, 'b, I : for<'x> Foo<&'x int>>(
+    x: <I as Foo<&'a int>>::A,
+    y: <I as Foo<&'b int>>::A,
+    cond: bool)
+{
+    // x and y here have two distinct lifetimes:
+    let z: I::A = if cond { x } else { y };
+    //~^ ERROR cannot infer
+}
+
+pub fn main() {}
diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs
new file mode 100644
index 00000000000..0d5c6959142
--- /dev/null
+++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-fn.rs
@@ -0,0 +1,47 @@
+// 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 projection of an associated type out of a higher-ranked trait-bound
+// in the context of a function signature.
+
+#![feature(associated_types)]
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+fn foo2<I : for<'x> Foo<&'x int>>(
+    x: I::A)
+    //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
+{
+    // This case is illegal because we have to instantiate `'x`, and
+    // we don't know what region to instantiate it with.
+    //
+    // This could perhaps be made equivalent to the examples below,
+    // specifically for fn signatures.
+}
+
+fn foo3<I : for<'x> Foo<&'x int>>(
+    x: <I as Foo<&int>>::A)
+{
+    // OK, in this case we spelled out the precise regions involved, though we left one of
+    // them anonymous.
+}
+
+fn foo4<'a, I : for<'x> Foo<&'x int>>(
+    x: <I as Foo<&'a int>>::A)
+{
+    // OK, in this case we spelled out the precise regions involved.
+}
+
+
+pub fn main() {}
diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs
new file mode 100644
index 00000000000..5016c6448a5
--- /dev/null
+++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-struct.rs
@@ -0,0 +1,36 @@
+// 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 projection of an associated type out of a higher-ranked trait-bound
+// in the context of a struct definition.
+
+#![feature(associated_types)]
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+struct SomeStruct<I : for<'x> Foo<&'x int>> {
+    field: I::A
+    //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
+}
+
+struct AnotherStruct<I : for<'x> Foo<&'x int>> {
+    field: <I as Foo<&int>>::A
+    //~^ ERROR missing lifetime specifier
+}
+
+struct YetAnotherStruct<'a, I : for<'x> Foo<&'x int>> {
+    field: <I as Foo<&'a int>>::A
+}
+
+pub fn main() {}
diff --git a/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs b/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs
new file mode 100644
index 00000000000..a92d4ec04cb
--- /dev/null
+++ b/src/test/compile-fail/associated-types-project-from-hrtb-in-trait-method.rs
@@ -0,0 +1,35 @@
+// 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 projection of an associated type out of a higher-ranked trait-bound
+// in the context of a method definition in a trait.
+
+#![feature(associated_types)]
+
+pub trait Foo<T> {
+    type A;
+
+    fn get(&self, t: T) -> Self::A;
+}
+
+trait SomeTrait<I : for<'x> Foo<&'x int>> {
+    fn some_method(&self, arg: I::A);
+    //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
+}
+
+trait AnotherTrait<I : for<'x> Foo<&'x int>> {
+    fn some_method(&self, arg: <I as Foo<&int>>::A);
+}
+
+trait YetAnotherTrait<I : for<'x> Foo<&'x int>> {
+    fn some_method<'a>(&self, arg: <I as Foo<&'a int>>::A);
+}
+
+pub fn main() {}
diff --git a/src/test/compile-fail/associated-types-unconstrained.rs b/src/test/compile-fail/associated-types-unconstrained.rs
new file mode 100644
index 00000000000..02e11218806
--- /dev/null
+++ b/src/test/compile-fail/associated-types-unconstrained.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.
+
+// Check that an associated type cannot be bound in an expression path.
+
+#![feature(associated_types)]
+
+trait Foo {
+    type A;
+    fn bar() -> int;
+}
+
+impl Foo for int {
+    type A = uint;
+    fn bar() -> int { 42 }
+}
+
+pub fn main() {
+    let x: int = Foo::bar();
+    //~^ ERROR type annotations required
+}
diff --git a/src/test/compile-fail/better-expected.rs b/src/test/compile-fail/better-expected.rs
index 2e0f2a174c6..672d8a30fc5 100644
--- a/src/test/compile-fail/better-expected.rs
+++ b/src/test/compile-fail/better-expected.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    let x: [int 3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, `;`, or `]`, found `3`
+    let x: [int 3]; //~ ERROR expected one of `(`, `+`, `::`, `;`, or `]`, found `3`
 }
diff --git a/src/test/compile-fail/double-type-import.rs b/src/test/compile-fail/double-type-import.rs
new file mode 100644
index 00000000000..923f95e69d1
--- /dev/null
+++ b/src/test/compile-fail/double-type-import.rs
@@ -0,0 +1,24 @@
+// 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.
+
+mod foo {
+    pub use self::bar::X;
+    use self::bar::X;
+    //~^ ERROR a value named `X` has already been imported in this module
+    //~| ERROR a type named `X` has already been imported in this module
+
+    mod bar {
+        pub struct X;
+    }
+}
+
+fn main() {
+    let _ = foo::X;
+}
diff --git a/src/test/compile-fail/duplicate-trait-bounds.rs b/src/test/compile-fail/duplicate-trait-bounds.rs
new file mode 100644
index 00000000000..d9aa9d9dfcc
--- /dev/null
+++ b/src/test/compile-fail/duplicate-trait-bounds.rs
@@ -0,0 +1,15 @@
+// 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 Foo {}
+
+fn foo<T: Foo + Foo>() {} //~ ERROR `Foo` already appears in the list of bounds
+
+fn main() {}
diff --git a/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs b/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs
new file mode 100644
index 00000000000..cd49c7c016e
--- /dev/null
+++ b/src/test/compile-fail/feature-gated-feature-in-macro-arg.rs
@@ -0,0 +1,24 @@
+// 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.
+
+// tests that input to a macro is checked for use of gated features. If this
+// test succeeds due to the acceptance of a feature, pick a new feature to
+// test. Not ideal, but oh well :(
+
+fn main() {
+    let a = &[1i32, 2, 3];
+    println!("{}", {
+        extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change
+            fn atomic_fence();
+        }
+        atomic_fence();
+        42
+    });
+}
diff --git a/src/test/compile-fail/import-shadow-1.rs b/src/test/compile-fail/import-shadow-1.rs
new file mode 100644
index 00000000000..007b28b6924
--- /dev/null
+++ b/src/test/compile-fail/import-shadow-1.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that import shadowing using globs causes errors
+
+#![no_implicit_prelude]
+#![feature(globs)]
+
+use foo::*;
+use bar::*; //~ERROR a type named `Baz` has already been imported in this module
+
+mod foo {
+    pub type Baz = int;
+}
+
+mod bar {
+    pub type Baz = int;
+}
+
+mod qux {
+    pub use bar::Baz;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/import-shadow-2.rs b/src/test/compile-fail/import-shadow-2.rs
new file mode 100644
index 00000000000..e597b557383
--- /dev/null
+++ b/src/test/compile-fail/import-shadow-2.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that import shadowing using globs causes errors
+
+#![no_implicit_prelude]
+#![feature(globs)]
+
+use foo::*;
+use foo::*; //~ERROR a type named `Baz` has already been imported in this module
+
+mod foo {
+    pub type Baz = int;
+}
+
+mod bar {
+    pub type Baz = int;
+}
+
+mod qux {
+    pub use bar::Baz;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/import-shadow-3.rs b/src/test/compile-fail/import-shadow-3.rs
new file mode 100644
index 00000000000..68222fa3fd7
--- /dev/null
+++ b/src/test/compile-fail/import-shadow-3.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that import shadowing using globs causes errors
+
+#![no_implicit_prelude]
+#![feature(globs)]
+
+use foo::Baz;
+use bar::*; //~ERROR a type named `Baz` has already been imported in this module
+
+mod foo {
+    pub type Baz = int;
+}
+
+mod bar {
+    pub type Baz = int;
+}
+
+mod qux {
+    pub use bar::Baz;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/import-shadow-4.rs b/src/test/compile-fail/import-shadow-4.rs
new file mode 100644
index 00000000000..c698004bda0
--- /dev/null
+++ b/src/test/compile-fail/import-shadow-4.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that import shadowing using globs causes errors
+
+#![no_implicit_prelude]
+#![feature(globs)]
+
+use foo::*;
+use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module
+
+mod foo {
+    pub type Baz = int;
+}
+
+mod bar {
+    pub type Baz = int;
+}
+
+mod qux {
+    pub use bar::Baz;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/import-shadow-5.rs b/src/test/compile-fail/import-shadow-5.rs
new file mode 100644
index 00000000000..6ad7e5ec3e2
--- /dev/null
+++ b/src/test/compile-fail/import-shadow-5.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that import shadowing using globs causes errors
+
+#![no_implicit_prelude]
+#![feature(globs)]
+
+use foo::Baz;
+use bar::Baz; //~ERROR a type named `Baz` has already been imported in this module
+
+mod foo {
+    pub type Baz = int;
+}
+
+mod bar {
+    pub type Baz = int;
+}
+
+mod qux {
+    pub use bar::Baz;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/import-shadow-6.rs b/src/test/compile-fail/import-shadow-6.rs
new file mode 100644
index 00000000000..1864251e71b
--- /dev/null
+++ b/src/test/compile-fail/import-shadow-6.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that import shadowing using globs causes errors
+
+#![no_implicit_prelude]
+#![feature(globs)]
+
+use qux::*;
+use foo::*; //~ERROR a type named `Baz` has already been imported in this module
+
+mod foo {
+    pub type Baz = int;
+}
+
+mod bar {
+    pub type Baz = int;
+}
+
+mod qux {
+    pub use bar::Baz;
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/import-shadow-7.rs b/src/test/compile-fail/import-shadow-7.rs
new file mode 100644
index 00000000000..a2df266fb74
--- /dev/null
+++ b/src/test/compile-fail/import-shadow-7.rs
@@ -0,0 +1,31 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that import shadowing using globs causes errors
+
+#![no_implicit_prelude]
+#![feature(globs)]
+
+use foo::*;
+use qux::*; //~ERROR a type named `Baz` has already been imported in this module
+
+mod foo {
+    pub type Baz = int;
+}
+
+mod bar {
+    pub type Baz = int;
+}
+
+mod qux {
+    pub use bar::Baz;
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-12028.rs b/src/test/compile-fail/issue-12028.rs
index dbfa330d33d..78502efdec5 100644
--- a/src/test/run-pass/issue-12028.rs
+++ b/src/test/compile-fail/issue-12028.rs
@@ -8,6 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Test an example where we fail to infer the type parameter H. This
+// is because there is really nothing constraining it. At one time, we
+// would infer based on the where clauses in scope, but that no longer
+// works.
+
 trait Hash<H> {
     fn hash2(&self, hasher: &H) -> u64;
 }
@@ -30,7 +35,7 @@ trait StreamHash<S: Stream, H: StreamHasher<S>>: Hash<H> {
 impl<S: Stream, H: StreamHasher<S>> Hash<H> for u8 {
     fn hash2(&self, hasher: &H) -> u64 {
         let mut stream = hasher.stream();
-        self.input_stream(&mut stream);
+        self.input_stream(&mut stream); //~ ERROR type annotations required
         stream.result()
     }
 }
diff --git a/src/test/compile-fail/issue-13853-2.rs b/src/test/compile-fail/issue-13853-2.rs
new file mode 100644
index 00000000000..ea0d880f4a1
--- /dev/null
+++ b/src/test/compile-fail/issue-13853-2.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.
+
+trait FromStructReader<'a> { }
+trait ResponseHook {
+     fn get<'a, T: FromStructReader<'a>>(&'a self);
+}
+fn foo(res : Box<ResponseHook>) { res.get } //~ ERROR attempted to take value of method
+fn main() {}
diff --git a/src/test/compile-fail/issue-13853-3.rs b/src/test/compile-fail/issue-13853-3.rs
new file mode 100644
index 00000000000..f10c47b594e
--- /dev/null
+++ b/src/test/compile-fail/issue-13853-3.rs
@@ -0,0 +1,33 @@
+// 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.
+
+#![crate_type = "lib"]
+
+enum NodeContents<'a> {
+    Children(Vec<Node<'a>>),
+}
+
+impl<'a> Drop for NodeContents<'a> {
+    //~^ ERROR cannot implement a destructor on a structure with type parameters
+    fn drop( &mut self ) {
+    }
+}
+
+struct Node<'a> {
+    contents: NodeContents<'a>,
+}
+
+impl<'a> Node<'a> {
+    fn noName(contents: NodeContents<'a>) -> Node<'a> {
+        Node{  contents: contents,}
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-13853-4.rs b/src/test/compile-fail/issue-13853-4.rs
new file mode 100644
index 00000000000..7d653f5ab9e
--- /dev/null
+++ b/src/test/compile-fail/issue-13853-4.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.
+
+struct AutoBuilder<'a> {
+    context: &'a int
+}
+
+impl<'a> Drop for AutoBuilder<'a> {
+    //~^ ERROR cannot implement a destructor on a structure with type parameters
+    fn drop(&mut self) {
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-13853-5.rs b/src/test/compile-fail/issue-13853-5.rs
new file mode 100644
index 00000000000..b3a4f341f84
--- /dev/null
+++ b/src/test/compile-fail/issue-13853-5.rs
@@ -0,0 +1,23 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Deserializer<'a> { }
+
+trait Deserializable {
+    fn deserialize_token<'a, D: Deserializer<'a>>(D, &'a str) -> Self;
+}
+
+impl<'a, T: Deserializable> Deserializable for &'a str {
+    //~^ ERROR unable to infer enough type information
+    fn deserialize_token<D: Deserializer<'a>>(_x: D, _y: &'a str) -> &'a str {
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-13853.rs b/src/test/compile-fail/issue-13853.rs
new file mode 100644
index 00000000000..868836a4bbd
--- /dev/null
+++ b/src/test/compile-fail/issue-13853.rs
@@ -0,0 +1,45 @@
+// 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 Node {
+    fn zomg();
+}
+
+trait Graph<N: Node> {
+    fn nodes<'a, I: Iterator<&'a N>>(&'a self) -> I;
+}
+
+impl<N: Node> Graph<N> for Vec<N> {
+    fn nodes<'a, I: Iterator<&'a N>>(&self) -> I {
+        self.iter() //~ ERROR mismatched types
+    }
+}
+
+struct Stuff;
+
+impl Node for Stuff {
+    fn zomg() {
+        println!("zomg");
+    }
+}
+
+fn iterate<N: Node, G: Graph<N>>(graph: &G) {
+    for node in graph.iter() { //~ ERROR does not implement any method in scope named
+        node.zomg();
+    }
+}
+
+pub fn main() {
+    let graph = Vec::new();
+
+    graph.push(Stuff);
+
+    iterate(graph); //~ ERROR mismatched types
+}
diff --git a/src/test/compile-fail/issue-14227.rs b/src/test/compile-fail/issue-14227.rs
new file mode 100644
index 00000000000..c4846a64f29
--- /dev/null
+++ b/src/test/compile-fail/issue-14227.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.
+
+extern {
+    pub static symbol: ();
+}
+static CRASH: () = symbol; //~ cannot refer to other statics by value
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-15034.rs b/src/test/compile-fail/issue-15034.rs
new file mode 100644
index 00000000000..13d27e7152b
--- /dev/null
+++ b/src/test/compile-fail/issue-15034.rs
@@ -0,0 +1,32 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct Lexer<'a> {
+    input: &'a str,
+}
+
+impl<'a> Lexer<'a> {
+    pub fn new(input: &'a str) -> Lexer<'a> {
+        Lexer { input: input }
+    }
+}
+
+struct Parser<'a> {
+    lexer: &'a mut Lexer<'a>,
+}
+
+impl<'a> Parser<'a> {
+    pub fn new(lexer: &'a mut Lexer) -> Parser<'a> {
+        Parser { lexer: lexer }
+        //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-15756.rs b/src/test/compile-fail/issue-15756.rs
index df19de7731a..5be3b960ec6 100644
--- a/src/test/compile-fail/issue-15756.rs
+++ b/src/test/compile-fail/issue-15756.rs
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 use std::slice::Chunks;
-use std::slice::MutChunks;
+use std::slice::ChunksMut;
 
-fn dft_iter<'a, T>(arg1: Chunks<'a,T>, arg2: MutChunks<'a,T>)
+fn dft_iter<'a, T>(arg1: Chunks<'a,T>, arg2: ChunksMut<'a,T>)
 {
     for
     &something
diff --git a/src/test/compile-fail/issue-15965.rs b/src/test/compile-fail/issue-15965.rs
index f3636edeaa5..08b896f387b 100644
--- a/src/test/compile-fail/issue-15965.rs
+++ b/src/test/compile-fail/issue-15965.rs
@@ -12,8 +12,6 @@ fn main() {
     return
         { return () }
 //~^ ERROR the type of this value must be known in this context
-//~| ERROR this function takes 1 parameter
-//~| ERROR mismatched types
     ()
     ;
 }
diff --git a/src/test/compile-fail/issue-16538.rs b/src/test/compile-fail/issue-16538.rs
new file mode 100644
index 00000000000..0e022834bac
--- /dev/null
+++ b/src/test/compile-fail/issue-16538.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod Y {
+    type X = uint;
+    extern {
+        static x: *const uint;
+    }
+    fn foo(value: *const X) -> *const X {
+        value
+    }
+}
+
+static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
+//~^ ERROR cannot refer to other statics by value
+//~| ERROR: the trait `core::kinds::Sync` is not implemented for the type
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-16966.rs b/src/test/compile-fail/issue-16966.rs
index dfa23c48afa..5dbf7546de2 100644
--- a/src/test/compile-fail/issue-16966.rs
+++ b/src/test/compile-fail/issue-16966.rs
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// error-pattern:type annotations required
 fn main() {
     panic!(
-        1.2 //~ ERROR cannot determine a type for this expression
+        std::default::Default::default()
     );
 }
diff --git a/src/test/compile-fail/issue-17728.rs b/src/test/compile-fail/issue-17728.rs
new file mode 100644
index 00000000000..50b0a1a20c2
--- /dev/null
+++ b/src/test/compile-fail/issue-17728.rs
@@ -0,0 +1,132 @@
+// 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::fmt::{Show, Formatter, Error};
+use std::collections::HashMap;
+
+trait HasInventory {
+    fn getInventory<'s>(&'s self) -> &'s mut Inventory;
+    fn addToInventory(&self, item: &Item);
+    fn removeFromInventory(&self, itemName: &str) -> bool;
+}
+
+trait TraversesWorld {
+    fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
+        let direction = str_to_direction(directionStr);
+        let maybe_room = room.direction_to_room.find(&direction);
+        //~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements
+        match maybe_room {
+            Some(entry) => Ok(entry),
+            _ => Err("Direction does not exist in room.")
+        }
+    }
+}
+
+
+#[deriving(Show, Eq, PartialEq, Hash)]
+enum RoomDirection {
+    West,
+    East,
+    North,
+    South,
+    Up,
+    Down,
+    In,
+    Out,
+
+    None
+}
+
+struct Room {
+    description: String,
+    items: Vec<Item>,
+    direction_to_room: HashMap<RoomDirection, Room>,
+}
+
+impl Room {
+    fn new(description: &'static str) -> Room {
+        Room {
+            description: description.to_string(),
+            items: Vec::new(),
+            direction_to_room: HashMap::new()
+        }
+    }
+
+    fn add_direction(&mut self, direction: RoomDirection, room: Room) {
+        self.direction_to_room.insert(direction, room);
+    }
+}
+
+struct Item {
+    name: String,
+}
+
+struct Inventory {
+    items: Vec<Item>,
+}
+
+impl Inventory {
+    fn new() -> Inventory {
+        Inventory {
+            items: Vec::new()
+        }
+    }
+}
+
+struct Player {
+    name: String,
+    inventory: Inventory,
+}
+
+impl Player {
+    fn new(name: &'static str) -> Player {
+        Player {
+            name: name.to_string(),
+            inventory: Inventory::new()
+        }
+    }
+}
+
+impl TraversesWorld for Player {
+}
+
+impl Show for Player {
+    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
+        formatter.write_str("Player{ name:");
+        formatter.write_str(self.name.as_slice());
+        formatter.write_str(" }");
+        Ok(())
+    }
+}
+
+fn str_to_direction(to_parse: &str) -> RoomDirection {
+    match to_parse {
+        "w" | "west" => RoomDirection::West,
+        "e" | "east" => RoomDirection::East,
+        "n" | "north" => RoomDirection::North,
+        "s" | "south" => RoomDirection::South,
+        "in" => RoomDirection::In,
+        "out" => RoomDirection::Out,
+        "up" => RoomDirection::Up,
+        "down" => RoomDirection::Down,
+        _ => None //~ ERROR mismatched types
+    }
+}
+
+fn main() {
+    let mut player = Player::new("Test player");
+    let mut room = Room::new("A test room");
+    println!("Made a player: {}", player);
+    println!("Direction parse: {}", str_to_direction("east"));
+    match player.attemptTraverse(&room, "west") {
+        Ok(_) => println!("Was able to move west"),
+        Err(msg) => println!("Not able to move west: {}", msg)
+    };
+}
diff --git a/src/test/compile-fail/issue-17740.rs b/src/test/compile-fail/issue-17740.rs
new file mode 100644
index 00000000000..73f86fee903
--- /dev/null
+++ b/src/test/compile-fail/issue-17740.rs
@@ -0,0 +1,22 @@
+// 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.
+
+struct Foo<'a> {
+    data: &'a[u8],
+}
+
+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)
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-17913.rs b/src/test/compile-fail/issue-17913.rs
index 81f9ed991eb..3224edb381c 100644
--- a/src/test/compile-fail/issue-17913.rs
+++ b/src/test/compile-fail/issue-17913.rs
@@ -13,13 +13,13 @@
 #[cfg(target_word_size = "64")]
 fn main() {
     let n = 0u;
-    let a = box [&n,..0xF000000000000000u];
+    let a = box [&n; 0xF000000000000000u];
     println!("{}", a[0xFFFFFFu]);
 }
 
 #[cfg(target_word_size = "32")]
 fn main() {
     let n = 0u;
-    let a = box [&n,..0xFFFFFFFFu];
+    let a = box [&n; 0xFFFFFFFFu];
     println!("{}", a[0xFFFFFFu]);
 }
diff --git a/src/test/compile-fail/issue-18345.rs b/src/test/compile-fail/issue-18345.rs
index c8b3463b091..e93acb3f064 100644
--- a/src/test/compile-fail/issue-18345.rs
+++ b/src/test/compile-fail/issue-18345.rs
@@ -15,7 +15,6 @@ fn mapping<'f, R, T, U>(f: |T|: 'f -> U) -> &'f Transducer<'f, R, T, U> {
     |step| |r, x|
         step(r, f(x))
         //~^ ERROR the type of this value must be known in this context
-        //~| ERROR this function takes 1 parameter but 2 parameters were supplied
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-18532.rs b/src/test/compile-fail/issue-18532.rs
index ec44ab7b277..9cf922ae990 100644
--- a/src/test/compile-fail/issue-18532.rs
+++ b/src/test/compile-fail/issue-18532.rs
@@ -17,5 +17,4 @@
 fn main() {
     (return)((),());
     //~^ ERROR the type of this value must be known
-    //~| ERROR this function takes 1 parameter
 }
diff --git a/src/test/compile-fail/issue-18611.rs b/src/test/compile-fail/issue-18611.rs
index b2f204d7476..49eeccb2b0c 100644
--- a/src/test/compile-fail/issue-18611.rs
+++ b/src/test/compile-fail/issue-18611.rs
@@ -10,10 +10,9 @@
 
 #![feature(associated_types)]
 
-fn add_state(op:
-    <int as HasState>::State
-//~^ ERROR it is currently unsupported to access associated types except through a type parameter
-) {}
+fn add_state(op: <int as HasState>::State) {
+//~^ ERROR the trait `HasState` is not implemented for the type `int`
+}
 
 trait HasState {
     type State;
diff --git a/src/test/compile-fail/issue-19707.rs b/src/test/compile-fail/issue-19707.rs
new file mode 100644
index 00000000000..9affb44b744
--- /dev/null
+++ b/src/test/compile-fail/issue-19707.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(unboxed_closures)]
+#![allow(dead_code)]
+
+type foo = fn(&u8, &u8) -> &u8; //~ ERROR missing lifetime specifier
+//~^ HELP the signature does not say whether it is borrowed from argument 1 or argument 2
+
+fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {} //~ ERROR missing lifetime specifier
+//~^ HELP the signature does not say whether it is borrowed from argument 1 or argument 2
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/issue-5543.rs
index 0090dd544f6..bbd41b28f03 100644
--- a/src/test/compile-fail/issue-5543.rs
+++ b/src/test/compile-fail/issue-5543.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test
-
-use std::io::ReaderUtil;
-use std::io::Reader;
-
-fn bar(r:@ReaderUtil) -> String { r.read_line() }
+trait Foo {}
+impl Foo for u8 {}
 
 fn main() {
-    let r : @Reader = io::stdin();
-    let _m = bar(r as @ReaderUtil);
+    let r: Box<Foo> = box 5;
+    let _m: Box<Foo> = r as Box<Foo>;
+    //~^ ERROR `core::kinds::Sized` is not implemented for the type `Foo`
+    //~| ERROR `Foo` is not implemented for the type `Foo`
 }
diff --git a/src/test/compile-fail/issue-6977.rs b/src/test/compile-fail/issue-6977.rs
index d0ff116b42f..c2bd810abad 100644
--- a/src/test/compile-fail/issue-6977.rs
+++ b/src/test/compile-fail/issue-6977.rs
@@ -11,5 +11,5 @@
 // Trying to create a fixed-length vector with a negative size
 
 fn main() {
-      let _x = [0,..-1]; //~ ERROR found negative integer
+      let _x = [0; -1]; //~ ERROR found negative integer
 }
diff --git a/src/test/compile-fail/issue-7364.rs b/src/test/compile-fail/issue-7364.rs
index 2646edd7684..77836143f27 100644
--- a/src/test/compile-fail/issue-7364.rs
+++ b/src/test/compile-fail/issue-7364.rs
@@ -14,8 +14,7 @@ use std::cell::RefCell;
 // Regresion test for issue 7364
 static boxed: Box<RefCell<int>> = box RefCell::new(0);
 //~^ ERROR statics are not allowed to have custom pointers
-//~^^ ERROR: the trait `core::kinds::Sync` is not implemented for the type
-//~^^^ ERROR: the trait `core::kinds::Sync` is not implemented for the type
-//~^^^^ ERROR: the trait `core::kinds::Sync` is not implemented for the type
+//~| ERROR: the trait `core::kinds::Sync` is not implemented for the type
+//~| ERROR: the trait `core::kinds::Sync` is not implemented for the type
 
 fn main() { }
diff --git a/src/test/compile-fail/mut-not-freeze.rs b/src/test/compile-fail/mut-not-freeze.rs
index 4b058f6fdb3..95ebb8bd882 100644
--- a/src/test/compile-fail/mut-not-freeze.rs
+++ b/src/test/compile-fail/mut-not-freeze.rs
@@ -17,5 +17,4 @@ fn main() {
     f(x);
     //~^ ERROR `core::kinds::Sync` is not implemented
     //~^^ ERROR `core::kinds::Sync` is not implemented
-    //~^^^ ERROR `core::kinds::Sync` is not implemented
 }
diff --git a/src/test/compile-fail/range-1.rs b/src/test/compile-fail/range-1.rs
index ca7401dc26c..4af748661fd 100644
--- a/src/test/compile-fail/range-1.rs
+++ b/src/test/compile-fail/range-1.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // Test range syntax - type errors.
+#![feature(slicing_syntax)]
 
 pub fn main() {
     // Mixed types.
diff --git a/src/test/compile-fail/range-2.rs b/src/test/compile-fail/range-2.rs
index 40690bd844b..74c304884a0 100644
--- a/src/test/compile-fail/range-2.rs
+++ b/src/test/compile-fail/range-2.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // Test range syntax - borrow errors.
+#![feature(slicing_syntax)]
 
 pub fn main() {
     let r = {
diff --git a/src/test/compile-fail/removed-syntax-fixed-vec.rs b/src/test/compile-fail/removed-syntax-fixed-vec.rs
index 0a8420c19c3..6537e3ddd27 100644
--- a/src/test/compile-fail/removed-syntax-fixed-vec.rs
+++ b/src/test/compile-fail/removed-syntax-fixed-vec.rs
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-type v = [int * 3]; //~ ERROR expected one of `(`, `+`, `,`, `::`, `;`, or `]`, found `*`
+type v = [int * 3]; //~ ERROR expected one of `(`, `+`, `::`, `;`, or `]`, found `*`
diff --git a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs
index 9c6056bd72a..efde1f1b24d 100644
--- a/src/test/compile-fail/removed-syntax-mut-vec-ty.rs
+++ b/src/test/compile-fail/removed-syntax-mut-vec-ty.rs
@@ -10,4 +10,4 @@
 
 type v = [mut int];
     //~^  ERROR expected identifier, found keyword `mut`
-    //~^^ ERROR expected one of `(`, `+`, `,`, `::`, `;`, or `]`, found `int`
+    //~^^ ERROR expected one of `(`, `+`, `::`, `;`, or `]`, found `int`
diff --git a/src/test/compile-fail/resolve-conflict-type-vs-import.rs b/src/test/compile-fail/resolve-conflict-type-vs-import.rs
index de934286a7c..45b0314d2c0 100644
--- a/src/test/compile-fail/resolve-conflict-type-vs-import.rs
+++ b/src/test/compile-fail/resolve-conflict-type-vs-import.rs
@@ -15,4 +15,3 @@ struct Iter;
 
 fn main() {
 }
-
diff --git a/src/test/compile-fail/resolve-label.rs b/src/test/compile-fail/resolve-label.rs
new file mode 100644
index 00000000000..398b4f5859e
--- /dev/null
+++ b/src/test/compile-fail/resolve-label.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.
+
+fn f() {
+    'l: loop {
+        fn g() {
+            loop {
+                break 'l; //~ ERROR use of undeclared label
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/slice-2.rs b/src/test/compile-fail/slice-2.rs
index 63f79c808ae..24f710d2ae3 100644
--- a/src/test/compile-fail/slice-2.rs
+++ b/src/test/compile-fail/slice-2.rs
@@ -20,8 +20,4 @@ fn main() {
     x[Foo..]; //~ ERROR cannot take a slice of a value with type `Foo`
     x[..Foo]; //~ ERROR cannot take a slice of a value with type `Foo`
     x[Foo..Foo]; //~ ERROR cannot take a slice of a value with type `Foo`
-    x[mut]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
-    x[mut Foo..]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
-    x[mut ..Foo]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
-    x[mut Foo..Foo]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
 }
diff --git a/src/test/compile-fail/slice-mut-2.rs b/src/test/compile-fail/slice-mut-2.rs
index 6778ed88ff7..8970bcfd153 100644
--- a/src/test/compile-fail/slice-mut-2.rs
+++ b/src/test/compile-fail/slice-mut-2.rs
@@ -15,5 +15,6 @@
 fn main() {
     let x: &[int] = &[1, 2, 3, 4, 5];
     // Can't mutably slice an immutable slice
-    let y = x[mut 2..4]; //~ ERROR cannot borrow
+    let slice: &mut [int] = &mut [0, 1];
+    x[2..4] = slice; //~ ERROR cannot borrow
 }
diff --git a/src/test/compile-fail/slice-mut.rs b/src/test/compile-fail/slice-mut.rs
index cbfa3ed85fd..ad6b384d747 100644
--- a/src/test/compile-fail/slice-mut.rs
+++ b/src/test/compile-fail/slice-mut.rs
@@ -16,9 +16,4 @@ fn main() {
     let x: &[int] = &[1, 2, 3, 4, 5];
     // Immutable slices are not mutable.
     let y: &mut[_] = x[2..4]; //~ ERROR cannot borrow immutable dereference of `&`-pointer as mutabl
-
-    let x: &mut [int] = &mut [1, 2, 3, 4, 5];
-    // Can't borrow mutably twice
-    let y = x[mut 1..2];
-    let y = x[mut 4..5]; //~ERROR cannot borrow
 }
diff --git a/src/test/compile-fail/task-rng-isnt-sendable.rs b/src/test/compile-fail/task-rng-isnt-sendable.rs
index d96599404de..f673c3b7978 100644
--- a/src/test/compile-fail/task-rng-isnt-sendable.rs
+++ b/src/test/compile-fail/task-rng-isnt-sendable.rs
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ensure that the TaskRng isn't/doesn't become accidentally sendable.
+// ensure that the ThreadRng isn't/doesn't become accidentally sendable.
 
 use std::rand;
 
 fn test_send<S: Send>() {}
 
 pub fn main() {
-    test_send::<rand::TaskRng>();
+    test_send::<rand::ThreadRng>();
     //~^ ERROR `core::kinds::Send` is not implemented
     //~^^ ERROR `core::kinds::Send` is not implemented
 }
diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs
index 5fe8e435e68..c11b5d22878 100644
--- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs
+++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs
@@ -41,14 +41,14 @@ enum Boo {
     Quux(Bar<uint>),
 }
 
-struct Badness<T> {
+struct Badness<U> {
 //~^ ERROR not implemented
-    b: Foo<T>,
+    b: Foo<U>,
 }
 
-enum MoreBadness<T> {
+enum MoreBadness<V> {
 //~^ ERROR not implemented
-    EvenMoreBadness(Bar<T>),
+    EvenMoreBadness(Bar<V>),
 }
 
 trait PolyTrait<T> {
diff --git a/src/test/compile-fail/trait-object-safety.rs b/src/test/compile-fail/trait-object-safety.rs
new file mode 100644
index 00000000000..761bcd4968a
--- /dev/null
+++ b/src/test/compile-fail/trait-object-safety.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that static methods are not object-safe.
+
+trait Tr {
+    fn foo();
+}
+
+struct St;
+
+impl Tr for St {
+    fn foo() {}
+}
+
+fn main() {
+    let _: &Tr = &St; //~ ERROR cannot convert to a trait object because trait `Tr` is not
+}
diff --git a/src/test/compile-fail/trait-static-method-generic-inference.rs b/src/test/compile-fail/trait-static-method-generic-inference.rs
new file mode 100644
index 00000000000..651f663fc99
--- /dev/null
+++ b/src/test/compile-fail/trait-static-method-generic-inference.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.
+
+// Issue #3902. We are (at least currently) unable to infer `Self`
+// based on `T`, even though there is only a single impl, because of
+// the possibility of associated types and other things (basically: no
+// constraints on `Self` here at all).
+
+mod base {
+    pub trait HasNew<T> {
+        fn new() -> T;
+    }
+
+    pub struct Foo {
+        dummy: (),
+    }
+
+    impl HasNew<Foo> for Foo {
+        fn new() -> Foo {
+            Foo { dummy: () }
+        }
+    }
+}
+
+pub fn foo() {
+    let _f: base::Foo = base::HasNew::new();
+    //~^ ERROR type annotations required
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs
index 9ceae41d1a4..0a5aa1b7bd3 100644
--- a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs
+++ b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs
@@ -33,7 +33,7 @@ where T : Convert<U>
 }
 
 fn a() {
-    test(22_i32, 44); //~ ERROR unable to infer
+    test(22_i32, std::default::Default::default()); //~ ERROR type annotations required
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/transmute-different-sizes.rs b/src/test/compile-fail/transmute-different-sizes.rs
index abdfe983e3a..5c61212a7f5 100644
--- a/src/test/compile-fail/transmute-different-sizes.rs
+++ b/src/test/compile-fail/transmute-different-sizes.rs
@@ -21,7 +21,7 @@ unsafe fn f() {
 
 unsafe fn g<T>(x: &T) {
     let _: i8 = transmute(x);
-    //~^ ERROR transmute called on types with different sizes
+    //~^ ERROR transmute called on types with potentially different sizes
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/transmute-fat-pointers.rs b/src/test/compile-fail/transmute-fat-pointers.rs
new file mode 100644
index 00000000000..5e81a4cec22
--- /dev/null
+++ b/src/test/compile-fail/transmute-fat-pointers.rs
@@ -0,0 +1,41 @@
+// 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.
+
+// Tests that are conservative around thin/fat pointer mismatches.
+
+#![allow(dead_code)]
+
+use std::mem::transmute;
+
+fn a<T, Sized? U>(x: &[T]) -> &U {
+    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+}
+
+fn b<Sized? T, Sized? U>(x: &T) -> &U {
+    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+}
+
+fn c<T, U>(x: &T) -> &U {
+    unsafe { transmute(x) }
+}
+
+fn d<T, U>(x: &[T]) -> &[U] {
+    unsafe { transmute(x) }
+}
+
+fn e<Sized? T, U>(x: &T) -> &U {
+    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+}
+
+fn f<T, Sized? U>(x: &T) -> &U {
+    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/transmute-impl.rs b/src/test/compile-fail/transmute-impl.rs
new file mode 100644
index 00000000000..8b5a8c679b2
--- /dev/null
+++ b/src/test/compile-fail/transmute-impl.rs
@@ -0,0 +1,33 @@
+// 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.
+
+// Tests that are conservative around thin/fat pointer mismatches.
+
+#![allow(dead_code)]
+
+use std::mem::transmute;
+
+struct Foo<Sized? T> {
+    t: Box<T>
+}
+
+impl<Sized? T> Foo<T> {
+    fn m(x: &T) -> &int where T : Sized {
+        // OK here, because T : Sized is in scope.
+        unsafe { transmute(x) }
+    }
+
+    fn n(x: &T) -> &int {
+        // Not OK here, because T : Sized is not in scope.
+        unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+    }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/unsized-inherent-impl-self-type.rs b/src/test/compile-fail/unsized-inherent-impl-self-type.rs
new file mode 100644
index 00000000000..2c8a2b361d5
--- /dev/null
+++ b/src/test/compile-fail/unsized-inherent-impl-self-type.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.
+
+// Test sized-ness checking in substitution in impls.
+
+// impl - struct
+
+struct S5<Y>;
+
+impl<Sized? X> S5<X> { //~ ERROR not implemented
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/unsized-trait-impl-self-type.rs b/src/test/compile-fail/unsized-trait-impl-self-type.rs
new file mode 100644
index 00000000000..0f0a97fab4d
--- /dev/null
+++ b/src/test/compile-fail/unsized-trait-impl-self-type.rs
@@ -0,0 +1,22 @@
+// 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 sized-ness checking in substitution in impls.
+
+// impl - struct
+trait T3<Sized? Z> {
+}
+
+struct S5<Y>;
+
+impl<Sized? X> T3<X> for S5<X> { //~ ERROR not implemented
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs
new file mode 100644
index 00000000000..bdb652b168a
--- /dev/null
+++ b/src/test/compile-fail/unsized-trait-impl-trait-arg.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.
+
+// Test sized-ness checking in substitution in impls.
+
+// impl - unbounded
+trait T2<Z> {
+}
+struct S4<Sized? Y>;
+impl<Sized? X> T2<X> for S4<X> {
+    //~^ ERROR `core::kinds::Sized` is not implemented for the type `X`
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/unsized4.rs b/src/test/compile-fail/unsized4.rs
index a66c1d85009..0537fc1f94a 100644
--- a/src/test/compile-fail/unsized4.rs
+++ b/src/test/compile-fail/unsized4.rs
@@ -11,8 +11,9 @@
 // Test that bounds are sized-compatible.
 
 trait T {}
+
 fn f<Sized? Y: T>() {
-//~^ERROR incompatible bounds on type parameter `Y`, bound `T` does not allow unsized type
+//~^ERROR incompatible bounds on `Y`, bound `T` does not allow unsized type
 }
 
 pub fn main() {
diff --git a/src/test/compile-fail/unsized7.rs b/src/test/compile-fail/unsized7.rs
index fd9dffe00d2..c0e6ae1db92 100644
--- a/src/test/compile-fail/unsized7.rs
+++ b/src/test/compile-fail/unsized7.rs
@@ -21,23 +21,4 @@ impl<Sized? X: T> T1<X> for S3<X> {
     //~^ ERROR `core::kinds::Sized` is not implemented for the type `X`
 }
 
-// impl - unbounded
-trait T2<Z> {
-}
-struct S4<Sized? Y>;
-impl<Sized? X> T2<X> for S4<X> {
-    //~^ ERROR `core::kinds::Sized` is not implemented for the type `X`
-}
-
-// impl - struct
-trait T3<Sized? Z> {
-}
-struct S5<Y>;
-impl<Sized? X> T3<X> for S5<X> { //~ ERROR not implemented
-}
-
-impl<Sized? X> S5<X> { //~ ERROR not implemented
-}
-
-
 fn main() { }
diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs
index 48813ff142c..fa38482b21c 100644
--- a/src/test/compile-fail/variance-regions-direct.rs
+++ b/src/test/compile-fail/variance-regions-direct.rs
@@ -14,7 +14,7 @@
 // Regions that just appear in normal spots are contravariant:
 
 #[rustc_variance]
-struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[];[]]
+struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
     x: &'a int,
     y: &'b [int],
     c: &'c str
@@ -23,7 +23,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[];[]]
 // Those same annotations in function arguments become covariant:
 
 #[rustc_variance]
-struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[];[]]
+struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
     x: extern "Rust" fn(&'a int),
     y: extern "Rust" fn(&'b [int]),
     c: extern "Rust" fn(&'c str),
@@ -32,7 +32,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[];[]]
 // Mutability induces invariance:
 
 #[rustc_variance]
-struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[];[]]
+struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]]
     x: &'a mut &'b int,
 }
 
@@ -40,7 +40,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[];[]]
 // contravariant context:
 
 #[rustc_variance]
-struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[];[]]
+struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]]
     x: extern "Rust" fn(&'a mut &'b int),
 }
 
@@ -50,21 +50,21 @@ struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[];[]]
 // argument list occurs in an invariant context.
 
 #[rustc_variance]
-struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[];[]]
+struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[]]
     x: &'a mut extern "Rust" fn(&'b int),
 }
 
 // No uses at all is bivariant:
 
 #[rustc_variance]
-struct Test7<'a> { //~ ERROR regions=[[*];[];[];[]]
+struct Test7<'a> { //~ ERROR regions=[[*];[];[]]
     x: int
 }
 
 // Try enums too.
 
 #[rustc_variance]
-enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]]
+enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
     Test8A(extern "Rust" fn(&'a int)),
     Test8B(&'b [int]),
     Test8C(&'b mut &'c str),
diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs
index 0e8e52df456..c049fbc0fed 100644
--- a/src/test/compile-fail/variance-regions-indirect.rs
+++ b/src/test/compile-fail/variance-regions-indirect.rs
@@ -13,29 +13,29 @@
 // Try enums too.
 
 #[rustc_variance]
-enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[];[]]
+enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]]
     Test8A(extern "Rust" fn(&'a int)),
     Test8B(&'b [int]),
     Test8C(&'b mut &'c str),
 }
 
 #[rustc_variance]
-struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[];[]]
+struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]]
     f: Base<'z, 'y, 'x, 'w>
 }
 
 #[rustc_variance] // Combine - and + to yield o
-struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[];[]]
+struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]]
     f: Base<'a, 'a, 'b, 'c>
 }
 
 #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
-struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[];[]]
+struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]]
     f: Base<'a, 'b, 'a, 'c>
 }
 
 #[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
-struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]]
+struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
     f: Base<'a, 'b, 'c, 'a>
 }
 
diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs
index c576c5e2edd..c61f2ff79c0 100644
--- a/src/test/compile-fail/variance-trait-object-bound.rs
+++ b/src/test/compile-fail/variance-trait-object-bound.rs
@@ -19,7 +19,7 @@ use std::mem;
 trait T { fn foo(); }
 
 #[rustc_variance]
-struct TOption<'a> { //~ ERROR regions=[[-];[];[];[]]
+struct TOption<'a> { //~ ERROR regions=[[-];[];[]]
     v: Option<Box<T + 'a>>,
 }
 
diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs
index 54d34d1840c..4251f22b291 100644
--- a/src/test/debuginfo/basic-types-globals-metadata.rs
+++ b/src/test/debuginfo/basic-types-globals-metadata.rs
@@ -45,6 +45,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![omit_gdb_pretty_printer_section]
 
 
 static B: bool = false;
diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs
index bbb8c2423c3..a4d4ddfea53 100644
--- a/src/test/debuginfo/basic-types-globals.rs
+++ b/src/test/debuginfo/basic-types-globals.rs
@@ -50,6 +50,7 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 static B: bool = false;
 static I: int = -1;
diff --git a/src/test/debuginfo/basic-types-metadata.rs b/src/test/debuginfo/basic-types-metadata.rs
index b998f096a07..6aa228ec51b 100644
--- a/src/test/debuginfo/basic-types-metadata.rs
+++ b/src/test/debuginfo/basic-types-metadata.rs
@@ -48,6 +48,7 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
     let unit: () = ();
diff --git a/src/test/debuginfo/basic-types-mut-globals.rs b/src/test/debuginfo/basic-types-mut-globals.rs
index 435bfd98989..bc8cdaf8eac 100644
--- a/src/test/debuginfo/basic-types-mut-globals.rs
+++ b/src/test/debuginfo/basic-types-mut-globals.rs
@@ -83,6 +83,7 @@
 // gdb-check:$28 = 9.25
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 static mut B: bool = false;
 static mut I: int = -1;
diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs
index 8be91e3ee76..f61f49228cd 100644
--- a/src/test/debuginfo/basic-types.rs
+++ b/src/test/debuginfo/basic-types.rs
@@ -88,6 +88,7 @@
 // lldb-check:[...]$12 = 3.5
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
     let b: bool = false;
diff --git a/src/test/debuginfo/borrowed-basic.rs b/src/test/debuginfo/borrowed-basic.rs
index 00bee44d264..f4c31278cf6 100644
--- a/src/test/debuginfo/borrowed-basic.rs
+++ b/src/test/debuginfo/borrowed-basic.rs
@@ -109,6 +109,7 @@
 // lldb-check:[...]$12 = 3.5
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
     let bool_val: bool = true;
diff --git a/src/test/debuginfo/borrowed-c-style-enum.rs b/src/test/debuginfo/borrowed-c-style-enum.rs
index bbda6c93eba..c2da58f1583 100644
--- a/src/test/debuginfo/borrowed-c-style-enum.rs
+++ b/src/test/debuginfo/borrowed-c-style-enum.rs
@@ -41,6 +41,7 @@
 // lldb-check:[...]$2 = TheC
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 enum ABC { TheA, TheB, TheC }
 
diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs
index 9cda56a7743..d54869888f1 100644
--- a/src/test/debuginfo/borrowed-enum.rs
+++ b/src/test/debuginfo/borrowed-enum.rs
@@ -40,6 +40,7 @@
 // lldb-check:[...]$2 = TheOnlyCase(4820353753753434)
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 // The first element is to ensure proper alignment, irrespective of the machines word size. Since
 // the size of the discriminant value is machine dependent, this has be taken into account when
diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs
index 7e6cf41162c..e3cf438be43 100644
--- a/src/test/debuginfo/borrowed-struct.rs
+++ b/src/test/debuginfo/borrowed-struct.rs
@@ -64,6 +64,7 @@
 // lldb-check:[...]$6 = 26.5
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct SomeStruct {
     x: int,
diff --git a/src/test/debuginfo/borrowed-tuple.rs b/src/test/debuginfo/borrowed-tuple.rs
index 57c14450467..ce0930f2fbf 100644
--- a/src/test/debuginfo/borrowed-tuple.rs
+++ b/src/test/debuginfo/borrowed-tuple.rs
@@ -42,6 +42,7 @@
 
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
     let stack_val: (i16, f32) = (-14, -19f32);
diff --git a/src/test/debuginfo/borrowed-unique-basic.rs b/src/test/debuginfo/borrowed-unique-basic.rs
index 30787716c72..d152775a8ed 100644
--- a/src/test/debuginfo/borrowed-unique-basic.rs
+++ b/src/test/debuginfo/borrowed-unique-basic.rs
@@ -112,7 +112,7 @@
 // lldb-check:[...]$12 = 3.5
 
 #![allow(unused_variables)]
-
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
     let bool_box: Box<bool> = box true;
diff --git a/src/test/debuginfo/box.rs b/src/test/debuginfo/box.rs
index 59f0c8f2d65..5a70eb19041 100644
--- a/src/test/debuginfo/box.rs
+++ b/src/test/debuginfo/box.rs
@@ -32,6 +32,7 @@
 // lldb-check:[...]$1 = (2, 3.5)
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
     let a = box 1i;
diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs
index 8f77de7e6d3..f9d762bf99d 100644
--- a/src/test/debuginfo/boxed-struct.rs
+++ b/src/test/debuginfo/boxed-struct.rs
@@ -35,6 +35,7 @@
 // lldb-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct StructWithSomePadding {
     x: i16,
diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs
index 258c49afcc4..b0c5b2f21b9 100644
--- a/src/test/debuginfo/by-value-non-immediate-argument.rs
+++ b/src/test/debuginfo/by-value-non-immediate-argument.rs
@@ -71,6 +71,8 @@
 // lldb-check:[...]$6 = Case1 { x: 0, y: 8970181431921507452 }
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 #[deriving(Clone)]
 struct Struct {
     a: int,
diff --git a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
index 57a3e503d0a..6907313370e 100644
--- a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
+++ b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
@@ -46,6 +46,8 @@
 // lldb-check:[...]$2 = (4444.5, 5555, 6666, 7777.5)
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 trait Trait {
     fn method(self) -> Self;
 }
diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs
index 17e4110c2f1..f2dfc63d522 100644
--- a/src/test/debuginfo/c-style-enum-in-composite.rs
+++ b/src/test/debuginfo/c-style-enum-in-composite.rs
@@ -65,6 +65,7 @@
 // lldb-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9)
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use self::AnEnum::{OneHundred, OneThousand, OneMillion};
 use self::AnotherEnum::{MountainView, Toronto, Vienna};
diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs
index b0a0142f6dd..b62a8167eaf 100644
--- a/src/test/debuginfo/c-style-enum.rs
+++ b/src/test/debuginfo/c-style-enum.rs
@@ -99,6 +99,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![omit_gdb_pretty_printer_section]
 
 use self::AutoDiscriminant::{One, Two, Three};
 use self::ManualDiscriminant::{OneHundred, OneThousand, OneMillion};
diff --git a/src/test/debuginfo/closure-in-generic-function.rs b/src/test/debuginfo/closure-in-generic-function.rs
index 673b4676a95..84366ae7114 100644
--- a/src/test/debuginfo/closure-in-generic-function.rs
+++ b/src/test/debuginfo/closure-in-generic-function.rs
@@ -46,6 +46,8 @@
 // lldb-check:[...]$3 = 110
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 fn some_generic_fun<T1, T2>(a: T1, b: T2) -> (T2, T1) {
 
     let closure = |x, y| {
diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs
index 17e1651f9f6..b4688e4928a 100644
--- a/src/test/debuginfo/destructured-fn-argument.rs
+++ b/src/test/debuginfo/destructured-fn-argument.rs
@@ -311,6 +311,7 @@
 // lldb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use self::Univariant::Unit;
 
diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs
index 9935bb60364..364720d0e4f 100644
--- a/src/test/debuginfo/destructured-for-loop-variable.rs
+++ b/src/test/debuginfo/destructured-for-loop-variable.rs
@@ -152,6 +152,9 @@
 // lldb-check:[...]$23 = (34903493, 232323)
 // lldb-command:continue
 
+#![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
+
 struct Struct {
     x: i16,
     y: f32,
diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs
index 58db37888e6..d5a6b36f1fc 100644
--- a/src/test/debuginfo/destructured-local.rs
+++ b/src/test/debuginfo/destructured-local.rs
@@ -244,6 +244,7 @@
 
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use self::Univariant::Unit;
 
diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs
index 786868f6b89..f623a321922 100644
--- a/src/test/debuginfo/evec-in-struct.rs
+++ b/src/test/debuginfo/evec-in-struct.rs
@@ -51,6 +51,7 @@
 // lldb-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct NoPadding1 {
     x: [u32; 3],
diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs
index 53b3044b0f7..55c5c504064 100644
--- a/src/test/debuginfo/function-arg-initialization.rs
+++ b/src/test/debuginfo/function-arg-initialization.rs
@@ -222,10 +222,8 @@
 // lldb-command:continue
 
 
-
 #![allow(unused_variables)]
-
-
+#![omit_gdb_pretty_printer_section]
 
 fn immediate_args(a: int, b: bool, c: f64) {
     ::std::io::print("") // #break
diff --git a/src/test/debuginfo/function-arguments.rs b/src/test/debuginfo/function-arguments.rs
index 304745e3945..01136c11014 100644
--- a/src/test/debuginfo/function-arguments.rs
+++ b/src/test/debuginfo/function-arguments.rs
@@ -45,6 +45,9 @@
 // lldb-check:[...]$3 = 3000
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
 
     fun(111102, true);
diff --git a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs
index 3288fa4c0cb..e437e35db3a 100644
--- a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs
+++ b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs
@@ -245,6 +245,7 @@
 // lldb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 #[no_stack_check]
 fn immediate_args(a: int, b: bool, c: f64) {
diff --git a/src/test/debuginfo/function-prologue-stepping-regular.rs b/src/test/debuginfo/function-prologue-stepping-regular.rs
index dbeb87fd44a..05ea357389b 100644
--- a/src/test/debuginfo/function-prologue-stepping-regular.rs
+++ b/src/test/debuginfo/function-prologue-stepping-regular.rs
@@ -126,6 +126,7 @@
 // lldb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn immediate_args(a: int, b: bool, c: f64) {
     ()
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
index 8abb2cd5c26..092cd9edc70 100644
--- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
+++ b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
@@ -17,7 +17,6 @@
 // ignore-lldb
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// gdb-use-pretty-printer
 
 // gdb-command: run
 
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
index 76cf3c1149d..64c120e1ab3 100644
--- a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
+++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
@@ -13,7 +13,6 @@
 // ignore-lldb
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// gdb-use-pretty-printer
 
 // This test uses some GDB Python API features (e.g. accessing anonymous fields)
 // which are only available in newer GDB version. The following directive will
diff --git a/src/test/debuginfo/generic-function.rs b/src/test/debuginfo/generic-function.rs
index abfe95db51b..cefe67970e9 100644
--- a/src/test/debuginfo/generic-function.rs
+++ b/src/test/debuginfo/generic-function.rs
@@ -70,6 +70,7 @@
 // lldb-check:[...]$8 = ((5, Struct { a: 6, b: 7.5 }), (Struct { a: 6, b: 7.5 }, 5))
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 #[deriving(Clone)]
 struct Struct {
diff --git a/src/test/debuginfo/generic-functions-nested.rs b/src/test/debuginfo/generic-functions-nested.rs
index 069906b14fd..0f3fd556f18 100644
--- a/src/test/debuginfo/generic-functions-nested.rs
+++ b/src/test/debuginfo/generic-functions-nested.rs
@@ -70,6 +70,9 @@
 // lldb-check:[...]$7 = 2.5
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 fn outer<TA: Clone>(a: TA) {
     inner(a.clone(), 1i);
     inner(a.clone(), 2.5f64);
diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs
index 4c0c82efea3..0e358499a3d 100644
--- a/src/test/debuginfo/generic-method-on-generic-struct.rs
+++ b/src/test/debuginfo/generic-method-on-generic-struct.rs
@@ -112,6 +112,7 @@
 // lldb-check:[...]$14 = -10.5
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 struct Struct<T> {
     x: T
diff --git a/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs b/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs
index d69d432fcb3..bf755d379a6 100644
--- a/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs
+++ b/src/test/debuginfo/generic-static-method-on-struct-and-enum.rs
@@ -31,6 +31,9 @@
 // gdb-check:$5 = 5
 // gdb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 struct Struct {
     x: int
 }
diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs
index 5e967266421..992e7417913 100644
--- a/src/test/debuginfo/generic-struct-style-enum.rs
+++ b/src/test/debuginfo/generic-struct-style-enum.rs
@@ -29,6 +29,9 @@
 // gdb-command:print univariant
 // gdb-check:$4 = {{a = -1}}
 
+
+#![omit_gdb_pretty_printer_section]
+
 use self::Regular::{Case1, Case2, Case3};
 use self::Univariant::TheOnlyCase;
 
diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs
index 7d485a6f5d5..908968fd6b3 100644
--- a/src/test/debuginfo/generic-struct.rs
+++ b/src/test/debuginfo/generic-struct.rs
@@ -41,6 +41,9 @@
 // lldb-command:print float_int_float
 // lldb-check:[...]$3 = AGenericStruct<f64, generic-struct::AGenericStruct<int, f64>> { key: 6.5, value: AGenericStruct<int, f64> { key: 7, value: 8.5 } }
 
+
+#![omit_gdb_pretty_printer_section]
+
 struct AGenericStruct<TKey, TValue> {
     key: TKey,
     value: TValue
diff --git a/src/test/debuginfo/generic-trait-generic-static-default-method.rs b/src/test/debuginfo/generic-trait-generic-static-default-method.rs
index 0984f8c9fa2..4382861fd20 100644
--- a/src/test/debuginfo/generic-trait-generic-static-default-method.rs
+++ b/src/test/debuginfo/generic-trait-generic-static-default-method.rs
@@ -25,6 +25,7 @@
 // gdb-check:$4 = {3.5, {4, 5, 6}}
 // gdb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     x: int
diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs
index 74d5dd2adc8..f9dc9d1f055 100644
--- a/src/test/debuginfo/generic-tuple-style-enum.rs
+++ b/src/test/debuginfo/generic-tuple-style-enum.rs
@@ -48,6 +48,8 @@
 // lldb-command:print univariant
 // lldb-check:[...]$3 = TheOnlyCase(-1)
 
+#![omit_gdb_pretty_printer_section]
+
 use self::Regular::{Case1, Case2, Case3};
 use self::Univariant::TheOnlyCase;
 
diff --git a/src/test/debuginfo/include_string.rs b/src/test/debuginfo/include_string.rs
index f196938437a..25719a80286 100644
--- a/src/test/debuginfo/include_string.rs
+++ b/src/test/debuginfo/include_string.rs
@@ -36,6 +36,7 @@
 // lldb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 // This test case makes sure that debug info does not ICE when include_str is
 // used multiple times (see issue #11322).
diff --git a/src/test/debuginfo/issue12886.rs b/src/test/debuginfo/issue12886.rs
index e2dae2dc3f0..c6acc9a31fe 100644
--- a/src/test/debuginfo/issue12886.rs
+++ b/src/test/debuginfo/issue12886.rs
@@ -16,9 +16,11 @@
 
 // gdb-command:run
 // gdb-command:next
-// gdb-check:[...]32[...]s
+// gdb-check:[...]34[...]s
 // gdb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 // IF YOU MODIFY THIS FILE, BE CAREFUL TO ADAPT THE LINE NUMBERS IN THE DEBUGGER COMMANDS
 
 // This test makes sure that gdb does not set unwanted breakpoints in inlined functions. If a
diff --git a/src/test/debuginfo/lexical-scope-in-for-loop.rs b/src/test/debuginfo/lexical-scope-in-for-loop.rs
index 7636ffdb07d..3309ae13c9d 100644
--- a/src/test/debuginfo/lexical-scope-in-for-loop.rs
+++ b/src/test/debuginfo/lexical-scope-in-for-loop.rs
@@ -86,6 +86,8 @@
 // lldb-check:[...]$6 = 1000000
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
 
     let range = [1i, 2, 3];
diff --git a/src/test/debuginfo/lexical-scope-in-if.rs b/src/test/debuginfo/lexical-scope-in-if.rs
index 5bfe8371209..bc3a6945243 100644
--- a/src/test/debuginfo/lexical-scope-in-if.rs
+++ b/src/test/debuginfo/lexical-scope-in-if.rs
@@ -134,6 +134,7 @@
 // lldb-check:[...]$15 = -1
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
 
diff --git a/src/test/debuginfo/lexical-scope-in-match.rs b/src/test/debuginfo/lexical-scope-in-match.rs
index 6a956e06f24..37976ab3996 100644
--- a/src/test/debuginfo/lexical-scope-in-match.rs
+++ b/src/test/debuginfo/lexical-scope-in-match.rs
@@ -126,6 +126,7 @@
 // lldb-check:[...]$17 = 232
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     x: int,
diff --git a/src/test/debuginfo/lexical-scope-in-stack-closure.rs b/src/test/debuginfo/lexical-scope-in-stack-closure.rs
index 6666ddfbc82..d6e3a43eea0 100644
--- a/src/test/debuginfo/lexical-scope-in-stack-closure.rs
+++ b/src/test/debuginfo/lexical-scope-in-stack-closure.rs
@@ -70,6 +70,8 @@
 // lldb-check:[...]$5 = false
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
 
     let x = false;
diff --git a/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs b/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs
index 51ddc83a8d8..b295c6f37a7 100644
--- a/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs
+++ b/src/test/debuginfo/lexical-scope-in-unconditional-loop.rs
@@ -132,6 +132,8 @@
 // lldb-check:[...]$12 = 2
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
 
     let mut x = 0i;
diff --git a/src/test/debuginfo/lexical-scope-in-unique-closure.rs b/src/test/debuginfo/lexical-scope-in-unique-closure.rs
index fa7822495d5..be4085b63ab 100644
--- a/src/test/debuginfo/lexical-scope-in-unique-closure.rs
+++ b/src/test/debuginfo/lexical-scope-in-unique-closure.rs
@@ -70,6 +70,9 @@
 // lldb-check:[...]$5 = false
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
 
     let x = false;
diff --git a/src/test/debuginfo/lexical-scope-in-while.rs b/src/test/debuginfo/lexical-scope-in-while.rs
index bafff552cd3..c7a36ef9b82 100644
--- a/src/test/debuginfo/lexical-scope-in-while.rs
+++ b/src/test/debuginfo/lexical-scope-in-while.rs
@@ -132,6 +132,7 @@
 // lldb-check:[...]$12 = 2
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
 
diff --git a/src/test/debuginfo/lexical-scope-with-macro.rs b/src/test/debuginfo/lexical-scope-with-macro.rs
index 2c76f2ca7df..be52ffff1b4 100644
--- a/src/test/debuginfo/lexical-scope-with-macro.rs
+++ b/src/test/debuginfo/lexical-scope-with-macro.rs
@@ -112,6 +112,7 @@
 
 
 #![feature(macro_rules)]
+#![omit_gdb_pretty_printer_section]
 
 macro_rules! trivial {
     ($e1:expr) => ($e1)
diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs
index 41dee642fea..2f8b11ac283 100644
--- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs
+++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs
@@ -349,6 +349,7 @@
 
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
+#![omit_gdb_pretty_printer_section]
 
 static mut MUT_INT: int = 0;
 
diff --git a/src/test/debuginfo/limited-debuginfo.rs b/src/test/debuginfo/limited-debuginfo.rs
index 3a633fc5eec..35889ff8133 100644
--- a/src/test/debuginfo/limited-debuginfo.rs
+++ b/src/test/debuginfo/limited-debuginfo.rs
@@ -30,6 +30,7 @@
 
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     a: i64,
diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs
index 8cb8fae75cf..b1ebb124d4e 100644
--- a/src/test/debuginfo/method-on-enum.rs
+++ b/src/test/debuginfo/method-on-enum.rs
@@ -113,6 +113,8 @@
 // lldb-check:[...]$14 = -10
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 enum Enum {
     Variant1 { x: u16, y: u16 },
     Variant2 (u32)
diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs
index d4244ee27d4..68a6ac8c1f3 100644
--- a/src/test/debuginfo/method-on-generic-struct.rs
+++ b/src/test/debuginfo/method-on-generic-struct.rs
@@ -113,6 +113,8 @@
 // lldb-command:continue
 
 
+#![omit_gdb_pretty_printer_section]
+
 struct Struct<T> {
     x: T
 }
diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs
index ca00587ba44..84e74d4364c 100644
--- a/src/test/debuginfo/method-on-struct.rs
+++ b/src/test/debuginfo/method-on-struct.rs
@@ -112,6 +112,9 @@
 // lldb-check:[...]$14 = -10
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 struct Struct {
     x: int
 }
diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs
index e70f86a5367..f53bb11eac4 100644
--- a/src/test/debuginfo/method-on-trait.rs
+++ b/src/test/debuginfo/method-on-trait.rs
@@ -112,6 +112,9 @@
 // lldb-check:[...]$14 = -10
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 struct Struct {
     x: int
 }
diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs
index 31bdd20e409..6994c38818c 100644
--- a/src/test/debuginfo/method-on-tuple-struct.rs
+++ b/src/test/debuginfo/method-on-tuple-struct.rs
@@ -112,6 +112,9 @@
 // lldb-check:[...]$14 = -10
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 struct TupleStruct(int, f64);
 
 impl TupleStruct {
diff --git a/src/test/debuginfo/multiple-functions-equal-var-names.rs b/src/test/debuginfo/multiple-functions-equal-var-names.rs
index d5d085bfe50..cb21c13426a 100644
--- a/src/test/debuginfo/multiple-functions-equal-var-names.rs
+++ b/src/test/debuginfo/multiple-functions-equal-var-names.rs
@@ -45,6 +45,7 @@
 // lldb-check:[...]$2 = 30303
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn function_one() {
     let abc = 10101i;
diff --git a/src/test/debuginfo/multiple-functions.rs b/src/test/debuginfo/multiple-functions.rs
index a94785b892d..ef7c4ce2045 100644
--- a/src/test/debuginfo/multiple-functions.rs
+++ b/src/test/debuginfo/multiple-functions.rs
@@ -45,6 +45,7 @@
 // lldb-check:[...]$2 = 30303
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn function_one() {
     let a = 10101i;
diff --git a/src/test/debuginfo/name-shadowing-and-scope-nesting.rs b/src/test/debuginfo/name-shadowing-and-scope-nesting.rs
index 5d6dfb90794..d248c7e9819 100644
--- a/src/test/debuginfo/name-shadowing-and-scope-nesting.rs
+++ b/src/test/debuginfo/name-shadowing-and-scope-nesting.rs
@@ -94,6 +94,8 @@
 // lldb-check:[...]$11 = 20
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
     let x = false;
     let y = true;
diff --git a/src/test/debuginfo/nil-enum.rs b/src/test/debuginfo/nil-enum.rs
index 306dfed9895..f0eaf6acb61 100644
--- a/src/test/debuginfo/nil-enum.rs
+++ b/src/test/debuginfo/nil-enum.rs
@@ -23,6 +23,7 @@
 // gdb-check:$2 = {<No data fields>}
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 enum ANilEnum {}
 enum AnotherNilEnum {}
diff --git a/src/test/debuginfo/no-debug-attribute.rs b/src/test/debuginfo/no-debug-attribute.rs
index 826ac381c82..dcc1928ae50 100644
--- a/src/test/debuginfo/no-debug-attribute.rs
+++ b/src/test/debuginfo/no-debug-attribute.rs
@@ -24,6 +24,7 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn function_with_debuginfo() {
     let abc = 10u;
diff --git a/src/test/debuginfo/option-like-enum.rs b/src/test/debuginfo/option-like-enum.rs
index 333a430e351..333ad602cf1 100644
--- a/src/test/debuginfo/option-like-enum.rs
+++ b/src/test/debuginfo/option-like-enum.rs
@@ -68,6 +68,8 @@
 // lldb-check:[...]$7 = None
 
 
+#![omit_gdb_pretty_printer_section]
+
 // If a struct has exactly two variants, one of them is empty, and the other one
 // contains a non-nullable pointer, then this value is used as the discriminator.
 // The test cases in this file make sure that something readable is generated for
diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs
index 1140c2cdb44..84c0b8da02c 100644
--- a/src/test/debuginfo/packed-struct-with-destructor.rs
+++ b/src/test/debuginfo/packed-struct-with-destructor.rs
@@ -74,6 +74,7 @@
 
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 #[repr(packed)]
 struct Packed {
diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs
index 93941823fbc..97e6ee79952 100644
--- a/src/test/debuginfo/packed-struct.rs
+++ b/src/test/debuginfo/packed-struct.rs
@@ -60,6 +60,7 @@
 // lldb-check:[...]$5 = 40
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 #[repr(packed)]
 struct Packed {
diff --git a/src/test/debuginfo/recursive-enum.rs b/src/test/debuginfo/recursive-enum.rs
index f43caed0810..93348e7b53e 100644
--- a/src/test/debuginfo/recursive-enum.rs
+++ b/src/test/debuginfo/recursive-enum.rs
@@ -18,6 +18,7 @@
 // is taken from issue #11083.
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 pub struct Window<'a> {
     callbacks: WindowCallbacks<'a>
diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs
index 8cc0fdabfc2..90c32ad8da1 100644
--- a/src/test/debuginfo/recursive-struct.rs
+++ b/src/test/debuginfo/recursive-struct.rs
@@ -69,6 +69,7 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use self::Opt::{Empty, Val};
 
diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs
index 87fdb2c42c8..f8ef5b3d2fc 100644
--- a/src/test/debuginfo/self-in-default-method.rs
+++ b/src/test/debuginfo/self-in-default-method.rs
@@ -112,6 +112,7 @@
 // lldb-check:[...]$14 = -10
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     x: int
diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs
index 6f488230521..c2594df7d35 100644
--- a/src/test/debuginfo/self-in-generic-default-method.rs
+++ b/src/test/debuginfo/self-in-generic-default-method.rs
@@ -112,6 +112,7 @@
 // lldb-check:[...]$14 = -10.5
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     x: int
diff --git a/src/test/debuginfo/shadowed-argument.rs b/src/test/debuginfo/shadowed-argument.rs
index ead960c36df..c5c3664b07a 100644
--- a/src/test/debuginfo/shadowed-argument.rs
+++ b/src/test/debuginfo/shadowed-argument.rs
@@ -58,6 +58,9 @@
 // lldb-check:[...]$5 = 20
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 fn a_function(x: bool, y: bool) {
     zzz(); // #break
     sentinel();
diff --git a/src/test/debuginfo/shadowed-variable.rs b/src/test/debuginfo/shadowed-variable.rs
index fa56c1d1fb7..f384b756da6 100644
--- a/src/test/debuginfo/shadowed-variable.rs
+++ b/src/test/debuginfo/shadowed-variable.rs
@@ -58,6 +58,8 @@
 // lldb-check:[...]$5 = 20
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
     let x = false;
     let y = true;
diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs
index 2c2eedf4167..288e7461dd5 100644
--- a/src/test/debuginfo/simd.rs
+++ b/src/test/debuginfo/simd.rs
@@ -43,6 +43,7 @@
 
 #![allow(experimental)]
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use std::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2};
 
diff --git a/src/test/debuginfo/simple-lexical-scope.rs b/src/test/debuginfo/simple-lexical-scope.rs
index 4330a273258..5981c18494d 100644
--- a/src/test/debuginfo/simple-lexical-scope.rs
+++ b/src/test/debuginfo/simple-lexical-scope.rs
@@ -78,6 +78,9 @@
 // lldb-check:[...]$6 = false
 // lldb-command:continue
 
+
+#![omit_gdb_pretty_printer_section]
+
 fn main() {
     let x = false;
 
diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs
index 51241be921c..3015b16a0aa 100644
--- a/src/test/debuginfo/simple-struct.rs
+++ b/src/test/debuginfo/simple-struct.rs
@@ -95,8 +95,9 @@
 // lldb-command:print padding_at_end
 // lldb-check:[...]$5 = PaddingAtEnd { x: -10014, y: 10015 }
 
-#![allow(unused_variables)];
-#![allow(dead_code)];
+#![allow(unused_variables)]
+#![allow(dead_code)]
+#![omit_gdb_pretty_printer_section]
 
 struct NoPadding16 {
     x: u16,
diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs
index bbc9941e013..78184fab7d3 100644
--- a/src/test/debuginfo/simple-tuple.rs
+++ b/src/test/debuginfo/simple-tuple.rs
@@ -92,6 +92,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![omit_gdb_pretty_printer_section]
 
 static mut NO_PADDING_8: (i8, u8) = (-50, 50);
 static mut NO_PADDING_16: (i16, i16, u16) = (-1, 2, 3);
diff --git a/src/test/debuginfo/static-method-on-struct-and-enum.rs b/src/test/debuginfo/static-method-on-struct-and-enum.rs
index f808e7f8a90..59ee300b3e3 100644
--- a/src/test/debuginfo/static-method-on-struct-and-enum.rs
+++ b/src/test/debuginfo/static-method-on-struct-and-enum.rs
@@ -54,6 +54,8 @@
 // lldb-check:[...]$4 = 5
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 struct Struct {
     x: int
 }
diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs
index 68281cb2230..6f801a7d587 100644
--- a/src/test/debuginfo/struct-in-enum.rs
+++ b/src/test/debuginfo/struct-in-enum.rs
@@ -42,6 +42,7 @@
 // lldb-check:[...]$2 = TheOnlyCase(Struct { x: 123, y: 456, z: 789 })
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2};
 use self::Univariant::TheOnlyCase;
diff --git a/src/test/debuginfo/struct-in-struct.rs b/src/test/debuginfo/struct-in-struct.rs
index 4a7588b0bec..3f819c92e10 100644
--- a/src/test/debuginfo/struct-in-struct.rs
+++ b/src/test/debuginfo/struct-in-struct.rs
@@ -57,6 +57,7 @@
 // lldb-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct Simple {
     x: i32
diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs
index 48c6c2d79fb..f6d4627082f 100644
--- a/src/test/debuginfo/struct-style-enum.rs
+++ b/src/test/debuginfo/struct-style-enum.rs
@@ -49,6 +49,7 @@
 // lldb-check:[...]$3 = TheOnlyCase { a: -1 }
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2, Case3};
 use self::Univariant::TheOnlyCase;
diff --git a/src/test/debuginfo/struct-with-destructor.rs b/src/test/debuginfo/struct-with-destructor.rs
index 854ba2171eb..743f5ac5ff4 100644
--- a/src/test/debuginfo/struct-with-destructor.rs
+++ b/src/test/debuginfo/struct-with-destructor.rs
@@ -45,6 +45,7 @@
 // lldb-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct NoDestructor {
     x: i32,
diff --git a/src/test/debuginfo/trait-generic-static-default-method.rs b/src/test/debuginfo/trait-generic-static-default-method.rs
index 8d565a323ac..2ecafb02ae5 100644
--- a/src/test/debuginfo/trait-generic-static-default-method.rs
+++ b/src/test/debuginfo/trait-generic-static-default-method.rs
@@ -45,6 +45,8 @@
 // lldb-check:[...]$3 = (1, 2, 3)
 // lldb-command:continue
 
+#![omit_gdb_pretty_printer_section]
+
 struct Struct {
     x: int
 }
diff --git a/src/test/debuginfo/trait-pointers.rs b/src/test/debuginfo/trait-pointers.rs
index d73c3cf0f77..9f8c0aa06e6 100644
--- a/src/test/debuginfo/trait-pointers.rs
+++ b/src/test/debuginfo/trait-pointers.rs
@@ -16,6 +16,7 @@
 // lldb-command:run
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 trait Trait {
     fn method(&self) -> int { 0 }
diff --git a/src/test/debuginfo/tuple-in-struct.rs b/src/test/debuginfo/tuple-in-struct.rs
index 02492bf1aa2..3d28490c0cf 100644
--- a/src/test/debuginfo/tuple-in-struct.rs
+++ b/src/test/debuginfo/tuple-in-struct.rs
@@ -41,6 +41,7 @@
 // gdb-check:$10 = {x = {{40, 41, 42}, {43, 44}}, y = {45, 46, 47, 48}}
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct NoPadding1 {
     x: (i32, i32),
diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs
index 30fdd8c5530..b1228f7a884 100644
--- a/src/test/debuginfo/tuple-in-tuple.rs
+++ b/src/test/debuginfo/tuple-in-tuple.rs
@@ -57,6 +57,7 @@
 // lldb-check:[...]$6 = ((21, 22), 23)
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 fn main() {
     let no_padding1: ((u32, u32), u32, u32) = ((0, 1), 2, 3);
diff --git a/src/test/debuginfo/tuple-struct.rs b/src/test/debuginfo/tuple-struct.rs
index 62c150878cf..0960ab5834d 100644
--- a/src/test/debuginfo/tuple-struct.rs
+++ b/src/test/debuginfo/tuple-struct.rs
@@ -62,6 +62,9 @@
 // to all fields having the name "<unnamed_field>"). Otherwise they are handled the same a normal
 // structs.
 
+
+#![omit_gdb_pretty_printer_section]
+
 struct NoPadding16(u16, i16);
 struct NoPadding32(i32, f32, u32);
 struct NoPadding64(f64, i64, u64);
diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs
index 07a0f169606..f205f484f25 100644
--- a/src/test/debuginfo/tuple-style-enum.rs
+++ b/src/test/debuginfo/tuple-style-enum.rs
@@ -49,6 +49,7 @@
 // lldb-check:[...]$3 = TheOnlyCase(-1)
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2, Case3};
 use self::Univariant::TheOnlyCase;
diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs
index 286c44667c5..ddcbfdcceee 100644
--- a/src/test/debuginfo/type-names.rs
+++ b/src/test/debuginfo/type-names.rs
@@ -173,6 +173,8 @@
 // gdb-command:whatis stack_closure2
 // gdb-check:type = struct (&mut|i8, f32| -> f32, uint)
 
+#![omit_gdb_pretty_printer_section]
+
 use self::Enum1::{Variant1_1, Variant1_2};
 use std::ptr;
 
diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs
index 3c0a4a21b4f..3d028eb1077 100644
--- a/src/test/debuginfo/unique-enum.rs
+++ b/src/test/debuginfo/unique-enum.rs
@@ -42,6 +42,7 @@
 // lldb-check:[...]$2 = TheOnlyCase(123234)
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 // The first element is to ensure proper alignment, irrespective of the machines word size. Since
 // the size of the discriminant value is machine dependent, this has be taken into account when
diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs
index f3ee711e8fd..99d67c60516 100644
--- a/src/test/debuginfo/var-captured-in-nested-closure.rs
+++ b/src/test/debuginfo/var-captured-in-nested-closure.rs
@@ -79,6 +79,7 @@
 // lldb-command:continue
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     a: int,
diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs
index fca47ed47bd..b34749260f3 100644
--- a/src/test/debuginfo/var-captured-in-sendable-closure.rs
+++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs
@@ -42,6 +42,7 @@
 
 #![allow(unused_variables)]
 #![feature(unboxed_closures)]
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     a: int,
diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs
index 761d0f0be8f..f474e8d1317 100644
--- a/src/test/debuginfo/var-captured-in-stack-closure.rs
+++ b/src/test/debuginfo/var-captured-in-stack-closure.rs
@@ -72,6 +72,7 @@
 
 #![feature(unboxed_closures)]
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 struct Struct {
     a: int,
diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs
index dfe16452d85..70211d74d88 100644
--- a/src/test/debuginfo/vec-slices.rs
+++ b/src/test/debuginfo/vec-slices.rs
@@ -78,6 +78,7 @@
 
 #![allow(unused_variables)]
 #![feature(slicing_syntax)]
+#![omit_gdb_pretty_printer_section]
 
 struct AStruct {
     x: i16,
diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs
index 00c93653cf4..92a490206b6 100644
--- a/src/test/debuginfo/vec.rs
+++ b/src/test/debuginfo/vec.rs
@@ -29,6 +29,7 @@
 // lldb-check:[...]$0 = [1, 2, 3]
 
 #![allow(unused_variables)]
+#![omit_gdb_pretty_printer_section]
 
 static mut VECT: [i32; 3] = [1, 2, 3];
 
diff --git a/src/test/pretty/issue-4264.rs b/src/test/pretty/issue-4264.rs
index ad0954e6eab..b481e109e1a 100644
--- a/src/test/pretty/issue-4264.rs
+++ b/src/test/pretty/issue-4264.rs
@@ -14,35 +14,35 @@
 
 // #4264 fixed-length vector types
 
-pub fn foo(_: [int, ..3]) {}
+pub fn foo(_: [int; 3]) {}
 
 pub fn bar() {
     const FOO: uint = 5u - 4u;
-    let _: [(), ..FOO] = [()];
+    let _: [(); FOO] = [()];
 
-    let _ : [(), ..1u] = [()];
+    let _ : [(); 1u] = [()];
 
-    let _ = &([1i,2,3]) as *const _ as *const [int, ..3u];
+    let _ = &([1i,2,3]) as *const _ as *const [int; 3u];
 
     format!("test");
 }
 
-pub type Foo = [int, ..3u];
+pub type Foo = [int; 3u];
 
 pub struct Bar {
-    pub x: [int, ..3u]
+    pub x: [int; 3u]
 }
 
-pub struct TupleBar([int, ..4u]);
+pub struct TupleBar([int; 4u]);
 
 pub enum Baz {
-    BazVariant([int, ..5u])
+    BazVariant([int; 5u])
 }
 
 pub fn id<T>(x: T) -> T { x }
 
 pub fn use_id() {
-    let _ = id::<[int, ..3u]>([1,2,3]);
+    let _ = id::<[int; 3u]>([1,2,3]);
 }
 
 
diff --git a/src/test/compile-fail/issue-6458-1.rs b/src/test/run-fail/issue-6458-1.rs
index 52a57fa2f44..631517f6a3c 100644
--- a/src/test/compile-fail/issue-6458-1.rs
+++ b/src/test/run-fail/issue-6458-1.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// error-pattern:explicit panic
+
 fn foo<T>(t: T) {}
 fn main() { foo(panic!()) }
-    //~^ ERROR type annotations required
diff --git a/src/test/run-make/compiler-lookup-paths/Makefile b/src/test/run-make/compiler-lookup-paths/Makefile
new file mode 100644
index 00000000000..032e0882ff8
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/Makefile
@@ -0,0 +1,30 @@
+-include ../tools.mk
+
+all: $(TMPDIR)/libnative.a
+	mkdir -p $(TMPDIR)/crate
+	mkdir -p $(TMPDIR)/native
+	mv $(TMPDIR)/libnative.a $(TMPDIR)/native
+	$(RUSTC) a.rs
+	mv $(TMPDIR)/liba.rlib $(TMPDIR)/crate
+	$(RUSTC) b.rs -L $(TMPDIR)/crate:native && exit 1 || exit 0
+	$(RUSTC) b.rs -L $(TMPDIR)/crate:dependency && exit 1 || exit 0
+	$(RUSTC) b.rs -L $(TMPDIR)/crate:crate
+	$(RUSTC) b.rs -L $(TMPDIR)/crate
+	$(RUSTC) c.rs -L $(TMPDIR)/crate:native && exit 1 || exit 0
+	$(RUSTC) c.rs -L $(TMPDIR)/crate:crate && exit 1 || exit 0
+	$(RUSTC) c.rs -L $(TMPDIR)/crate:dependency
+	$(RUSTC) c.rs -L $(TMPDIR)/crate
+	$(RUSTC) d.rs -L $(TMPDIR)/native:dependency && exit 1 || exit 0
+	$(RUSTC) d.rs -L $(TMPDIR)/native:crate && exit 1 || exit 0
+	$(RUSTC) d.rs -L $(TMPDIR)/native:native
+	$(RUSTC) d.rs -L $(TMPDIR)/native
+	mkdir -p $(TMPDIR)/e1
+	mkdir -p $(TMPDIR)/e2
+	$(RUSTC) e.rs -o $(TMPDIR)/e1/libe.rlib
+	$(RUSTC) e.rs -o $(TMPDIR)/e2/libe.rlib
+	$(RUSTC) f.rs -L $(TMPDIR)/e1 -L $(TMPDIR)/e2 && exit 1 || exit 0
+	$(RUSTC) f.rs -L $(TMPDIR)/e1:crate -L $(TMPDIR)/e2 && exit 1 || exit 0
+	$(RUSTC) f.rs -L $(TMPDIR)/e1:crate -L $(TMPDIR)/e2:crate && exit 1 || exit 0
+	$(RUSTC) f.rs -L $(TMPDIR)/e1:native -L $(TMPDIR)/e2
+	$(RUSTC) f.rs -L $(TMPDIR)/e1:dependency -L $(TMPDIR)/e2
+	$(RUSTC) f.rs -L $(TMPDIR)/e1:dependency -L $(TMPDIR)/e2:crate
diff --git a/src/test/run-make/compiler-lookup-paths/a.rs b/src/test/run-make/compiler-lookup-paths/a.rs
new file mode 100644
index 00000000000..4ddf231fba2
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/a.rs
@@ -0,0 +1,11 @@
+// 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.
+
+#![crate_type = "lib"]
diff --git a/src/test/run-make/compiler-lookup-paths/b.rs b/src/test/run-make/compiler-lookup-paths/b.rs
new file mode 100644
index 00000000000..c38300f976e
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/b.rs
@@ -0,0 +1,12 @@
+// 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.
+
+#![crate_type = "lib"]
+extern crate a;
diff --git a/src/test/run-make/compiler-lookup-paths/c.rs b/src/test/run-make/compiler-lookup-paths/c.rs
new file mode 100644
index 00000000000..8a801d589fb
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/c.rs
@@ -0,0 +1,13 @@
+// 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.
+
+#![crate_type = "lib"]
+extern crate b;
+
diff --git a/src/test/run-make/compiler-lookup-paths/d.rs b/src/test/run-make/compiler-lookup-paths/d.rs
new file mode 100644
index 00000000000..295b6e00e41
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/d.rs
@@ -0,0 +1,14 @@
+// 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.
+
+#![crate_type = "rlib"]
+
+#[link(name = "native", kind = "static")]
+extern {}
diff --git a/src/test/run-make/compiler-lookup-paths/e.rs b/src/test/run-make/compiler-lookup-paths/e.rs
new file mode 100644
index 00000000000..c0407aba7c9
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/e.rs
@@ -0,0 +1,12 @@
+// 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.
+
+#![crate_name = "e"]
+#![crate_type = "rlib"]
diff --git a/src/test/run-make/compiler-lookup-paths/f.rs b/src/test/run-make/compiler-lookup-paths/f.rs
new file mode 100644
index 00000000000..e6160422576
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/f.rs
@@ -0,0 +1,12 @@
+// 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.
+
+#![crate_type = "rlib"]
+extern crate e;
diff --git a/src/test/run-make/compiler-lookup-paths/native.c b/src/test/run-make/compiler-lookup-paths/native.c
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/src/test/run-make/compiler-lookup-paths/native.c
diff --git a/src/test/run-make/staticlib-blank-lib/Makefile b/src/test/run-make/staticlib-blank-lib/Makefile
index c56d1212047..5878eec66ba 100644
--- a/src/test/run-make/staticlib-blank-lib/Makefile
+++ b/src/test/run-make/staticlib-blank-lib/Makefile
@@ -1,6 +1,6 @@
 -include ../tools.mk
 
 all:
-	ar crus libfoo.a foo.rs
-	ar d libfoo.a foo.rs
+	ar crus $(TMPDIR)/libfoo.a foo.rs
+	ar d $(TMPDIR)/libfoo.a foo.rs
 	$(RUSTC) foo.rs
diff --git a/src/test/run-make/unicode-input/multiple_files.rs b/src/test/run-make/unicode-input/multiple_files.rs
index 2aa4264225c..88d8f10e709 100644
--- a/src/test/run-make/unicode-input/multiple_files.rs
+++ b/src/test/run-make/unicode-input/multiple_files.rs
@@ -10,7 +10,7 @@
 
 use std::{char, os};
 use std::io::{File, Command};
-use std::rand::{task_rng, Rng};
+use std::rand::{thread_rng, Rng};
 
 // creates unicode_input_multiple_files_{main,chars}.rs, where the
 // former imports the latter. `_chars` just contains an identifier
@@ -19,7 +19,7 @@ use std::rand::{task_rng, Rng};
 // this span used to upset the compiler).
 
 fn random_char() -> char {
-    let mut rng = task_rng();
+    let mut rng = thread_rng();
     // a subset of the XID_start Unicode table (ensuring that the
     // compiler doesn't fail with an "unrecognised token" error)
     let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
diff --git a/src/test/run-make/unicode-input/span_length.rs b/src/test/run-make/unicode-input/span_length.rs
index 7b096d7d583..f83734b1502 100644
--- a/src/test/run-make/unicode-input/span_length.rs
+++ b/src/test/run-make/unicode-input/span_length.rs
@@ -10,7 +10,7 @@
 
 use std::{char, os};
 use std::io::{File, Command};
-use std::rand::{task_rng, Rng};
+use std::rand::{thread_rng, Rng};
 
 // creates a file with `fn main() { <random ident> }` and checks the
 // compiler emits a span of the appropriate length (for the
@@ -18,7 +18,7 @@ use std::rand::{task_rng, Rng};
 // points, but should be the number of graphemes (FIXME #7043)
 
 fn random_char() -> char {
-    let mut rng = task_rng();
+    let mut rng = thread_rng();
     // a subset of the XID_start Unicode table (ensuring that the
     // compiler doesn't fail with an "unrecognised token" error)
     let (lo, hi): (u32, u32) = match rng.gen_range(1u32, 4u32 + 1) {
@@ -38,7 +38,7 @@ fn main() {
     let main_file = tmpdir.join("span_main.rs");
 
     for _ in range(0u, 100) {
-        let n = task_rng().gen_range(3u, 20);
+        let n = thread_rng().gen_range(3u, 20);
 
         {
             let _ = write!(&mut File::create(&main_file).unwrap(),
diff --git a/src/test/run-pass/associated-types-basic.rs b/src/test/run-pass/associated-types-basic.rs
new file mode 100644
index 00000000000..fcfcce3ff1b
--- /dev/null
+++ b/src/test/run-pass/associated-types-basic.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.
+
+#![feature(associated_types)]
+
+trait Foo {
+    type T;
+}
+
+impl Foo for i32 {
+    type T = int;
+}
+
+fn main() {
+    let x: <i32 as Foo>::T = 22;
+    let y: int = 44;
+    assert_eq!(x * 2, y);
+}
+
diff --git a/src/test/run-pass/associated-types-binding-in-where-clause.rs b/src/test/run-pass/associated-types-binding-in-where-clause.rs
new file mode 100644
index 00000000000..c3300c52935
--- /dev/null
+++ b/src/test/run-pass/associated-types-binding-in-where-clause.rs
@@ -0,0 +1,47 @@
+// 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 equality constraints on associated types in a where clause.
+
+#![feature(associated_types)]
+
+pub trait Foo {
+    type A;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+#[deriving(PartialEq)]
+struct Bar;
+
+impl Foo for int {
+    type A = uint;
+    fn boo(&self) -> uint { 42 }
+}
+
+impl Foo for char {
+    type A = Bar;
+    fn boo(&self) -> Bar { Bar }
+}
+
+fn foo_bar<I: Foo<A=Bar>>(x: I) -> Bar {
+    x.boo()
+}
+
+fn foo_uint<I: Foo<A=uint>>(x: I) -> uint {
+    x.boo()
+}
+
+pub fn main() {
+    let a = 42i;
+    foo_uint(a);
+
+    let a = 'a';
+    foo_bar(a);
+}
diff --git a/src/test/run-pass/associated-types-bound.rs b/src/test/run-pass/associated-types-bound.rs
new file mode 100644
index 00000000000..db5119132cc
--- /dev/null
+++ b/src/test/run-pass/associated-types-bound.rs
@@ -0,0 +1,53 @@
+// 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 equality constraints on associated types in a where clause.
+
+#![feature(associated_types)]
+
+pub trait ToInt {
+    fn to_int(&self) -> int;
+}
+
+impl ToInt for int {
+    fn to_int(&self) -> int { *self }
+}
+
+impl ToInt for uint {
+    fn to_int(&self) -> int { *self as int }
+}
+
+pub trait GetToInt
+{
+    type R : ToInt;
+
+    fn get(&self) -> <Self as GetToInt>::R;
+}
+
+impl GetToInt for int {
+    type R = int;
+    fn get(&self) -> int { *self }
+}
+
+impl GetToInt for uint {
+    type R = uint;
+    fn get(&self) -> uint { *self }
+}
+
+fn foo<G>(g: G) -> int
+    where G : GetToInt
+{
+    ToInt::to_int(&g.get())
+}
+
+pub fn main() {
+    assert_eq!(foo(22i), 22i);
+    assert_eq!(foo(22u), 22i);
+}
diff --git a/src/test/run-pass/associated-types-cc.rs b/src/test/run-pass/associated-types-cc.rs
new file mode 100644
index 00000000000..c0cf917aa41
--- /dev/null
+++ b/src/test/run-pass/associated-types-cc.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.
+
+// aux-build:associated-types-cc-lib.rs
+
+// Test that we are able to reference cross-crate traits that employ
+// associated types.
+
+#![feature(associated_types)]
+
+extern crate "associated-types-cc-lib" as bar;
+
+use bar::Bar;
+
+fn foo<B:Bar>(b: B) -> <B as Bar>::T {
+    Bar::get(None::<B>)
+}
+
+fn main() {
+    println!("{}", foo(3i));
+}
diff --git a/src/test/run-pass/associated-types-constant-type.rs b/src/test/run-pass/associated-types-constant-type.rs
new file mode 100644
index 00000000000..ea2cf84b757
--- /dev/null
+++ b/src/test/run-pass/associated-types-constant-type.rs
@@ -0,0 +1,42 @@
+// 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(associated_types)]
+
+trait SignedUnsigned {
+    type Opposite;
+    fn convert(self) -> Self::Opposite;
+}
+
+impl SignedUnsigned for int {
+    type Opposite = uint;
+
+    fn convert(self) -> uint {
+        self as uint
+    }
+}
+
+impl SignedUnsigned for uint {
+    type Opposite = int;
+
+    fn convert(self) -> int {
+        self as int
+    }
+}
+
+fn get(x: int) -> <int as SignedUnsigned>::Opposite {
+    x.convert()
+}
+
+fn main() {
+    let x = get(22);
+    assert_eq!(22u, x);
+}
+
diff --git a/src/test/run-pass/associated-types-eq-obj.rs b/src/test/run-pass/associated-types-eq-obj.rs
new file mode 100644
index 00000000000..f0343a743cb
--- /dev/null
+++ b/src/test/run-pass/associated-types-eq-obj.rs
@@ -0,0 +1,34 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test equality constraints on associated types inside of an object type
+
+#![feature(associated_types)]
+
+pub trait Foo {
+    type A;
+    fn boo(&self) -> <Self as Foo>::A;
+}
+
+struct Bar;
+
+impl Foo for char {
+    type A = Bar;
+    fn boo(&self) -> Bar { Bar }
+}
+
+fn baz(x: &Foo<A=Bar>) -> Bar {
+    x.boo()
+}
+
+pub fn main() {
+    let a = 'a';
+    baz(&a);
+}
diff --git a/src/test/run-pass/associated-types-impl-redirect.rs b/src/test/run-pass/associated-types-impl-redirect.rs
new file mode 100644
index 00000000000..a28cf346336
--- /dev/null
+++ b/src/test/run-pass/associated-types-impl-redirect.rs
@@ -0,0 +1,58 @@
+// 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 how resolving a projection interacts with inference.  In this
+// case, we were eagerly unifying the type variable for the iterator
+// type with `I` from the where clause, ignoring the in-scope `impl`
+// for `ByRef`. The right answer was to consider the result ambiguous
+// until more type information was available.
+
+// ignore-pretty -- FIXME(#17362)
+
+#![feature(associated_types, lang_items, unboxed_closures)]
+#![no_implicit_prelude]
+
+use std::option::Option::{None, Some, mod};
+
+trait Iterator {
+    type Item;
+
+    fn next(&mut self) -> Option<Self::Item>;
+}
+
+trait IteratorExt: Iterator {
+    fn by_ref(&mut self) -> ByRef<Self> {
+        ByRef(self)
+    }
+}
+
+impl<I> IteratorExt for I where I: Iterator {}
+
+struct ByRef<'a, I: 'a + Iterator>(&'a mut I);
+
+impl<'a, I: Iterator> Iterator for ByRef<'a, I> {
+    type Item = I::Item;
+
+    fn next(&mut self) -> Option< <I as Iterator>::Item > {
+        self.0.next()
+    }
+}
+
+fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
+
+fn test<A, I: Iterator<Item=A>>(mut it: I) {
+    is_iterator_of::<A, _>(&it.by_ref());
+}
+
+fn test2<A, I1: Iterator<Item=A>, I2: Iterator<Item=I1::Item>>(mut it: I2) {
+    is_iterator_of::<A, _>(&it)
+}
+
+fn main() { }
diff --git a/src/test/run-pass/associated-types-issue-20371.rs b/src/test/run-pass/associated-types-issue-20371.rs
new file mode 100644
index 00000000000..a6fb2b9e2ea
--- /dev/null
+++ b/src/test/run-pass/associated-types-issue-20371.rs
@@ -0,0 +1,17 @@
+// 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 we are able to have an impl that defines an associated type
+// before the actual trait.
+
+#![feature(associated_types)]
+impl X for f64 { type Y = int; }
+trait X {type Y; }
+fn main() {}
diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs
new file mode 100644
index 00000000000..0fd47720421
--- /dev/null
+++ b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs
@@ -0,0 +1,41 @@
+// 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 we normalize associated types that appear in bounds; if
+// we didn't, the call to `self.split2()` fails to type check.
+
+#![feature(associated_types)]
+
+struct Splits<'a, T, P>;
+struct SplitsN<I>;
+
+trait SliceExt2 for Sized? {
+    type Item;
+
+    fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P>
+        where P: FnMut(&Self::Item) -> bool;
+    fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, Self::Item, P>>
+        where P: FnMut(&Self::Item) -> bool;
+}
+
+impl<T> SliceExt2 for [T] {
+    type Item = T;
+
+    fn split2<P>(&self, pred: P) -> Splits<T, P> where P: FnMut(&T) -> bool {
+        loop {}
+    }
+
+    fn splitn2<P>(&self, n: uint, pred: P) -> SplitsN<Splits<T, P>> where P: FnMut(&T) -> bool {
+        SliceExt2::split2(self, pred);
+        loop {}
+    }
+}
+
+fn main() { }
diff --git a/src/test/run-pass/associated-types-normalize-in-bounds.rs b/src/test/run-pass/associated-types-normalize-in-bounds.rs
new file mode 100644
index 00000000000..f09c27029d7
--- /dev/null
+++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs
@@ -0,0 +1,41 @@
+// 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 we normalize associated types that appear in bounds; if
+// we didn't, the call to `self.split2()` fails to type check.
+
+#![feature(associated_types)]
+
+struct Splits<'a, T, P>;
+struct SplitsN<I>;
+
+trait SliceExt2 for Sized? {
+    type Item;
+
+    fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P>
+        where P: FnMut(&Self::Item) -> bool;
+    fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, Self::Item, P>>
+        where P: FnMut(&Self::Item) -> bool;
+}
+
+impl<T> SliceExt2 for [T] {
+    type Item = T;
+
+    fn split2<P>(&self, pred: P) -> Splits<T, P> where P: FnMut(&T) -> bool {
+        loop {}
+    }
+
+    fn splitn2<P>(&self, n: uint, pred: P) -> SplitsN<Splits<T, P>> where P: FnMut(&T) -> bool {
+        self.split2(pred);
+        loop {}
+    }
+}
+
+fn main() { }
diff --git a/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs
new file mode 100644
index 00000000000..83686d92a7c
--- /dev/null
+++ b/src/test/run-pass/associated-types-projection-bound-in-supertraits.rs
@@ -0,0 +1,33 @@
+// 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 we correctly handle projection bounds appearing in the
+// supertrait list (and in conjunction with overloaded operators). In
+// this case, the `Result=Self` binding in the supertrait listing of
+// `Int` was being ignored.
+
+#![feature(associated_types)]
+
+trait Not {
+    type Result;
+
+    fn not(self) -> Self::Result;
+}
+
+trait Int: Not<Result=Self> {
+    fn count_ones(self) -> uint;
+    fn count_zeros(self) -> uint {
+        // neither works
+        let x: Self = self.not();
+        0
+    }
+}
+
+fn main() { }
diff --git a/src/test/run-pass/assoc-eq.rs b/src/test/run-pass/associated-types-return.rs
index f1ba382b42d..d8e277510ed 100644
--- a/src/test/run-pass/assoc-eq.rs
+++ b/src/test/run-pass/associated-types-return.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test equality constraints on associated types.
+// Test equality constraints on associated types in a where clause.
 
 #![feature(associated_types)]
 
@@ -17,16 +17,19 @@ pub trait Foo {
     fn boo(&self) -> <Self as Foo>::A;
 }
 
+#[deriving(PartialEq)]
 struct Bar;
 
 impl Foo for int {
     type A = uint;
     fn boo(&self) -> uint { 42 }
 }
+
 impl Foo for Bar {
     type A = int;
     fn boo(&self) -> int { 43 }
 }
+
 impl Foo for char {
     type A = Bar;
     fn boo(&self) -> Bar { Bar }
@@ -35,12 +38,10 @@ impl Foo for char {
 fn foo1<I: Foo<A=Bar>>(x: I) -> Bar {
     x.boo()
 }
+
 fn foo2<I: Foo>(x: I) -> <I as Foo>::A {
     x.boo()
 }
-fn baz(x: &Foo<A=Bar>) -> Bar {
-    x.boo()
-}
 
 pub fn main() {
     let a = 42i;
@@ -51,5 +52,5 @@ pub fn main() {
 
     let a = 'a';
     foo1(a);
-    baz(&a);
+    assert!(foo2(a) == Bar);
 }
diff --git a/src/test/run-pass/assoc-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs
index 28c06f51ceb..28c06f51ceb 100644
--- a/src/test/run-pass/assoc-sugar-path.rs
+++ b/src/test/run-pass/associated-types-sugar-path.rs
diff --git a/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
new file mode 100644
index 00000000000..062d37556ec
--- /dev/null
+++ b/src/test/run-pass/associated-types-where-clause-impl-ambiguity.rs
@@ -0,0 +1,54 @@
+// 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 how resolving a projection interacts with inference.  In this
+// case, we were eagerly unifying the type variable for the iterator
+// type with `I` from the where clause, ignoring the in-scope `impl`
+// for `ByRef`. The right answer was to consider the result ambiguous
+// until more type information was available.
+
+// ignore-pretty -- FIXME(#17362) pretty prints with `<<` which lexes wrong
+
+#![feature(associated_types, lang_items, unboxed_closures)]
+#![no_implicit_prelude]
+
+use std::option::Option::{None, Some, mod};
+
+trait Iterator {
+    type Item;
+
+    fn next(&mut self) -> Option<Self::Item>;
+}
+
+trait IteratorExt: Iterator {
+    fn by_ref(&mut self) -> ByRef<Self> {
+        ByRef(self)
+    }
+}
+
+impl<I> IteratorExt for I where I: Iterator {}
+
+struct ByRef<'a, I: 'a + Iterator>(&'a mut I);
+
+impl<'a, A, I> Iterator for ByRef<'a, I> where I: Iterator<Item=A> {
+    type Item = A;
+
+    fn next(&mut self) -> Option< <I as Iterator>::Item > {
+        self.0.next()
+    }
+}
+
+fn is_iterator_of<A, I: Iterator<Item=A>>(_: &I) {}
+
+fn test<A, I: Iterator<Item=A>>(mut it: I) {
+    is_iterator_of::<A, _>(&it.by_ref());
+}
+
+fn main() { }
diff --git a/src/test/run-pass/dst-raw.rs b/src/test/run-pass/dst-raw.rs
index 19af9fd7ea7..d3d2e3581aa 100644
--- a/src/test/run-pass/dst-raw.rs
+++ b/src/test/run-pass/dst-raw.rs
@@ -23,7 +23,7 @@ impl Trait for A {
     }
 }
 
-struct Foo<Sized? T> {
+struct Foo<T: ?Sized> {
     f: T
 }
 
diff --git a/src/test/run-pass/dst-struct-sole.rs b/src/test/run-pass/dst-struct-sole.rs
index 26cb27cc653..47547bb7e5a 100644
--- a/src/test/run-pass/dst-struct-sole.rs
+++ b/src/test/run-pass/dst-struct-sole.rs
@@ -10,7 +10,7 @@
 
 // As dst-struct.rs, but the unsized field is the only field in the struct.
 
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
     ptr: T
 }
 
diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs
index 3644ca81d56..fb536904ac8 100644
--- a/src/test/run-pass/dst-struct.rs
+++ b/src/test/run-pass/dst-struct.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
     f1: int,
     f2: &'static str,
     ptr: T
diff --git a/src/test/run-pass/dst-trait.rs b/src/test/run-pass/dst-trait.rs
index 907c7810736..abe55d78ac6 100644
--- a/src/test/run-pass/dst-trait.rs
+++ b/src/test/run-pass/dst-trait.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct Fat<Sized? T> {
+struct Fat<T: ?Sized> {
     f1: int,
     f2: &'static str,
     ptr: T
diff --git a/src/test/run-pass/enum-null-pointer-opt.rs b/src/test/run-pass/enum-null-pointer-opt.rs
index d8d74c8bb45..34ff0b3821c 100644
--- a/src/test/run-pass/enum-null-pointer-opt.rs
+++ b/src/test/run-pass/enum-null-pointer-opt.rs
@@ -54,7 +54,7 @@ fn main() {
     // and tuples
     assert_eq!(size_of::<(u8, Box<int>)>(), size_of::<Option<(u8, Box<int>)>>());
     // and fixed-size arrays
-    assert_eq!(size_of::<[Box<int>, ..1]>(), size_of::<Option<[Box<int>, ..1]>>());
+    assert_eq!(size_of::<[Box<int>; 1]>(), size_of::<Option<[Box<int>; 1]>>());
 
     // Should apply to NonZero
     assert_eq!(size_of::<NonZero<uint>>(), size_of::<Option<NonZero<uint>>>());
diff --git a/src/test/run-pass/foreach-external-iterators-break.rs b/src/test/run-pass/foreach-external-iterators-break.rs
index d9d3e320260..5f7770e97a9 100644
--- a/src/test/run-pass/foreach-external-iterators-break.rs
+++ b/src/test/run-pass/foreach-external-iterators-break.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub fn main() {
-    let x = [1i,..100];
+    let x = [1i; 100];
     let mut y = 0i;
     for i in x.iter() {
         if y > 10 {
diff --git a/src/test/run-pass/foreach-external-iterators-loop.rs b/src/test/run-pass/foreach-external-iterators-loop.rs
index c6c2d423927..d8c6dd6a93d 100644
--- a/src/test/run-pass/foreach-external-iterators-loop.rs
+++ b/src/test/run-pass/foreach-external-iterators-loop.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub fn main() {
-    let x = [1i,..100];
+    let x = [1i; 100];
     let mut y = 0i;
     for (n,i) in x.iter().enumerate() {
         if n < 10 {
diff --git a/src/test/run-pass/foreach-external-iterators-nested.rs b/src/test/run-pass/foreach-external-iterators-nested.rs
index f4d38dfcfc3..20ea9c440a1 100644
--- a/src/test/run-pass/foreach-external-iterators-nested.rs
+++ b/src/test/run-pass/foreach-external-iterators-nested.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 pub fn main() {
-    let x = [1i,..100];
-    let y = [2i,..100];
+    let x = [1i; 100];
+    let y = [2i; 100];
     let mut p = 0i;
     let mut q = 0i;
     for i in x.iter() {
diff --git a/src/test/run-pass/foreach-external-iterators.rs b/src/test/run-pass/foreach-external-iterators.rs
index 684a9b81fb2..0ac642cc449 100644
--- a/src/test/run-pass/foreach-external-iterators.rs
+++ b/src/test/run-pass/foreach-external-iterators.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub fn main() {
-    let x = [1i,..100];
+    let x = [1i; 100];
     let mut y = 0i;
     for i in x.iter() {
         y += *i
diff --git a/src/test/run-pass/inconsistent-lifetime-mismatch.rs b/src/test/run-pass/inconsistent-lifetime-mismatch.rs
new file mode 100644
index 00000000000..b30583c6668
--- /dev/null
+++ b/src/test/run-pass/inconsistent-lifetime-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.
+
+fn foo(_: &[&str]) {}
+
+fn bad(a: &str, b: &str) {
+    foo(&[a, b]);
+}
+
+fn good(a: &str, b: &str) {
+    foo(&[a.as_slice(), b.as_slice()]);
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/integer-literal-suffix-inference-2.rs b/src/test/run-pass/integer-literal-suffix-inference-2.rs
index 7c862d04d20..05973a545a2 100644
--- a/src/test/compile-fail/integer-literal-suffix-inference-2.rs
+++ b/src/test/run-pass/integer-literal-suffix-inference-2.rs
@@ -11,7 +11,7 @@
 fn foo(_: *const ()) {}
 
 fn main() {
-    let a = 3;  //~ ERROR cannot determine a type for this local variable
+    let a = 3;
     foo(&a as *const _ as *const ());
 }
 
diff --git a/src/test/compile-fail/integer-literal-suffix-inference-3.rs b/src/test/run-pass/integer-literal-suffix-inference-3.rs
index dc3db985660..05b275a0d8c 100644
--- a/src/test/compile-fail/integer-literal-suffix-inference-3.rs
+++ b/src/test/run-pass/integer-literal-suffix-inference-3.rs
@@ -10,6 +10,5 @@
 
 fn main() {
     println!("{}", std::mem::size_of_val(&1));
-    //~^ ERROR cannot determine a type for this expression
 }
 
diff --git a/src/test/compile-fail/issue-11382.rs b/src/test/run-pass/issue-11382.rs
index 44f6cd7719d..51996614d25 100644
--- a/src/test/compile-fail/issue-11382.rs
+++ b/src/test/run-pass/issue-11382.rs
@@ -9,8 +9,5 @@
 // except according to those terms.
 
 fn main() {
-panic!(
-    1.2
-//~^ ERROR cannot determine the type of this number; add a suffix to specify the type explicitly
-);
+    println!("{}", 1.2);
 }
diff --git a/src/test/run-pass/issue-12684.rs b/src/test/run-pass/issue-12684.rs
index e24cf5a0f26..856fbbd00b2 100644
--- a/src/test/run-pass/issue-12684.rs
+++ b/src/test/run-pass/issue-12684.rs
@@ -9,9 +9,10 @@
 // except according to those terms.
 
 use std::time::Duration;
+use std::thread::Thread;
 
 fn main() {
-    std::task::spawn(move|| customtask());
+    Thread::spawn(move|| customtask()).join().ok().unwrap();
 }
 
 fn customtask() {
diff --git a/src/test/run-pass/multidispatch-infer-from-single-impl.rs b/src/test/run-pass/issue-13655.rs
index f4ca67548fd..6fdaac99204 100644
--- a/src/test/run-pass/multidispatch-infer-from-single-impl.rs
+++ b/src/test/run-pass/issue-13655.rs
@@ -8,25 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that we correctly infer that `E` must be `()` here.  This is
-// known because there is just one impl that could apply where
-// `Self=()`.
+#![feature(unboxed_closures)]
+use std::ops::Fn;
 
-pub trait FromError<E> {
-    fn from_error(err: E) -> Self;
-}
+struct Foo<T>(T);
 
-impl<E> FromError<E> for E {
-    fn from_error(err: E) -> E {
-        err
+impl<T: Copy> Fn<(), T> for Foo<T> {
+    extern "rust-call" fn call(&self, _: ()) -> T {
+      match *self {
+        Foo(t) => t
+      }
     }
 }
 
-fn test() -> Result<(), ()> {
-    Err(FromError::from_error(()))
-}
-
 fn main() {
-    let result = (|| Err(FromError::from_error(())))();
-    let foo: () = result.unwrap_or(());
+  let t: u8 = 1;
+  println!("{}", Foo(t)());
 }
diff --git a/src/test/run-pass/issue-13665.rs b/src/test/run-pass/issue-13665.rs
new file mode 100644
index 00000000000..5ccbe9a7980
--- /dev/null
+++ b/src/test/run-pass/issue-13665.rs
@@ -0,0 +1,22 @@
+// 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.
+
+fn foo<'r>() {
+  let maybe_value_ref: Option<&'r u8> = None;
+
+  let _ = maybe_value_ref.map(|& ref v| v);
+  let _ = maybe_value_ref.map(|& ref v| -> &'r u8 {v});
+  let _ = maybe_value_ref.map(|& ref v: &'r u8| -> &'r u8 {v});
+  let _ = maybe_value_ref.map(|& ref v: &'r u8| {v});
+}
+
+fn main() {
+  foo();
+}
diff --git a/src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs b/src/test/run-pass/issue-13808.rs
index c10029791df..e20090adcf6 100644
--- a/src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs
+++ b/src/test/run-pass/issue-13808.rs
@@ -8,28 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that if there is one impl we can infer everything.
-
-use std::mem;
-
-trait Convert<Target> {
-    fn convert(&self) -> Target;
+struct Foo<'a> {
+    listener: ||: 'a
 }
 
-impl Convert<u32> for i16 {
-    fn convert(&self) -> u32 {
-        *self as u32
+impl<'a> Foo<'a> {
+    fn new(listener: ||: 'a) -> Foo<'a> {
+        Foo { listener: listener }
     }
 }
 
-fn test<T,U>(_: T, _: U, t_size: uint, u_size: uint)
-where T : Convert<U>
-{
-    assert_eq!(mem::size_of::<T>(), t_size);
-    assert_eq!(mem::size_of::<U>(), u_size);
-}
-
 fn main() {
-    // T = i16, U = u32
-    test(22, 44,  2, 4);
+    let a = Foo::new(|| {});
 }
diff --git a/src/test/run-pass/issue-15155.rs b/src/test/run-pass/issue-15155.rs
index 053a4916e22..3a63e63355c 100644
--- a/src/test/run-pass/issue-15155.rs
+++ b/src/test/run-pass/issue-15155.rs
@@ -22,7 +22,7 @@ struct IndirectBlah { x: Box<IndirectTraitWithSend> }
 impl TraitWithSend for IndirectBlah {}
 impl IndirectTraitWithSend for IndirectBlah {}
 
-fn test_trait<Sized? T: Send>() { println!("got here!") }
+fn test_trait<T: Send + ?Sized>() { println!("got here!") }
 
 fn main() {
     test_trait::<TraitWithSend>();
diff --git a/src/test/compile-fail/issue-15730.rs b/src/test/run-pass/issue-15730.rs
index c29e74af03c..a1a5922e150 100644
--- a/src/test/compile-fail/issue-15730.rs
+++ b/src/test/run-pass/issue-15730.rs
@@ -12,6 +12,5 @@
 
 fn main() {
     let mut array = [1, 2, 3];
-//~^ ERROR cannot determine a type for this local variable: cannot determine the type of this integ
     let pie_slice = array[1..2];
 }
diff --git a/src/test/compile-fail/issue-16783.rs b/src/test/run-pass/issue-16783.rs
index 1b52bd9c3de..cb12d138a5f 100644
--- a/src/test/compile-fail/issue-16783.rs
+++ b/src/test/run-pass/issue-16783.rs
@@ -10,6 +10,5 @@
 
 pub fn main() {
     let x = [1, 2, 3];
-    //~^ ERROR cannot determine a type for this local variable: cannot determine the type of this
     let y = x.as_slice();
 }
diff --git a/src/test/run-pass/issue-17361.rs b/src/test/run-pass/issue-17361.rs
index fa38dcc1986..092bcf661a7 100644
--- a/src/test/run-pass/issue-17361.rs
+++ b/src/test/run-pass/issue-17361.rs
@@ -11,6 +11,6 @@
 // Test that astconv doesn't forget about mutability of &mut str
 
 fn main() {
-    fn foo<Sized? T>(_: &mut T) {}
+    fn foo<T: ?Sized>(_: &mut T) {}
     let _f: fn(&mut str) = foo;
 }
diff --git a/src/test/run-pass/issue-18906.rs b/src/test/run-pass/issue-18906.rs
new file mode 100644
index 00000000000..e82359bc168
--- /dev/null
+++ b/src/test/run-pass/issue-18906.rs
@@ -0,0 +1,36 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Borrow<Sized? Borrowed> {
+        fn borrow(&self) -> &Borrowed;
+}
+
+impl<T: Sized> Borrow<T> for T {
+        fn borrow(&self) -> &T { self }
+}
+
+trait Foo {
+        fn foo(&self, other: &Self);
+}
+
+fn bar<K, Q>(k: &K, q: &Q) where K: Borrow<Q>, Q: Foo {
+    q.foo(k.borrow())
+}
+
+struct MyTree<K>;
+
+impl<K> MyTree<K> {
+    // This caused a failure in #18906
+    fn bar<Q>(k: &K, q: &Q) where K: Borrow<Q>, Q: Foo {
+        q.foo(k.borrow())
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-19081.rs b/src/test/run-pass/issue-19081.rs
index 613ec8acd41..57724ba91b0 100644
--- a/src/test/compile-fail/issue-19081.rs
+++ b/src/test/run-pass/issue-19081.rs
@@ -8,17 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-pretty -- FIXME(#17362) pretty prints as `Hash<<Self as Hasher...` which fails to parse
+
 #![feature(associated_types)]
 
-pub trait Hasher{
+pub trait Hasher {
     type State;
 
     fn hash<T: Hash<
-        <Self as Hasher>::State //~ ERROR no suitable bound on `Self`
+        <Self as Hasher>::State
     >>(&self, value: &T) -> u64;
 }
 
-trait Hash<S> {
+pub trait Hash<S> {
     fn hash(&self, state: &mut S);
 }
 
diff --git a/src/test/compile-fail/issue-19121.rs b/src/test/run-pass/issue-19121.rs
index 998c6a82535..79afb856be2 100644
--- a/src/test/compile-fail/issue-19121.rs
+++ b/src/test/run-pass/issue-19121.rs
@@ -17,6 +17,8 @@ trait Foo {
     type A;
 }
 
-fn bar(x: &Foo) {} //~ERROR missing type for associated type `A`
+fn bar(x: &Foo) {}
+// FIXME(#19482) -- `Foo` should specify `A`, but this is not
+// currently enforced except at object creation
 
 pub fn main() {}
diff --git a/src/test/run-pass/issue-7663.rs b/src/test/run-pass/issue-7663.rs
index ee500b3d4fa..39b0711721b 100644
--- a/src/test/run-pass/issue-7663.rs
+++ b/src/test/run-pass/issue-7663.rs
@@ -17,8 +17,7 @@ mod test1 {
     mod bar { pub fn p() -> int { 2 } }
 
     pub mod baz {
-        use test1::foo::*;
-        use test1::bar::*;
+        use test1::bar::p;
 
         pub fn my_main() { assert!(p() == 2); }
     }
@@ -36,20 +35,7 @@ mod test2 {
     }
 }
 
-mod test3 {
-
-    mod foo { pub fn p() -> int { 1 } }
-    mod bar { pub fn p() -> int { 2 } }
-
-    pub mod baz {
-        use test3::bar::p;
-
-        pub fn my_main() { assert!(p() == 2); }
-    }
-}
-
 fn main() {
     test1::baz::my_main();
     test2::baz::my_main();
-    test3::baz::my_main();
 }
diff --git a/src/test/run-pass/match-ref-binding-in-guard-3256.rs b/src/test/run-pass/match-ref-binding-in-guard-3256.rs
index 9bb912e081c..a83bc73457e 100644
--- a/src/test/run-pass/match-ref-binding-in-guard-3256.rs
+++ b/src/test/run-pass/match-ref-binding-in-guard-3256.rs
@@ -11,13 +11,11 @@
 use std::sync::Mutex;
 
 pub fn main() {
-    unsafe {
-        let x = Some(Mutex::new(true));
-        match x {
-            Some(ref z) if *z.lock() => {
-                assert!(*z.lock());
-            },
-            _ => panic!()
-        }
+    let x = Some(Mutex::new(true));
+    match x {
+        Some(ref z) if *z.lock().unwrap() => {
+            assert!(*z.lock().unwrap());
+        },
+        _ => panic!()
     }
 }
diff --git a/src/test/run-pass/method-recursive-blanket-impl.rs b/src/test/run-pass/method-recursive-blanket-impl.rs
index b45faca2de6..4e4fb75b428 100644
--- a/src/test/run-pass/method-recursive-blanket-impl.rs
+++ b/src/test/run-pass/method-recursive-blanket-impl.rs
@@ -16,7 +16,7 @@
 use std::kinds::Sized;
 
 // Note: this must be generic for the problem to show up
-trait Foo<A> for Sized? {
+trait Foo<A> for ?Sized {
     fn foo(&self);
 }
 
diff --git a/src/test/run-pass/range.rs b/src/test/run-pass/range.rs
index 027121dd422..43b6d4b3109 100644
--- a/src/test/run-pass/range.rs
+++ b/src/test/run-pass/range.rs
@@ -10,6 +10,8 @@
 
 // Test range syntax.
 
+#![feature(slicing_syntax)]
+
 fn foo() -> int { 42 }
 
 pub fn main() {
@@ -39,6 +41,8 @@ pub fn main() {
     let _ = 0u..4+4-3;
     let _ = 0..foo();
 
+    let _ = ..42u;
+
     // Test we can use two different types with a common supertype.
     let x = &42i;
     {
diff --git a/src/test/run-pass/tcp-connect-timeouts.rs b/src/test/run-pass/tcp-connect-timeouts.rs
index c33bdcf8698..38a762d5803 100644
--- a/src/test/run-pass/tcp-connect-timeouts.rs
+++ b/src/test/run-pass/tcp-connect-timeouts.rs
@@ -23,7 +23,6 @@
 #![allow(unused_imports)]
 
 use std::io::*;
-use std::io::net::tcp::*;
 use std::io::test::*;
 use std::io;
 use std::time::Duration;
diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs
index b3391669d35..7a061f5b99c 100644
--- a/src/test/run-pass/tcp-stress.rs
+++ b/src/test/run-pass/tcp-stress.rs
@@ -17,22 +17,23 @@
 extern crate log;
 extern crate libc;
 
+use std::comm::channel;
 use std::io::net::tcp::{TcpListener, TcpStream};
 use std::io::{Acceptor, Listener};
-use std::thread::Builder;
+use std::thread::{Builder, Thread};
 use std::time::Duration;
 
 fn main() {
     // This test has a chance to time out, try to not let it time out
-    spawn(move|| {
+    Thread::spawn(move|| -> () {
         use std::io::timer;
         timer::sleep(Duration::milliseconds(30 * 1000));
         println!("timed out!");
         unsafe { libc::exit(1) }
-    });
+    }).detach();
 
     let (tx, rx) = channel();
-    spawn(move|| {
+    Thread::spawn(move || -> () {
         let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
         tx.send(listener.socket_name().unwrap());
         let mut acceptor = listener.listen();
@@ -47,7 +48,7 @@ fn main() {
             stream.read_byte();
             stream.write(&[2]);
         }
-    });
+    }).detach();
     let addr = rx.recv();
 
     let (tx, rx) = channel();
diff --git a/src/test/run-pass/trait-object-safety.rs b/src/test/run-pass/trait-object-safety.rs
index 929cb9e7f17..ed7284a8353 100644
--- a/src/test/run-pass/trait-object-safety.rs
+++ b/src/test/run-pass/trait-object-safety.rs
@@ -8,20 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that object-safe methods are identified as such.  Also
-// acts as a regression test for #18490
+// Check that object-safe methods are identified as such.
 
 trait Tr {
-    // Static methods are always safe regardless of other rules
-    fn new() -> Self;
+    fn foo(&self);
 }
 
 struct St;
 
 impl Tr for St {
-    fn new() -> St { St }
+    fn foo(&self) {}
 }
 
 fn main() {
-    &St as &Tr;
+    let s: &Tr = &St;
+    s.foo();
 }
diff --git a/src/test/run-pass/traits-multidispatch-infer-convert-target.rs b/src/test/run-pass/traits-multidispatch-infer-convert-target.rs
index 54515f3b0d7..532ef7cbec6 100644
--- a/src/test/run-pass/traits-multidispatch-infer-convert-target.rs
+++ b/src/test/run-pass/traits-multidispatch-infer-convert-target.rs
@@ -36,11 +36,10 @@ where T : Convert<U>
 }
 
 fn main() {
+    use std::default::Default;
     // T = i16, U = u32
-    test(22_i16, 44,  2, 4);
-    test(22, 44_u32, 2, 4);
+    test(22_i16, Default::default(),  2, 4);
 
     // T = u32, U = i16
-    test(22_u32, 44, 4, 2);
-    test(22, 44_i16, 4, 2);
+    test(22_u32, Default::default(), 4, 2);
 }
diff --git a/src/test/run-pass/transmute-non-immediate-to-immediate.rs b/src/test/run-pass/transmute-non-immediate-to-immediate.rs
index e070757eaf4..70a41f773a3 100644
--- a/src/test/run-pass/transmute-non-immediate-to-immediate.rs
+++ b/src/test/run-pass/transmute-non-immediate-to-immediate.rs
@@ -13,6 +13,6 @@
 
 pub fn main() {
     unsafe {
-        ::std::mem::transmute::<[int,..1],int>([1])
+        ::std::mem::transmute::<[int; 1],int>([1])
     };
 }
diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs
index 7c007cf9d33..961a4472bd4 100644
--- a/src/test/run-pass/type-sizes.rs
+++ b/src/test/run-pass/type-sizes.rs
@@ -26,7 +26,7 @@ enum e2 {
 }
 
 enum e3 {
-    a([u16, ..0], u8), b
+    a([u16; 0], u8), b
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs
index 141d6c88dd9..07b9fac6655 100644
--- a/src/test/run-pass/unsized.rs
+++ b/src/test/run-pass/unsized.rs
@@ -10,21 +10,22 @@
 //
 // ignore-lexer-test FIXME #15879
 
-// Test syntax checks for `Sized?` syntax.
+// Test syntax checks for `?Sized` syntax.
 
-trait T1 for Sized? {}
-pub trait T2 for Sized? {}
-trait T3<X: T1> for Sized?: T2 {}
-trait T4<Sized? X> {}
-trait T5<Sized? X, Y> {}
-trait T6<Y, Sized? X> {}
-trait T7<Sized? X, Sized? Y> {}
-trait T8<Sized? X: T2> {}
-struct S1<Sized? X>;
-enum E<Sized? X> {}
-impl <Sized? X> T1 for S1<X> {}
-fn f<Sized? X>() {}
-type TT<Sized? T> = T;
+trait T1 for ?Sized {}
+pub trait T2 for ?Sized {}
+trait T3<X: T1> for ?Sized: T2 {}
+trait T4<X: ?Sized> {}
+trait T5<X: ?Sized, Y> {}
+trait T6<Y, X: ?Sized> {}
+trait T7<X: ?Sized, Y: ?Sized> {}
+trait T8<X: ?Sized+T2> {}
+trait T9<X: T2 + ?Sized> {}
+struct S1<X: ?Sized>;
+enum E<X: ?Sized> {}
+impl <X: ?Sized> T1 for S1<X> {}
+fn f<X: ?Sized>() {}
+type TT<T: ?Sized> = T;
 
 pub fn main() {
 }
diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs
index d28d47c0cfb..8d2c99d4414 100644
--- a/src/test/run-pass/unsized2.rs
+++ b/src/test/run-pass/unsized2.rs
@@ -13,7 +13,7 @@
 // Test sized-ness checking in substitution.
 
 // Unbounded.
-fn f1<Sized? X>(x: &X) {
+fn f1<X: ?Sized>(x: &X) {
     f1::<X>(x);
 }
 fn f2<X>(x: &X) {
@@ -22,8 +22,8 @@ fn f2<X>(x: &X) {
 }
 
 // Bounded.
-trait T for Sized? {}
-fn f3<Sized? X: T>(x: &X) {
+trait T for ?Sized {}
+fn f3<X: T+?Sized>(x: &X) {
     f3::<X>(x);
 }
 fn f4<X: T>(x: &X) {
@@ -32,7 +32,7 @@ fn f4<X: T>(x: &X) {
 }
 
 // Self type.
-trait T2 for Sized? {
+trait T2 for ?Sized {
     fn f() -> Box<Self>;
 }
 struct S;
@@ -41,14 +41,14 @@ impl T2 for S {
         box S
     }
 }
-fn f5<Sized? X: T2>(x: &X) {
+fn f5<X: ?Sized+T2>(x: &X) {
     let _: Box<X> = T2::f();
 }
 fn f6<X: T2>(x: &X) {
     let _: Box<X> = T2::f();
 }
 
-trait T3 for Sized? {
+trait T3 for ?Sized {
     fn f() -> Box<Self>;
 }
 impl T3 for S {
@@ -56,7 +56,7 @@ impl T3 for S {
         box S
     }
 }
-fn f7<Sized? X: T3>(x: &X) {
+fn f7<X: ?Sized+T3>(x: &X) {
     // This is valid, but the unsized bound on X is irrelevant because any type
     // which implements T3 must have statically known size.
     let _: Box<X> = T3::f();
@@ -66,7 +66,7 @@ trait T4<X> {
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
 }
-trait T5<Sized? X> {
+trait T5<X: ?Sized> {
     // not an error (for now)
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
@@ -76,21 +76,21 @@ trait T6<X: T> {
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
 }
-trait T7<Sized? X: T> {
+trait T7<X: ?Sized+T> {
     // not an error (for now)
     fn m1(x: &T4<X>);
     fn m2(x: &T5<X>);
 }
 
 // The last field in a struct or variant may be unsized
-struct S2<Sized? X> {
+struct S2<X: ?Sized> {
     f: X,
 }
-struct S3<Sized? X> {
+struct S3<X: ?Sized> {
     f1: int,
     f2: X,
 }
-enum E<Sized? X> {
+enum E<X: ?Sized> {
     V1(X),
     V2{x: X},
     V3(int, X),
diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs
index fe89c7532ee..6ff1cffb4a4 100644
--- a/src/test/run-pass/vector-sort-panic-safe.rs
+++ b/src/test/run-pass/vector-sort-panic-safe.rs
@@ -10,7 +10,7 @@
 
 use std::task;
 use std::sync::atomic::{AtomicUint, INIT_ATOMIC_UINT, Relaxed};
-use std::rand::{task_rng, Rng, Rand};
+use std::rand::{thread_rng, Rng, Rand};
 
 const REPEATS: uint = 5;
 const MAX_LEN: uint = 32;
@@ -59,7 +59,7 @@ pub fn main() {
             // IDs start from 0.
             creation_count.store(0, Relaxed);
 
-            let main = task_rng().gen_iter::<DropCounter>()
+            let main = thread_rng().gen_iter::<DropCounter>()
                                  .take(len)
                                  .collect::<Vec<DropCounter>>();
 
diff --git a/src/test/run-pass/writealias.rs b/src/test/run-pass/writealias.rs
index f48272366e2..dacfeb00819 100644
--- a/src/test/run-pass/writealias.rs
+++ b/src/test/run-pass/writealias.rs
@@ -15,13 +15,11 @@ struct Point {x: int, y: int, z: int}
 fn f(p: &mut Point) { p.z = 13; }
 
 pub fn main() {
-    unsafe {
-        let x = Some(Mutex::new(true));
-        match x {
-            Some(ref z) if *z.lock() => {
-                assert!(*z.lock());
-            },
-            _ => panic!()
-        }
+    let x = Some(Mutex::new(true));
+    match x {
+        Some(ref z) if *z.lock().unwrap() => {
+            assert!(*z.lock().unwrap());
+        },
+        _ => panic!()
     }
 }